POCO库 Foundation::Thread模块 多线程与线程池支持

来源:互联网 发布:阿里云视频播放器sdk 编辑:程序博客网 时间:2024/05/29 06:57

本节主要介绍Thread类和ThreadLocal机制的使用方法以及实现原理,以及对ThreadPool线程池支持的简单了解

        在C++语言中,我们通过_beginThreadex或CreateThread来创建线程(最好使用前者,关于两者区别和线程基础知识可参见《Windows核心编程》),并且提供一个原型为void MyFunc(void pParam)入口函数来完成任务。在Poco中,将入口函数抽象为一个类Runnable,该类提供void run()接口,用户需要继承至该类来实现自定义的入口函数。Poco将线程也抽象为一个类Thread,提供了start, join等方法。一个Thread使用例子如下:

[cpp] view plaincopyprint?
  1. #include "Poco/Thread.h"  
  2. #include "Poco/Runnable.h"  
  3. #include <iostream>  
  4. class HelloRunnable: public Poco::Runnable  
  5. {  
  6.     virtual void run()  
  7.     {  
  8.         std::cout << "Hello, world!" << std::endl;  
  9.     }  
  10. };  
  11. int main(int argc, char** argv)  
  12. {  
  13.     HelloRunnable runnable;  
  14.     Poco::Thread thread;  
  15.     thread.start(runnable);//传入对象而不是对象指针  
  16.     thread.join();  
  17.     return 0;  
  18. }  

    定义一个Thread对象,调用其start方法并传入一个Runnable对象来启动线程,使用的方法比较简单,另外,如果你的线程的入口函数在另一个已定义好的类中,那么Poco提供了一个适配器来使线程能够从你指定的入口启动,并且无需修改已有的类:

[cpp] view plaincopyprint?
  1. #include "Poco/Thread.h"  
  2. #include "Poco/RunnableAdapter.h"  
  3. #include <iostream>  
  4. class Greeter  
  5. {  
  6. public:  
  7.     void greet()  
  8.    {  
  9.        std::cout << "Hello, world!" << std::endl;  
  10.    }  
  11. };  
  12. int main(int argc, char** argv)  
  13. {  
  14.     Greeter greeter;  
  15.     Poco::RunnableAdapter<Greeter> runnable(greeter, &Greeter::greet);  
  16.     Poco::Thread thread;  
  17.     thread.start(runnable);  
  18.     thread.join();//等待该线程技术  
  19.     return 0;  
  20. }  

看完了其使用方法之后,我们来查看其内部实现。


   Thread和Runnable如何工作

先看看thread.start是怎么启动一个新线程的:

在Poco-1.4.6/Foundation/src/Thread_WIN32中找到start的实现startImpl:

[cpp] view plaincopyprint?
  1. void ThreadImpl::startImpl(Runnable& target)  
  2. {  
  3.     if (isRunningImpl())  
  4.         throw SystemException("thread already running");  
  5.   
  6.     _pRunnableTarget = ⌖ //记录入口  
  7.   
  8.     createImpl(runnableEntry, this);  
  9. }  

    该函数先判断线程是否正在运行,然后将Runnable对象指针存入成员_pRunnableTarget中,之后调用createImpl函数,并传入runnableEntry函数地址和this指针

[cpp] view plaincopyprint?
  1. void ThreadImpl::createImpl(Entry ent, void* pData)  
  2. {  
  3. #if defined(_DLL)  
  4.     _thread = CreateThread(NULL, _stackSize, ent, pData, 0, &_threadId);  
  5. #else  
  6.     unsigned threadId;  
  7.     _thread = (HANDLE) _beginthreadex(NULL, _stackSize, ent, this, 0, &threadId);  
  8.     _threadId = static_cast<DWORD>(threadId);  
  9. #endif  
  10.     if (!_thread)  
  11.         throw SystemException("cannot create thread");  
  12.     if (_prio != PRIO_NORMAL_IMPL && !SetThreadPriority(_thread, _prio))  
  13.         throw SystemException("cannot set thread priority");  
  14. }  


    其中Entry ent参数也就是runnableEntry函数代码如下:

[cpp] view plaincopyprint?
  1. #if defined(_DLL)  
  2. DWORD WINAPI ThreadImpl::runnableEntry(LPVOID pThread)  
  3. #else  
  4. unsigned __stdcall ThreadImpl::runnableEntry(void* pThread)  
  5. #endif  
  6. {  
  7.     _currentThreadHolder.set(reinterpret_cast<ThreadImpl*>(pThread));  
  8. #if defined(_DEBUG) && defined(POCO_WIN32_DEBUGGER_THREAD_NAMES)  
  9.     setThreadName(-1, reinterpret_cast<Thread*>(pThread)->getName().c_str());  
  10. #endif  
  11.     try  
  12.     {  
  13.         reinterpret_cast<ThreadImpl*>(pThread)->_pRunnableTarget->run();  
  14.     }  
  15.     catch (Exception& exc)  
  16.     {  
  17.         ErrorHandler::handle(exc);  
  18.     }  
  19.     catch (std::exception& exc)  
  20.     {  
  21.         ErrorHandler::handle(exc);  
  22.     }  
  23.     catch (...)  
  24.     {  
  25.         ErrorHandler::handle();  
  26.     }  
  27.     return 0;  
  28. }  


    可以看出,createImpl负责创建线程,并且把入口函数runnableEntry作为线程入口,将this指针作为参数。在runnableEntry中,首先将pThread也就是代表该线程的Threal对象地址放入_currentThreadHolder中,static CurrentThreadHolder _currentThreadHolder;是一个静态数据成员,它的存在是为了方便程序在任何环境下通过Thread::current来获取当前运行线程所属的Thread对象指针。CurrentThreadHolder是ThreadImpl的一个内嵌类,它通过线程的TLS机制将线程的Thread指针放入TLS数组的某个槽中(_slot),并提供存取(set)和获取(get)方法,源码如下:

[cpp] view plaincopyprint?
  1. class CurrentThreadHolder  
  2. {  
  3.     public:  
  4.         CurrentThreadHolder(): _slot(TlsAlloc())  
  5.         {  
  6.             if (_slot == TLS_OUT_OF_INDEXES)  
  7.                 throw SystemException("cannot allocate thread context key");  
  8.         }  
  9.         ~CurrentThreadHolder()  
  10.         {  
  11.             TlsFree(_slot);  
  12.         }  
  13.         ThreadImpl* get() const  
  14.         {  
  15.             return reinterpret_cast<ThreadImpl*>(TlsGetValue(_slot));  
  16.         }  
  17.         void set(ThreadImpl* pThread)  
  18.         {  
  19.             TlsSetValue(_slot, pThread);  
  20.         }  
  21.       
  22.     private:  
  23.         DWORD _slot;  
  24. };  


runnableEntry在通过_currentThreadHolder存取了Thread指针之后,便开始调用用户在Runnable类中定义的run函数。

ThreadImpl类还提供了一系列线程相关的方法:

[cpp] view plaincopyprint?
  1. void ThreadImpl::joinImpl()  
  2. {  
  3.     if (!_thread) return;  
  4.   
  5.     switch (WaitForSingleObject(_thread, INFINITE))  
  6.     {  
  7.     case WAIT_OBJECT_0:  
  8.         threadCleanup();  
  9.         return;  
  10.     default:  
  11.         throw SystemException("cannot join thread");  
  12.     }  
  13. }  
  14.   
  15.   
  16. bool ThreadImpl::joinImpl(long milliseconds)  
  17. {  
  18.     if (!_thread) return true;  
  19.   
  20.     switch (WaitForSingleObject(_thread, milliseconds + 1))  
  21.     {  
  22.     case WAIT_TIMEOUT:  
  23.         return false;  
  24.     case WAIT_OBJECT_0:  
  25.         threadCleanup();  
  26.         return true;  
  27.     default:  
  28.         throw SystemException("cannot join thread");  
  29.     }  
  30. }  
  31.   
  32.   
  33. bool ThreadImpl::isRunningImpl() const  
  34. {  
  35.     if (_thread)  
  36.     {  
  37.         DWORD ec = 0;  
  38.         return GetExitCodeThread(_thread, &ec) && ec == STILL_ACTIVE;  
  39.     }  
  40.     return false;  
  41. }  
  42.   
  43.   
  44. void ThreadImpl::threadCleanup()  
  45. {  
  46.     if (!_thread) return;  
  47.     if (CloseHandle(_thread)) _thread = 0;  
  48. }  
  49.   
  50.   
  51. ThreadImpl* ThreadImpl::currentImpl()  
  52. {  
  53.     return _currentThreadHolder.get();  
  54. }  
  55.   
  56.   
  57. ThreadImpl::TIDImpl ThreadImpl::currentTidImpl()  
  58. {  
  59.     return GetCurrentThreadId();  
  60. }  



  RunnableAdapter适配器:

      下面我们再看看RunnableAdapter是如何运用适配器模式的,在Poco-1.4.6/Foundation/Include/RunnableAdaper.h中找到RunnableAdaper类的实现:

[cpp] view plaincopyprint?
  1. template <class C>  
  2. class RunnableAdapter: public Runnable  
  3.     /// This adapter simplifies using ordinary methods as  
  4.     /// targets for threads.  
  5.     /// Usage:  
  6.     ///    RunnableAdapter<MyClass> ra(myObject, &MyObject::doSomething));  
  7.     ///    Thread thr;  
  8.     ///    thr.Start(ra);  
  9.     ///  
  10.     /// For using a freestanding or static member function as a thread  
  11.     /// target, please see the ThreadTarget class.  
  12. {  
  13. public:  
  14.     typedef void (C::*Callback)();  
  15.       
  16.     RunnableAdapter(C& object, Callback method): _pObject(&object), _method(method)  
  17.     {  
  18.     }  
  19.       
  20.     RunnableAdapter(const RunnableAdapter& ra): _pObject(ra._pObject), _method(ra._method)  
  21.     {  
  22.     }  
  23.   
  24.     ~RunnableAdapter()  
  25.     {  
  26.     }  
  27.   
  28.     RunnableAdapter& operator = (const RunnableAdapter& ra)  
  29.     {  
  30.         _pObject = ra._pObject;  
  31.         _method  = ra._method;  
  32.         return *this;  
  33.     }  
  34.   
  35.     void run()  
  36.     {  
  37.         (_pObject->*_method)();  
  38.     }  
  39.       
  40. private:  
  41.     RunnableAdapter();  
  42.   
  43.     C*       _pObject;  
  44.     Callback _method;  
  45. };  

    可以看出,这里是一个经典的对象适配器模式的运用,关于适配器模式可见参考文章:http://www.cnblogs.com/houleixx/archive/2008/03/04/1090214.html



   Thread的另一个接口:直接传入通过函数和参数

Thread::start除了接收Runnable对象之外,还可以传入函数和参数,向_beginThreadex和CreateThread那样,start原型如下:

[cpp] view plaincopyprint?
  1. typedef void (*Callable)(void*);  
  2. void start(Callable target, void* pData = 0);  
  3. 使用范例:  
  4. #include <iostream>  
  5. #include "Poco/Thread.h"  
  6. #include "Poco/ThreadLocal.h"  
  7. #include "Poco/Runnable.h"  
  8.   
  9.  using namespace std;  
  10.  using namespace Poco;  
  11.   
  12. void sayHello(void* name)  
  13. {  
  14.     cout<<"Hello "<<(char*)name<<endl;  
  15. }  
  16. void main()  
  17. {  
  18.     static char* name = "DJWu";  
  19.     Thread thr;  
  20.     thr.start(sayHello, name);  
  21.     thr.join();  
  22.     return ;  
  23. }  


    现在我们来看看这种情况下Thread::start是如何工作的:

在Foundation/src/Thread_WIN32.cpp中找到startImpl的另一个重载源码:

[cpp] view plaincopyprint?
  1. void ThreadImpl::startImpl(Callable target, void* pData)  
  2. {  
  3.     if (isRunningImpl())  
  4.         throw SystemException("thread already running");  
  5.   
  6.     threadCleanup();  
  7.     _callbackTarget.callback = target;  
  8.     _callbackTarget.pData = pData;  
  9.   
  10.     createImpl(callableEntry, this);  
  11. }  

    startImpl将用户定义的参数和入口函数放入一个成员结构体_callbackTarget中,然后调用createImpl,由于这里传入的callableEntry和前面Runnable版本的startImpl传入的runnableEntry函数原型是一致的(定义在Foundation/Include/Thread_WIN32.h中):

[cpp] view plaincopyprint?
  1. #if defined(_DLL)  
  2.     static DWORD WINAPI runnableEntry(LPVOID pThread);  
  3. #else  
  4.     static unsigned __stdcall runnableEntry(void* pThread);  
  5. #endif  
  6.   
  7. #if defined(_DLL)  
  8.     static DWORD WINAPI callableEntry(LPVOID pThread);  
  9. #else  
  10.     static unsigned __stdcall callableEntry(void* pThread);  
  11. #endif  

它们的原型与Entry一致:

[cpp] view plaincopyprint?
  1. #if defined(_DLL)  
  2.     typedef DWORD (WINAPI *Entry)(LPVOID);  
  3. #else  
  4.     typedef unsigned (__stdcall *Entry)(void*);  
  5. #endif  

因此它们调用的是同一个createImpl(createImpl也没有重载),这里再次将createImpl贴出来:

[cpp] view plaincopyprint?
  1. void ThreadImpl::createImpl(Entry ent, void* pData)  
  2. {  
  3. #if defined(_DLL)  
  4.     _thread = CreateThread(NULL, _stackSize, ent, pData, 0, &_threadId);  
  5. #else  
  6.     unsigned threadId;  
  7.     _thread = (HANDLE) _beginthreadex(NULL, _stackSize, ent, this, 0, &threadId);  
  8.     _threadId = static_cast<DWORD>(threadId);  
  9. #endif  
  10.     if (!_thread)  
  11.         throw SystemException("cannot create thread");  
  12.     if (_prio != PRIO_NORMAL_IMPL && !SetThreadPriority(_thread, _prio))  
  13.         throw SystemException("cannot set thread priority");  
  14. }  

此时线程的真正入口callableEntry如下:

[cpp] view plaincopyprint?
  1. #if defined(_DLL)  
  2. DWORD WINAPI ThreadImpl::callableEntry(LPVOID pThread)  
  3. #else  
  4. unsigned __stdcall ThreadImpl::callableEntry(void* pThread)  
  5. #endif  
  6. {  
  7.     _currentThreadHolder.set(reinterpret_cast<ThreadImpl*>(pThread));  
  8. #if defined(_DEBUG) && defined(POCO_WIN32_DEBUGGER_THREAD_NAMES)  
  9.     setThreadName(-1, reinterpret_cast<Thread*>(pThread)->getName().c_str());  
  10. #endif  
  11.     try  
  12.     {  
  13.         ThreadImpl* pTI = reinterpret_cast<ThreadImpl*>(pThread);  
  14.         pTI->_callbackTarget.callback(pTI->_callbackTarget.pData);  
  15.     }  
  16.     catch (Exception& exc)  
  17.     {  
  18.         ErrorHandler::handle(exc);  
  19.     }  
  20.     catch (std::exception& exc)  
  21.     {  
  22.         ErrorHandler::handle(exc);  
  23.     }  
  24.     catch (...)  
  25.     {  
  26.         ErrorHandler::handle();  
  27.     }  
  28.     return 0;  
  29. }  


     这里面和runnableEntry做相似的工作:先保存该线程对应的Thread对象指针,再调用用户指定的入口,前面用用户指定的对象调用run函数,这里用_callbackTarget中的函数地址和参数启动函数。

     综合这两种启动线程的方式,它们的入口并不直接是用户指定的入口,而是runnableEntry或者callbackEntry,它们做了一些额外工作:

1.保存当前线程对应的Thread对象指针(通过TLS机制)

2.如果是在调试状态,则可以给线程设置名字(可通过Thread::setName指定)

3.为线程运行设置异常帧


    线程本地存储:ThreadLocal类

    ThreadLocal类为开发者提供了更为简洁的TLS机制使用方法,TLS机制用来保存这样一些变量:它们在不同的线程里有不同的值,并且各自维护,线程不能访问其他线程中的这些变量。

    关于TLS机制可参见《Windows核心编程》和这篇文章:http://www.cnblogs.com/stli/archive/2010/11/03/1867852.html

   ThreadLocal使用方法:

[cpp] view plaincopyprint?
  1. #include "Poco/Thread.h"  
  2. #include "Poco/Runnable.h"  
  3. #include "Poco/ThreadLocal.h"  
  4. #include <iostream>  
  5. class Counter: public Poco::Runnable  
  6. {  
  7.     void run()  
  8.    {  
  9.         static Poco::ThreadLocal<int> tls;  
  10.         for (*tls = 0; *tls < 10; ++(*tls))  
  11.         {  
  12.             std::cout << *tls << std::endl;  
  13.         }  
  14.     }  
  15. };  
  16. int main(int argc, char** argv)  
  17. {  
  18.     Counter counter;  
  19.     Poco::Thread t1;  
  20.     Poco::Thread t2;  
  21.     t1.start(counter);//这两句官方文档上有错,文档上是t1.start(); t2.start();  
  22.     t2.start(counter);  
  23.     t1.join();  
  24.     t2.join();  
  25.     return 0;  
  26. }  

    使用ThreadLocal模板类可以保存任何变量(只需提供默认构造函数),并且通过*和->来进行很方便的存取。使用方法一目了然,避开了相对繁琐的TlsAlloc,TlsSetValue,TlsGetValue,其实ThreadLocal内部也并没有使用线程的TLS机制。来看看其内部实现。在Foundation/Include/Poco/ThreadLocal.h和Foundation/src/ThreadLocal.cpp中,我们找到四个相关类,为了解释方便,我将ThreadLocal.cpp中比较重要的函数实现一起放在了ThreadLocal.h中:

[cpp] view plaincopyprint?
  1. class Foundation_API TLSAbstractSlot  //该类用于抽象TLSSlot模板类,并没有实际接口  
  2.     /// This is the base class for all objects  
  3.     /// that the ThreadLocalStorage class manages.  
  4. {  
  5. public:  
  6.     TLSAbstractSlot();  
  7.     virtual ~TLSAbstractSlot();  
  8. };  
  9.   
  10.   
  11. template <class C>  
  12. class TLSSlot: public TLSAbstractSlot  //该类实际代表了对ThreadLocal对象所保存的值(模板参数也由ThreadLocal提供) 并且给出了值的存取过程(注意value()函数返回的是引用)  
  13.     /// The Slot template wraps another class  
  14.     /// so that it can be stored in a ThreadLocalStorage  
  15.     /// object. This class is used internally, and you  
  16.     /// must not create instances of it yourself.  
  17. {  
  18. public:  
  19.     TLSSlot():_value(){}  
  20.       
  21.     ~TLSSlot(){}  
  22.       
  23.     C& value(){return _value;}  
  24.       
  25. private:  
  26.     TLSSlot(const TLSSlot&);  
  27.     TLSSlot& operator = (const TLSSlot&);  
  28.   
  29.     C _value;  
  30. };  
  31.   
  32.   
  33. class Foundation_API ThreadLocalStorage    
  34.     //该类维系一个map<ThreadLocal<C>*, TLSSlot<C>*>这是实现ThreadLocal的关键  
  35.     //ThreadLocal类通过传入this指针来获取自身所代表的值(一个ThreadLocal对象对应代表一个值)  
  36.     /// This class manages the local storage for each thread.  
  37.     /// Never use this class directly, always use the  
  38.     /// ThreadLocal template for managing thread local storage.  
  39. {  
  40. public:  
  41.     ThreadLocalStorage(){}  
  42.         /// Creates the TLS.  
  43.           
  44.     ~ThreadLocalStorage()  
  45.         /// Deletes the TLS.  
  46.     {  
  47.         for (TLSMap::iterator it = _map.begin(); it != _map.end(); ++it)  
  48.         {  
  49.             delete it->second;     
  50.         }  
  51.     }  
  52.   
  53.     TLSAbstractSlot*& get(const void* key)  
  54.     //通过传入的ThreadLocal<C>*指针在_map中查找对应的TLSSlot<C>指针,注意在ThreadLocal对象定义时  
  55.     //并不会立即将ThreadLocal对象和一个TLSSlot关联起来,而是在第一次对其使用*或者->获取其值时,  
  56.     //也就是第一次调用本函数时,如果在_map中没有找到其对应值,才将ThreadLocal指针和一个NULL指针插入_map  
  57.     //然后返回NULL。由于返回的指针引用,因此在之外对返回值作的修改也会修改_map中的值  
  58.         /// Returns the slot for the given key.  
  59.     {  
  60.         TLSMap::iterator it = _map.find(key);  
  61.         if (it == _map.end())//没找到 插入并返回空指针  
  62.             return _map.insert(TLSMap::value_type(key, reinterpret_cast<Poco::TLSAbstractSlot*>(0))).first->second;  
  63.         else  
  64.             return it->second;  
  65.     }     
  66.     static ThreadLocalStorage& current()  
  67.         /// Returns the TLS object for the current thread  
  68.         /// (which may also be the main thread).  
  69.     {  
  70.         Thread* pThread = Thread::current();  
  71.         if (pThread)  
  72.         {  
  73.             return pThread->tls();  
  74.             //附Thread::tls()代码:  
  75.             //ThreadLocalStorage& Thread::tls()  
  76.             //{  
  77.             //  if (!_pTLS)  
  78.             //      _pTLS = new ThreadLocalStorage;  
  79.             //  return *_pTLS;  
  80.             //}  
  81.         }  
  82.         else  
  83.         {  
  84.             return *sh.get();  
  85.             //static SingletonHolder<ThreadLocalStorage> sh;是一个全局静态变量  
  86.             //SingletonHolder是一个单例模式容器 如果pThread为NULL,则说明当前线程是主线程  
  87.             //sh是为主线程准备的ThreadLocalStorage  
  88.         }  
  89.     }  
  90.           
  91.     static void clear()  
  92.         /// Clears the current thread's TLS object.  
  93.         /// Does nothing in the main thread.  
  94.     {  
  95.         Thread* pThread = Thread::current();  
  96.         if (pThread)  
  97.             pThread->clearTLS();  
  98.             //附Thread::clearTls()代码:  
  99.             //void Thread::clearTLS()  
  100.             //{  
  101.             //  if (_pTLS)  
  102.             //  {  
  103.             //      delete _pTLS;  
  104.             //      _pTLS = 0;  
  105.             //  }  
  106.             //}  
  107.     }  
  108.       
  109. private:  
  110.     typedef std::map<const void*, TLSAbstractSlot*> TLSMap;  
  111.       
  112.     TLSMap _map;  
  113.   
  114.     friend class Thread;  
  115. };  
  116.   
  117.   
  118. template <class C>  
  119. class ThreadLocal //ThreadLocal完成对自身所代表的值的一层封装 值的获取在ThreadLocalStorage中完成  
  120.     /// This template is used to declare type safe thread  
  121.     /// local variables. It can basically be used like  
  122.     /// a smart pointer class with the special feature  
  123.     /// that it references a different object  
  124.     /// in every thread. The underlying object will  
  125.     /// be created when it is referenced for the first  
  126.     /// time.  
  127.     /// See the NestedDiagnosticContext class for an  
  128.     /// example how to use this template.  
  129.     /// Every thread only has access to its own  
  130.     /// thread local data. There is no way for a thread  
  131.     /// to access another thread's local data.  
  132. {  
  133.     typedef TLSSlot<C> Slot;  
  134.   
  135. public:  
  136.     ThreadLocal()  
  137.     {  
  138.     }  
  139.       
  140.     ~ThreadLocal()  
  141.     {  
  142.     }  
  143.       
  144.     C* operator -> ()  
  145.     {  
  146.         return &get();  
  147.     }  
  148.       
  149.     C& operator * ()  
  150.         /// "Dereferences" the smart pointer and returns a reference  
  151.         /// to the underlying data object. The reference can be used  
  152.         /// to modify the object.  
  153.     {  
  154.         return get();  
  155.     }  
  156.   
  157.     C& get()  
  158.         /// Returns a reference to the underlying data object.  
  159.         /// The reference can be used to modify the object.  
  160.     {  
  161.     //在当前线程的ThreadLocalStorage类中通过this指针在map中查找其代表的值   
  162.     //注意ThreadLocalStorage::get(this)返回的是TLSSlot<C>*指针的引用   
  163.     //因此对返回指针引用p的修改会直接影响到ThreadLocalStorage::_map中的值  
  164.         TLSAbstractSlot*& p = ThreadLocalStorage::current().get(this);  
  165.         if (!p) p = new Slot;  
  166.         return static_cast<Slot*>(p)->value();  
  167.     }  
  168.       
  169. private:  
  170.     ThreadLocal(const ThreadLocal&);  
  171.     ThreadLocal& operator = (const ThreadLocal&);  
  172. };  

看起来这四个类以及Thread类之间的交互有些麻烦,但是实际这主要是为了明确各个类的职责:

      对于Thread类,它维护一个ThreadLocalStorage* _pTLS指针,负责它本身的TLS类的分配(tls())和释放(clearTls())

      对于ThreadLocalStorage类 它是整个Thread TLS机制的核心,它从友元类Thread获取当前运行线程的_pTLS指针,并且在该ThreadLocalStorage里寻找传入的ThreadLocal指针所代表的值,如果找不到,则插入一个pair,将该second设为NULL, 并且返回TLSAbstractSlot*指针的引用。

      对于TLSAbstractSlot类,它的主要功能就是抽象TLSSlot<C>模板类,这样ThreadLocalStorage可以返回统一接口,而不用再成为模板类(如果这样,那么Thread类维护_pTLS也会比较困难,因为模板类实例化需要提供模板参数)。

       TLSSlot类代表ThreadLocal代表的值,并负责该值的读取(只有value()方法而没有setValue()方法),注意在使用ThreadLocal时,需要先声明再赋值,而不是直接初始化,因为如果ThreadLocal<int> a = 3;  a实际上是ThreadLocal对象,而不是int的引用。正确使用应该是ThreadLocal<int> a; *a = 3;这也是之前说使用ThreadLocal作为TLS值的类要求必须要有默认构造函数的原因。

      还有注意的是,在整个类之间的传递过程中,基本都是返回的指针引用,这样才能一处修改,影响到其他组件的同步修改。

      Poco的ThreadLocal机制并没有使用线程的TLS机制,而是将TLS数据放在了Thread类中(确切说是其维护的_pTLS指针中,对于主线程,其并没有对应Thread类,因此为其定制了一个全局静态单例的ThreadLocalStorage对象)。

ThreadPool线程池支持

POCO为我们提供了线程池的接口,关于线程池的优缺点和适用情形这里不再讨论,网上也有很多各式的线程池实现,POCO的线程池自然是基于前面介绍的多线程结构的。

简单地说,POCO线程池主要有两个类,PooledThread和ThreadPool,前者是线程池中的线程,负责执行线程池分配下来的任务,它基于Thread和Runnable机制。后者是线程池类,它负责对线程池中的各个线程进行维护(创建,分配,回收,清除等)。

先看看PooledThread的主要接口:

文件位置:poco-1.4.6/Foundation/src/ThreadPool.cpp

[cpp] view plaincopyprint?
  1. class PooledThread: public Runnable  
  2. {  
  3. public:  
  4.     PooledThread(const std::string& name, int stackSize = POCO_THREAD_STACK_SIZE);  
  5.     ~PooledThread();  
  6.   
  7.     void start();//线程处于就绪(空闲)状态,当入口被设定后(通过下面两个start),即可开始任务(由_targetReady信号量控制)。  
  8.     void start(Thread::Priority priority, Runnable& target);//为线程设定优先级和入口  
  9.     void start(Thread::Priority priority, Runnable& target, const std::string& name);//为线程设定优先级,入口和名字  
  10.     bool idle();//返回是否是空闲线程  
  11.     int idleTime();//空闲时间  
  12.     void join();//等待结束  
  13.     void activate();//激活线程 将线程由就绪(空闲)改为忙碌(_idle=false)  
  14.     void release();//销毁自身  
  15.     void run();//自定义入口 在start()中调用 它等待_targetReady信号量 并执行真正的线程入口_pTarget->run();  
  16.   
  17. private:  
  18.     volatile bool        _idle;//线程是否空闲  
  19.     volatile std::time_t _idleTime;//线程本次空闲开始时刻  
  20.     Runnable*            _pTarget;//线程入口  
  21.     std::string          _name;//线程名字(可选)  
  22.     Thread               _thread;//线程对象  
  23.     Event                _targetReady;//任务是否准备好 即_pTarget是否有效  
  24.     Event                _targetCompleted;//任务是否执行完毕 即_pTarget->run()是否执行完成  
  25.     Event                _started;//线程是否已经开始  
  26.     FastMutex            _mutex;//提供对_pTarget的互斥访问  
  27. };  
      下面是PooledThread的一些主要函数实现:

[cpp] view plaincopyprint?
  1. void PooledThread::start()  
  2. {  
  3.     _thread.start(*this);  
  4.     _started.wait();  
  5. }  
  6. void PooledThread::start(Thread::Priority priority, Runnable& target)  
  7. {  
  8.     FastMutex::ScopedLock lock(_mutex);  
  9.       
  10.     poco_assert (_pTarget == 0);  
  11.   
  12.     _pTarget = &target;  
  13.     _thread.setPriority(priority);  
  14.     _targetReady.set();  
  15. }  
  16. void PooledThread::start(Thread::Priority priority, Runnable& target, const std::string& name)  
  17. {  
  18.     FastMutex::ScopedLock lock(_mutex);  
  19.   
  20.     std::string fullName(name);  
  21.     if (name.empty())  
  22.     {  
  23.         fullName = _name;  
  24.     }  
  25.     else  
  26.     {  
  27.         fullName.append(" (");  
  28.         fullName.append(_name);  
  29.         fullName.append(")");  
  30.     }  
  31.     _thread.setName(fullName);  
  32.     _thread.setPriority(priority);  
  33.       
  34.     poco_assert (_pTarget == 0);  
  35.   
  36.     _pTarget = &target;  
  37.     _targetReady.set();  
  38. }  
  39. inline bool PooledThread::idle()  
  40. {  
  41.     return _idle;  
  42. }  
  43. int PooledThread::idleTime()  
  44. {  
  45.     FastMutex::ScopedLock lock(_mutex);  
  46.   
  47. #if defined(_WIN32_WCE)  
  48.     return (int) (wceex_time(NULL) - _idleTime);  
  49. #else  
  50.     return (int) (time(NULL) - _idleTime);  
  51. #endif    
  52. }  
  53. void PooledThread::join()  
  54. {  
  55.     _mutex.lock();  
  56.     Runnable* pTarget = _pTarget;  
  57.     _mutex.unlock();  
  58.     if (pTarget)  
  59.         _targetCompleted.wait();//等待本次任务结束  
  60. }  
  61. void PooledThread::activate()  
  62. {  
  63.     FastMutex::ScopedLock lock(_mutex);  
  64.       
  65.     poco_assert (_idle);  
  66.     _idle = false;//忙碌状态  
  67.     _targetCompleted.reset();//_targetCompeleted信号量无效 等待任务分配  
  68. }  
  69. void PooledThread::release()  
  70. {  
  71.     const long JOIN_TIMEOUT = 10000;  
  72.       
  73.     _mutex.lock();  
  74.     _pTarget = 0;  
  75.     _mutex.unlock();  
  76.   
  77.     _targetReady.set();//_targetReady信号量有效 而_pTarget=0; 此时在pooledThread:run()中将跳出无线循环 结束自身  
  78.     if (_thread.tryJoin(JOIN_TIMEOUT))  
  79.     {  
  80.         delete this;  
  81.     }  
  82. }  
  83. void PooledThread::run()  
  84. {  
  85.     _started.set();  
  86.     for (;;)//不断等待并执行分配的任务 通过_targetReady判断是否有新的任务  
  87.     {  
  88.         _targetReady.wait();  
  89.         _mutex.lock();  
  90.         if (_pTarget) //当_pTarget=0;将跳出无限循环 即结束自身   
  91.         {  
  92.             _mutex.unlock();  
  93.             try  
  94.             {  
  95.                 _pTarget->run();  
  96.             }  
  97.             catch (Exception& exc)  
  98.             {  
  99.                 ErrorHandler::handle(exc);  
  100.             }  
  101.             catch (std::exception& exc)  
  102.             {  
  103.                 ErrorHandler::handle(exc);  
  104.             }  
  105.             catch (...)  
  106.             {  
  107.                 ErrorHandler::handle();  
  108.             }  
  109.             FastMutex::ScopedLock lock(_mutex);  
  110.             _pTarget  = 0;  
  111. #if defined(_WIN32_WCE)  
  112.             _idleTime = wceex_time(NULL);  
  113. #else  
  114.             _idleTime = time(NULL);  
  115. #endif    
  116.             _idle     = true;//执行完成后,重新设为空闲状态  
  117.             _targetCompleted.set();  
  118.             ThreadLocalStorage::clear();  
  119.             _thread.setName(_name);  
  120.             _thread.setPriority(Thread::PRIO_NORMAL);  
  121.         }  
  122.         else  
  123.         {  
  124.             _mutex.unlock();  
  125.             break;  
  126.         }  
  127.     }  
  128. }  
      PooledThread通过维护一个Thread对象和一些信号量控制来完成对Thread对象的复用,PooledThread类从Runnable派生,这样就可以通过定义run()方法来反复执行任务,而实际上每次执行的任务是定义在成员Runnable* _pTarget中。

而ThreadPool就更为简单了,它负责任务的分配,线程的管理。接口如下:

文件位置:poco-1.4.6/Foundation/Include/poco/ThreadPool.h

[cpp] view plaincopyprint?
  1. class Foundation_API ThreadPool  
  2.     /// A thread pool always keeps a number of threads running, ready  
  3.     /// to accept work.  
  4.     /// Creating and starting a threads can impose a significant runtime  
  5.     /// overhead to an application. A thread pool helps to improve  
  6.     /// the performance of an application by reducing the number  
  7.     /// of threads that have to be created (and destroyed again).  
  8.     /// Threads in a thread pool are re-used once they become  
  9.     /// available again.  
  10.     /// The thread pool always keeps a minimum number of threads  
  11.     /// running. If the demans for threads increases, additional  
  12.     /// threads are created. Once the demand for threads sinks  
  13.     /// again, no-longer used threads are stopped and removed  
  14.     /// from the pool.  
  15. {  
  16. public:  
  17.     ThreadPool(int minCapacity = 2,  
  18.         int maxCapacity = 16,  
  19.         int idleTime = 60,  
  20.         int stackSize = POCO_THREAD_STACK_SIZE);  
  21.         /// Creates a thread pool with minCapacity threads.  
  22.         /// If required, up to maxCapacity threads are created  
  23.         /// a NoThreadAvailableException exception is thrown.  
  24.         /// If a thread is running idle for more than idleTime seconds,  
  25.         /// and more than minCapacity threads are running, the thread  
  26.         /// is killed. Threads are created with given stack size.  
  27.   
  28.     ThreadPool(const std::string& name,  
  29.         int minCapacity = 2,  
  30.         int maxCapacity = 16,  
  31.         int idleTime = 60,  
  32.         int stackSize = POCO_THREAD_STACK_SIZE);  
  33.         /// Creates a thread pool with the given name and minCapacity threads.  
  34.         /// If required, up to maxCapacity threads are created  
  35.         /// a NoThreadAvailableException exception is thrown.  
  36.         /// If a thread is running idle for more than idleTime seconds,  
  37.         /// and more than minCapacity threads are running, the thread  
  38.         /// is killed. Threads are created with given stack size.  
  39.   
  40.     ~ThreadPool();  
  41.         /// Currently running threads will remain active  
  42.         /// until they complete.   
  43.       
  44.     void addCapacity(int n);  
  45.         /// Increases (or decreases, if n is negative)  
  46.         /// the maximum number of threads.  
  47.   
  48.     int capacity() const;  
  49.         /// Returns the maximum capacity of threads.  
  50.   
  51.     void setStackSize(int stackSize);  
  52.         /// Sets the stack size for threads.  
  53.         /// New stack size applies only for newly created threads.  
  54.   
  55.     int getStackSize() const;  
  56.         /// Returns the stack size used to create new threads.  
  57.   
  58.     int used() const;  
  59.         /// Returns the number of currently used threads.  
  60.   
  61.     int allocated() const;  
  62.         /// Returns the number of currently allocated threads.  
  63.   
  64.     int available() const;  
  65.         /// Returns the number available threads.  
  66.   
  67.     void start(Runnable& target);  
  68.         /// Obtains a thread and starts the target.  
  69.         /// Throws a NoThreadAvailableException if no more  
  70.         /// threads are available.  
  71.   
  72.     void start(Runnable& target, const std::string& name);  
  73.         /// Obtains a thread and starts the target.  
  74.         /// Assigns the given name to the thread.  
  75.         /// Throws a NoThreadAvailableException if no more  
  76.         /// threads are available.  
  77.   
  78.     void startWithPriority(Thread::Priority priority, Runnable& target);  
  79.         /// Obtains a thread, adjusts the thread's priority, and starts the target.  
  80.         /// Throws a NoThreadAvailableException if no more  
  81.         /// threads are available.  
  82.   
  83.     void startWithPriority(Thread::Priority priority, Runnable& target, const std::string& name);  
  84.         /// Obtains a thread, adjusts the thread's priority, and starts the target.  
  85.         /// Assigns the given name to the thread.  
  86.         /// Throws a NoThreadAvailableException if no more  
  87.         /// threads are available.  
  88.   
  89.     void stopAll();  
  90.         /// Stops all running threads and waits for their completion.  
  91.         ///  
  92.         /// Will also delete all thread objects.  
  93.         /// If used, this method should be the last action before  
  94.         /// the thread pool is deleted.  
  95.         ///  
  96.         /// Note: If a thread fails to stop within 10 seconds   
  97.         /// (due to a programming error, for example), the  
  98.         /// underlying thread object will not be deleted and  
  99.         /// this method will return anyway. This allows for a  
  100.         /// more or less graceful shutdown in case of a misbehaving  
  101.         /// thread.  
  102.   
  103.     void joinAll();  
  104.         /// Waits for all threads to complete.  
  105.         ///  
  106.         /// Note that this will not actually join() the underlying  
  107.         /// thread, but rather wait for the thread's runnables  
  108.         /// to finish.  
  109.   
  110.     void collect();  
  111.         /// Stops and removes no longer used threads from the  
  112.         /// thread pool. Can be called at various times in an  
  113.         /// application's life time to help the thread pool  
  114.         /// manage its threads. Calling this method is optional,  
  115.         /// as the thread pool is also implicitly managed in  
  116.         /// calls to start(), addCapacity() and joinAll().  
  117.   
  118.     const std::string& name() const;  
  119.         /// Returns the name of the thread pool,  
  120.         /// or an empty string if no name has been  
  121.         /// specified in the constructor.  
  122.   
  123.     static ThreadPool& defaultPool();  
  124.         /// Returns a reference to the default  
  125.         /// thread pool.  
  126.   
  127. protected:  
  128.     PooledThread* getThread();//获取线程池中的一个空闲线程  
  129.     PooledThread* createThread();//创建线程  
  130.   
  131.     void housekeep();//清理线程,移除多余的线程  
  132.   
  133. private:  
  134.     ThreadPool(const ThreadPool& pool);  
  135.     ThreadPool& operator = (const ThreadPool& pool);  
  136.   
  137.     typedef std::vector<PooledThread*> ThreadVec;  
  138.   
  139.     std::string _name; //线程池名字  
  140.     int _minCapacity;  //线程池最小线程容量  
  141.     int _maxCapacity;  //<span style="font-family: Arial;">线程池最大线程容量</span>  
  142.     int _idleTime;     //线程空闲时间(线程池中空闲时间超过_idleTime的线程可能被移除线程池)  
  143.     int _serial;  
  144.     int _age;  
  145.     int _stackSize;    //线程池中线程的栈大小  
  146.     ThreadVec _threads;//线程对象数组  
  147.     mutable FastMutex _mutex;  
  148. };  
        在有新的任务分配时,ThreadPool通过getThread得到(或创建)一个可用的空闲线程对象PooledThread,并调用PooledThread的对应启动函数开始任务。如果此时线程池内的线程都在忙碌中且线程数达到最大容量,将抛出一个NoThreadAvailableException()异常。用户可设置线程池的名字,最小容量,最大容量,并可以手动地清理线程池中的多余空闲线程(houseKeep函数)。ThreadPool的主要函数实现如下:

[cpp] view plaincopyprint?
  1. ThreadPool::ThreadPool(int minCapacity,  
  2.     int maxCapacity,  
  3.     int idleTime,  
  4.     int stackSize):   
  5.     _minCapacity(minCapacity),   
  6.     _maxCapacity(maxCapacity),   
  7.     _idleTime(idleTime),  
  8.     _serial(0),  
  9.     _age(0),  
  10.     _stackSize(stackSize)  
  11. {  
  12.     poco_assert (minCapacity >= 1 && maxCapacity >= minCapacity && idleTime > 0);  
  13.   
  14.     for (int i = 0; i < _minCapacity; i++)  
  15.     {  
  16.         PooledThread* pThread = createThread();  
  17.         _threads.push_back(pThread);  
  18.         pThread->start();//线程处于就绪(空闲)状态 其实是在等待Thread->_targetReady信号量  
  19.     }  
  20. }  
  21.   
  22. ThreadPool::ThreadPool(const std::string& name,  
  23.     int minCapacity,  
  24.     int maxCapacity,  
  25.     int idleTime,  
  26.     int stackSize):  
  27.     _name(name),  
  28.     _minCapacity(minCapacity),   
  29.     _maxCapacity(maxCapacity),   
  30.     _idleTime(idleTime),  
  31.     _serial(0),  
  32.     _age(0),  
  33.     _stackSize(stackSize)  
  34. {  
  35.     poco_assert (minCapacity >= 1 && maxCapacity >= minCapacity && idleTime > 0);  
  36.   
  37.     for (int i = 0; i < _minCapacity; i++)  
  38.     {  
  39.         PooledThread* pThread = createThread();  
  40.         _threads.push_back(pThread);  
  41.         pThread->start();  
  42.     }  
  43. }  
  44.   
  45. ThreadPool::~ThreadPool()  
  46. {  
  47.     stopAll();  
  48. }  
  49.   
  50. void ThreadPool::addCapacity(int n)  
  51. {  
  52.     FastMutex::ScopedLock lock(_mutex);  
  53.   
  54.     poco_assert (_maxCapacity + n >= _minCapacity);  
  55.     _maxCapacity += n;  
  56.     housekeep();  
  57. }  
  58.   
  59. int ThreadPool::capacity() const  
  60. {  
  61.     FastMutex::ScopedLock lock(_mutex);  
  62.     return _maxCapacity;  
  63. }  
  64.   
  65. int ThreadPool::available() const  
  66. {  
  67.     FastMutex::ScopedLock lock(_mutex);  
  68.   
  69.     int count = 0;  
  70.     for (ThreadVec::const_iterator it = _threads.begin(); it != _threads.end(); ++it)  
  71.     {  
  72.         if ((*it)->idle()) ++count;  
  73.     }  
  74.     return (int) (count + _maxCapacity - _threads.size());  
  75. }  
  76.   
  77. int ThreadPool::used() const  
  78. {  
  79.     FastMutex::ScopedLock lock(_mutex);  
  80.   
  81.     int count = 0;  
  82.     for (ThreadVec::const_iterator it = _threads.begin(); it != _threads.end(); ++it)  
  83.     {  
  84.         if (!(*it)->idle()) ++count;  
  85.     }  
  86.     return count;  
  87. }  
  88.   
  89. int ThreadPool::allocated() const  
  90. {  
  91.     FastMutex::ScopedLock lock(_mutex);  
  92.   
  93.     return int(_threads.size());  
  94. }  
  95.   
  96.   
  97. void ThreadPool::start(Runnable& target)  
  98. {  
  99.     getThread()->start(Thread::PRIO_NORMAL, target);  
  100. }  
  101.   
  102. void ThreadPool::start(Runnable& target, const std::string& name)  
  103. {  
  104.     getThread()->start(Thread::PRIO_NORMAL, target, name);  
  105. }  
  106.   
  107. void ThreadPool::startWithPriority(Thread::Priority priority, Runnable& target)  
  108. {  
  109.     getThread()->start(priority, target);  
  110. }  
  111.   
  112. void ThreadPool::startWithPriority(Thread::Priority priority, Runnable& target, const std::string& name)  
  113. {  
  114.     getThread()->start(priority, target, name);  
  115. }  
  116.   
  117. void ThreadPool::stopAll()  
  118. {  
  119.     FastMutex::ScopedLock lock(_mutex);  
  120.   
  121.     for (ThreadVec::iterator it = _threads.begin(); it != _threads.end(); ++it)  
  122.     {  
  123.         (*it)->release();  
  124.     }  
  125.     _threads.clear();  
  126. }  
  127.   
  128. void ThreadPool::joinAll()  
  129. {  
  130.     FastMutex::ScopedLock lock(_mutex);  
  131.   
  132.     for (ThreadVec::iterator it = _threads.begin(); it != _threads.end(); ++it)  
  133.     {  
  134.         (*it)->join();  
  135.     }  
  136.     housekeep();//清理线程池  
  137. }  
  138.   
  139. void ThreadPool::collect()  
  140. {  
  141.     FastMutex::ScopedLock lock(_mutex);  
  142.     housekeep();  
  143. }  
  144.   
  145. void ThreadPool::housekeep()  
  146. {  
  147.     _age = 0;  
  148.     if (_threads.size() <= _minCapacity)  
  149.         return;  
  150.   
  151.     ThreadVec idleThreads;  
  152.     ThreadVec expiredThreads;  
  153.     ThreadVec activeThreads;  
  154.     idleThreads.reserve(_threads.size());  
  155.     activeThreads.reserve(_threads.size());  
  156.     //将线程池中的线程分为三类:正在运行的 空闲的(空闲时间小于_idleTime) 过期的(空闲时间大于_idleTime)  
  157.     for (ThreadVec::iterator it = _threads.begin(); it != _threads.end(); ++it)  
  158.     {  
  159.         if ((*it)->idle())  
  160.         {  
  161.             if ((*it)->idleTime() < _idleTime)  
  162.                 idleThreads.push_back(*it);  
  163.             else   
  164.                 expiredThreads.push_back(*it);    
  165.         }  
  166.         else activeThreads.push_back(*it);  
  167.     }  
  168.     int n = (int) activeThreads.size();  
  169.     int limit = (int) idleThreads.size() + n;  
  170.     if (limit < _minCapacity) limit = _minCapacity;//保证线程池中的线程数最少为_minCapacity  
  171.     idleThreads.insert(idleThreads.end(), expiredThreads.begin(), expiredThreads.end());  
  172.     _threads.clear();//清除线程数组(此时线程对象只是被转移,因此不会影响到正在运行的线程)  
  173.     for (ThreadVec::iterator it = idleThreads.begin(); it != idleThreads.end(); ++it)  
  174.     {<span style="white-space:pre"> </span>//如果忙碌的线程数n小于_minCapacity 那么再添加_minCapacity-n个空闲或过期线程到线程数组   
  175.         if (n < limit)  
  176.         {  
  177.             _threads.push_back(*it);  
  178.             ++n;  
  179.         }  
  180.         else (*it)->release();//清除多余的空闲或过期线程  
  181.     }  
  182.     _threads.insert(_threads.end(), activeThreads.begin(), activeThreads.end());  
  183. }  
  184.   
  185.   
  186. PooledThread* ThreadPool::getThread()  
  187. {  
  188.     FastMutex::ScopedLock lock(_mutex);  
  189.   
  190.     if (++_age == 32)  
  191.         housekeep();  
  192.   
  193.     PooledThread* pThread = 0;  
  194.     for (ThreadVec::iterator it = _threads.begin(); !pThread && it != _threads.end(); ++it)  
  195.     {//尝试寻找空闲线程  
  196.         if ((*it)->idle()) pThread = *it;  
  197.     }  
  198.     if (!pThread)  
  199.     {//如果没有空闲线程  
  200.         if (_threads.size() < _maxCapacity)  
  201.         {//还有足够容量 则创建一个新线程  
  202.             <span style="white-space:pre">      </span>pThread = createThread();  
  203.            <span style="white-space:pre">       </span>try  
  204.             <span style="white-space:pre">      </span>{  
  205.                 <span style="white-space:pre">      </span>pThread->start();  
  206.                 <span style="white-space:pre">      </span>_threads.push_back(pThread);  
  207.            <span style="white-space:pre">       </span>}  
  208.             <span style="white-space:pre">      </span>catch (...)  
  209.             <span style="white-space:pre">      </span>{  
  210.                 <span style="white-space:pre">      </span>delete pThread;  
  211.                 <span style="white-space:pre">      </span>throw;  
  212.             <span style="white-space:pre">      </span>}  
  213.         }  
  214.         else throw NoThreadAvailableException();//容量不足 抛出异常  
  215.     }  
  216.     pThread->activate();//激活线程(将线程状态由空闲改为忙碌 并重设_targetCompelete信号量)  
  217.     return pThread;  
  218. }  
  219.   
  220. PooledThread* ThreadPool::createThread()  
  221. {  
  222.     std::ostringstream name;  
  223.     name << _name << "[#" << ++_serial << "]";  
  224.     return new PooledThread(name.str(), _stackSize);  
  225. }  

     最后,POCO用单例模式提供了一个默认的线程池:

[cpp] view plaincopyprint?
  1. class ThreadPoolSingletonHolder  
  2. {  
  3. public:  
  4.     ThreadPoolSingletonHolder()  
  5.     {  
  6.         _pPool = 0;  
  7.     }  
  8.     ~ThreadPoolSingletonHolder()  
  9.     {  
  10.         delete _pPool;  
  11.     }  
  12.     ThreadPool* pool()  
  13.     {  
  14.         FastMutex::ScopedLock lock(_mutex);  
  15.           
  16.         if (!_pPool)  
  17.         {  
  18.             _pPool = new ThreadPool("default");  
  19.             if (POCO_THREAD_STACK_SIZE > 0)  
  20.                 _pPool->setStackSize(POCO_THREAD_STACK_SIZE);  
  21.         }  
  22.         return _pPool;  
  23.     }  
  24.       
  25. private:  
  26.     ThreadPool* _pPool;  
  27.     FastMutex   _mutex;  
  28. };  
  29.   
  30.   
  31. namespace  
  32. {  
  33.     static ThreadPoolSingletonHolder sh;  
  34. }  
  35.   
  36.   
  37. ThreadPool& ThreadPool::defaultPool()  
  38. {  
  39.     return *sh.pool();  
  40. }  


0 0
原创粉丝点击