POCO C++ 库学习和分析 -- 线程 (一)

michealtig 贡献于2014-09-12

作者 ya.jin  创建于2013-06-19 10:33:00   修改者ya.jin  修改于2013-06-19 10:33:00字数2739

文档摘要: 线程是程序设计中用的非常多的技术,在UI设计,网络通讯设计中广泛使用。在POCO库中,线程模块可以分成6个部分去理解。锁(Lock),线程(Thread),主动对象(ActiveObject),线程池(ThreadPool),定时器(Timer)。
关键词:

POCO C++库学习和分析 --  线程 (一)            线程是程序设计中用的非常多的技术,在UI设计,网络通讯设计中广泛使用。在POCO库中,线程模块可以分成6个部分去理解。锁(Lock),线程(Thread),主动对象(ActiveObject),线程池(ThreadPool), 定时器(Timer)。下面对它们分别介绍。   1.  数据保护-锁         线程是并行计算中比较复杂的技术之一,使用线程去设计问题时,在获取并行的好处时,也产生了racecondition的问题。锁的存在就是为了解决该问题。 POCO库封装了常见的几种锁,Mutex,Semaphore,Event,Scopelock,ReadWriteLock。类图分别如下:         Mutex         Semaphore         Event         ReadWriteLock          类图非常的简单。就不再多说了,有兴趣的朋友可以自己去看。对于不同平台, POCO基本上选择了比较好的实现方式。比如在Mutex的实现时,Window上用的是criticalsection而非mutex。 2.  线程         POCO对不同操作系统的线程进行了分装,使其变成了一个对象。下面是其的类图:          熟悉JAVA的朋友一定会很开心,这不就是JAVA中使用线程的两种形式之一吗。所有的业务逻辑全部在Runnable中。Thread类只负责开始(Start)和停止(Join)两个动作。          来看一下Thread的实现,在C++中底层API (windows下 _beginthreadex, linux下pthread_create)创建线程时必须要求入口函数是个全局或者静态函数,这要求业务具有唯一性。而事实上不同的线程就是为了完成不同业务的,不同对象对应不同线程。那变化时如何被封装至Thread类中呢。答案在下面。 [cpp] view plaincopy 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(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. }   15.    16. #if defined(_DLL)   17. DWORD WINAPI ThreadImpl::callableEntry(LPVOID pThread)   18. #else   19. unsigned __stdcall ThreadImpl::callableEntry(void* pThread)   20. #endif   21. {   22.     _currentThreadHolder.set(reinterpret_cast(pThread));   23. #if defined(_DEBUG) && defined(POCO_WIN32_DEBUGGER_THREAD_NAMES)   24.     setThreadName(-1, reinterpret_cast(pThread)->getName().c_str());   25. #endif   26.     try   27.     {   28.         ThreadImpl* pTI = reinterpret_cast(pThread);   29.         pTI->_callbackTarget.callback(pTI->_callbackTarget.pData);   30.     }   31.     catch (Exception& exc)   32.     {   33.         ErrorHandler::handle(exc);   34.     }   35.     catch (std::exception& exc)   36.     {   37.         ErrorHandler::handle(exc);   38.     }   39.     catch (...)   40.     {   41.         ErrorHandler::handle();   42.     }   43.     return 0;   44. }   在ThreadImpl::createImpl(Entry ent, void* pData)函数中创建线程时beginthreadex带入了this指针,也就是线程对象本身。 [cpp] view plaincopy 1. _thread = (HANDLE) _beginthreadex(NULL, _stackSize, ent, this, 0, &threadId);   线程对象本身存在一个结构体CallbackData,其中callback指向了真实的业务路口。不同线程对象在初始化时,会被赋值不同的业务入口函数。 而在静态函数callableEntry中,通过调用this指针可以运行真正的业务函数。 [cpp] view plaincopy 1. ThreadImpl* pTI = reinterpret_cast(pThread);   2. pTI->_callbackTarget.callback(pTI->_callbackTarget.pData);   最后用一段代码实例来结束吧 [cpp] view plaincopy 1. #include "Poco/Thread.h"   2. #include "Poco/Runnable.h"   3. #include    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. }   (版权所有,转载时请注明作者和出处  http://write.blog.csdn.net/postedit/8573894)

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 3 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档