前言
Windows I/O完成端口(IOCP)是一个强大的异步I/O模型,不仅可以用于网络编程,还可以用来实现高效的线程池。本文将介绍如何使用IOCP实现一个简单但实用的线程池。
IOCP简介
IOCP(I/O Completion Port)是Windows提供的一个用于处理异步I/O的可扩展模型。它可以:
- 高效管理线程池
- 实现负载均衡
- 最小化线程上下文切换
实现思路
- 创建完成端口
- 创建工作线程池
- 投递任务
- 处理完成回调
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| class IOCPThreadPool { private: HANDLE m_hIOCP; std::vector<std::thread> m_threads; bool m_running;
public: IOCPThreadPool(size_t threadCount = 0) { m_running = true; m_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (threadCount == 0) { SYSTEM_INFO sysInfo; GetSystemInfo(&sysInfo); threadCount = sysInfo.dwNumberOfProcessors; }
for (size_t i = 0; i < threadCount; i++) { m_threads.emplace_back(&IOCPThreadPool::WorkerThread, this); } }
template<typename F> void EnqueueTask(F&& task) { auto taskPtr = new std::function<void()>(std::forward<F>(task)); PostQueuedCompletionStatus(m_hIOCP, 0, (ULONG_PTR)taskPtr, nullptr); }
private: void WorkerThread() { while (m_running) { DWORD bytesTransferred; ULONG_PTR completionKey; LPOVERLAPPED overlapped;
BOOL result = GetQueuedCompletionStatus( m_hIOCP, &bytesTransferred, &completionKey, &overlapped, INFINITE );
if (result && completionKey) { auto task = reinterpret_cast<std::function<void()>*>(completionKey); (*task)(); delete task; } } } };
|
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| int main() { IOCPThreadPool pool;
pool.EnqueueTask([]() { std::cout << "Task 1 executed in thread: " << std::this_thread::get_id() << std::endl; });
pool.EnqueueTask([]() { std::cout << "Task 2 executed in thread: " << std::this_thread::get_id() << std::endl; });
std::this_thread::sleep_for(std::chrono::seconds(1)); return 0; }
|
优点分析
高效的线程管理
- IOCP自动实现线程池的负载均衡
- 最小化线程上下文切换
简单易用
性能优势
注意事项
内存管理
异常处理
总结
使用IOCP实现线程池不仅可以获得良好的性能,还能充分利用Windows系统的特性。这个简单的实现可以作为更复杂线程池的基础,根据实际需求进行扩展。
参考资料:
- Windows系统编程指南
- MSDN - I/O Completion Ports
- C++并发编程实战