写完上一篇日志"静态回调函数到成员函数的转换", 问了一下石教主有什么看法, 结果不问不知道, 一问才发现自己彻底土了, 这个问题用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
19
CRITICAL_SECTION cs;
20
21
struct 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
39
void 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
60
namespace LibUtil
{
61
class ThreadHelper
62

{
63
public:
64
ThreadHelper(void);
65
public:
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
189
protected:
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