写完上一篇日志"静态回调函数到成员函数的转换", 问了一下石教主有什么看法, 结果不问不知道, 一问才发现自己彻底土了, 这个问题用boost::bind可以解决得这么好, 调用的函数参数个数都可以没有限制... 唉, 以后还是要好好学习
ps. 不过不知道这个方法运行效率怎么样, 还要继续试验
// 下面的内容于2007年5月4日改成最后用的版本了
实现的功能:
(1) 用于把非多线程的代码改成多线程
(2) 普通Thread与Work Item for Thread Pool不相区别
(3) 所用的类成员函数参数个数不限(依bind参数限制来定,一般够用了)
1#pragma once
2
3#include <vector>
4#include <list>
5#include <boost/any.hpp>
6#include <boost/bind.hpp>
7#include <map>
8
9/**//************************************************************************/
10/**//* Code Sample: */
11/**//************************************************************************/
12/**//*
13
14#define _WIN32_WINNT 0x0500
15#include <windows.h>
16#include <iostream>
17#include "ThreadHelper.h"
18
19CRITICAL_SECTION cs;
20
21struct A
22{
23 int f1(int a, int b){
24 EnterCriticalSection(&cs);
25 std::cout<<a<<"+"<<b<<"="<<a+b<<"\n";
26 LeaveCriticalSection(&cs);
27 return a+b;
28 }
29
30 HANDLE ExecuteInThread(int i, int j){
31 return ThreadHelper::CreateThread(boost::bind(&A::f1, this, i, j));
32 }
33
34 HANDLE ExecuteInPool(int i, int j){
35 return ThreadHelper::QueueThread(boost::bind(&A::f1, this, i, j));
36 }
37};
38
39void main()
40{
41 A a;
42 ThreadHelper::makeFlag(8, WT_EXECUTEINIOTHREAD);
43 ThreadHelper::init();
44
45 InitializeCriticalSection(&cs);
46
47 HANDLE threads[3];
48
49 threads[0] = a.ExecuteInPool(3, 4);
50 threads[1] = a.ExecuteInThread(2, 8);
51 threads[2] = ThreadHelper::QueueThread(boost::bind(&A::f1, &a, 2, 3));
52
53 WaitForMultipleObjects(3, threads, TRUE, INFINITE);
54
55 DeleteCriticalSection(&cs);
56 ThreadHelper::finalize();
57}
58*/
59
60namespace LibUtil{
61class ThreadHelper
62{
63public:
64 ThreadHelper(void);
65public:
66 ~ThreadHelper(void);
67
68 typedef std::map<HANDLE, boost::any> ThreadReturnMap;
69 typedef DWORD (*ThreadProc)(LPVOID lpParameter);
70
71 static void init()
72 {
73 InitializeCriticalSection(&m_csQueueThread_Impl);
74 InitializeCriticalSection(&m_csQueueThread);
75 InitializeCriticalSection(&m_csCreateThread);
76 }
77
78 static void finalize()
79 {
80 DeleteCriticalSection(&m_csQueueThread);
81 DeleteCriticalSection(&m_csQueueThread_Impl);
82 DeleteCriticalSection(&m_csCreateThread);
83 }
84
85 static void makeFlag(int threadLimit, ULONG flagPrefix = WT_EXECUTEDEFAULT)
86 {
87 m_flagQueue = flagPrefix;
88 WT_SET_MAX_THREADPOOL_THREADS(m_flagQueue, threadLimit);
89 }
90
91 static HANDLE CreateThread(ThreadProc pFunc, LPVOID lpvThreadParam, LPSECURITY_ATTRIBUTES lpsa = NULL, DWORD cbStack = 0, DWORD fdwCreate = 0, LPDWORD lpIDThread = NULL)
92 {
93 HANDLE hThread = ::CreateThread(lpsa, cbStack, (LPTHREAD_START_ROUTINE)pFunc, lpvThreadParam, fdwCreate, lpIDThread);
94 if(hThread)
95 m_vThreads.insert(std::make_pair(hThread, boost::any()));
96 return hThread;
97 }
98
99 template <typename T>
100 static HANDLE CreateThread(T& t, LPSECURITY_ATTRIBUTES lpsa = NULL, DWORD cbStack = 0, DWORD fdwCreate = 0, LPDWORD lpIDThread = NULL)
101 {
102 EnterCriticalSection(&m_csCreateThread);
103 static std::list<boost::any> functors;
104 functors.push_back(t);
105 T* pt = &boost::any_cast<T&>(functors.back());
106 LeaveCriticalSection(&m_csCreateThread);
107
108 HANDLE hThread = CreateThread(&deliver<T>, pt, lpsa, cbStack, fdwCreate, lpIDThread);
109 if(hThread)
110 m_vThreads.insert(std::make_pair(hThread, boost::any()));
111 return hThread;
112 }
113
114 static HANDLE QueueThread(ThreadProc pFunc, LPVOID param, ULONG flag = m_flagQueue)
115 {
116 HANDLE hThread = CreateEvent(NULL, TRUE, FALSE, NULL);
117
118 if(QueueThread_Impl(boost::bind(worker, pFunc, param, hThread), flag))
119 {
120 m_vThreads.insert(std::make_pair(hThread, boost::any()));
121 return hThread;
122 }
123 else
124 {
125 CloseHandle(hThread);
126 return NULL;
127 }
128 }
129
130 template <typename T>
131 static HANDLE QueueThread(T& t, ULONG flag = m_flagQueue)
132 {
133 EnterCriticalSection(&m_csQueueThread);
134 static std::list<boost::any> functors;
135 functors.push_back(t);
136 T* pt = &boost::any_cast<T&>(functors.back());
137 LeaveCriticalSection(&m_csQueueThread);
138
139 HANDLE hThread = CreateEvent(NULL, TRUE, FALSE, NULL);
140
141 if(QueueThread_Impl(boost::bind(&worker<T>, pt, hThread), flag))
142 {
143 m_vThreads.insert(std::make_pair(hThread, boost::any()));
144 return hThread;
145 }
146 else
147 {
148 CloseHandle(hThread);
149 return NULL;
150 }
151 }
152
153 void WaitAll(DWORD elapseTime = INFINITE)
154 {
155 std::vector<HANDLE> threads;
156 for(ThreadReturnMap::iterator it = m_vThreads.begin();
157 it != m_vThreads.end(); it ++)
158 {
159 threads.push_back(it->first);
160 }
161 WaitForMultipleObjects(threads.size(), &threads[0], TRUE, elapseTime);
162 m_vThreads.clear();
163 }
164
165 void WaitSingle(HANDLE hThread, DWORD elapseTime = INFINITE)
166 {
167 WaitForSingleObject(hThread, elapseTime);
168
169 ThreadReturnMap::iterator it = m_vThreads.find(hThread);
170 if(it != m_vThreads.end())
171 m_vThreads.erase(m_vThreads.find(hThread));
172 return;
173 }
174
175 template<typename T>
176 void WaitForReturnValue(HANDLE hThread, T& returnValue, DWORD elapseTime = INFINITE)
177 {
178 WaitForSingleObject(hThread, elapseTime);
179
180 ThreadReturnMap::iterator it = m_vThreads.find(hThread);
181 if(it != m_vThreads.end())
182 {
183 returnValue = boost::any_cast<T&>(it->second);
184 m_vThreads.erase(m_vThreads.find(hThread));
185 }
186 return;
187 }
188
189protected:
190
191 template<typename T>
192 static bool QueueThread_Impl(T& t, ULONG flag)
193 {
194 EnterCriticalSection(&m_csQueueThread_Impl);
195 static std::list<boost::any> functors;
196 functors.push_back(t);
197 T* pt = &boost::any_cast<T&>(functors.back());
198 LeaveCriticalSection(&m_csQueueThread_Impl);
199
200 return QueueThread_Impl(&deliver<T>, pt, flag);
201 }
202
203 static bool QueueThread_Impl(ThreadProc pFunc, void* param, ULONG flag)
204 {
205 return QueueUserWorkItem((LPTHREAD_START_ROUTINE)pFunc, param, flag);
206 }
207
208 template <typename T>
209 static DWORD deliver(LPVOID p)
210 {
211 (*(T*)p)();
212 return 0;
213 }
214
215 template<typename T>
216 static void worker(T* t, HANDLE hTerminate)
217 {
218 (*t)();
219 SetEvent(hTerminate);
220 return;
221 }
222
223 static void worker(ThreadProc pFunc, LPVOID t, HANDLE hTerminate)
224 {
225 pFunc(t);
226 SetEvent(hTerminate);
227 return;
228 }
229
230 static std::map<HANDLE, boost::any> m_vThreads;
231 static ULONG m_flagQueue;
232 static CRITICAL_SECTION m_csQueueThread_Impl, m_csQueueThread, m_csCreateThread;
233};
234
235
236} // namespace LibUtil
237