写完上一篇日志"静态回调函数到成员函数的转换", 问了一下石教主有什么看法, 结果不问不知道, 一问才发现自己彻底土了, 这个问题用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