POCO C++库学习和分析 -- 线程 (一)
来源:互联网 发布:黑莓软件商店 编辑:程序博客网 时间:2024/05/16 12:54
POCO C++库学习和分析 -- 线程 (一)
线程是程序设计中用的非常多的技术,在UI设计,网络通讯设计中广泛使用。在POCO库中,线程模块可以分成6个部分去理解。锁(Lock),线程(Thread),主动对象(ActiveObject),线程池(ThreadPool), 定时器(Timer)。下面对它们分别介绍。
1. 数据保护-锁
线程是并行计算中比较复杂的技术之一,使用线程去设计问题时,在获取并行的好处时,也产生了racecondition的问题。锁的存在就是为了解决该问题。
POCO库封装了常见的几种锁,Mutex,Semaphore,Event,Scopelock,ReadWriteLock。类图分别如下:
Mutex
Semaphore
类图非常的简单。就不再多说了,有兴趣的朋友可以自己去看。对于不同平台, POCO基本上选择了比较好的实现方式。比如在Mutex的实现时,Window上用的是criticalsection而非mutex。
2. 线程
POCO对不同操作系统的线程进行了分装,使其变成了一个对象。下面是其的类图:
熟悉JAVA的朋友一定会很开心,这不就是JAVA中使用线程的两种形式之一吗。所有的业务逻辑全部在Runnable中。Thread类只负责开始(Start)和停止(Join)两个动作。
来看一下Thread的实现,在C++中底层API (windows下 _beginthreadex, linux下pthread_create)创建线程时必须要求入口函数是个全局或者静态函数,这要求业务具有唯一性。而事实上不同的线程就是为了完成不同业务的,不同对象对应不同线程。那变化时如何被封装至Thread类中呢。答案在下面。
void ThreadImpl::createImpl(Entry ent, void* pData){#if defined(_DLL)_thread = CreateThread(NULL, _stackSize, ent, pData, 0, &_threadId);#elseunsigned threadId;_thread = (HANDLE) _beginthreadex(NULL, _stackSize, ent, this, 0, &threadId);_threadId = static_cast<DWORD>(threadId);#endifif (!_thread)throw SystemException("cannot create thread");if (_prio != PRIO_NORMAL_IMPL && !SetThreadPriority(_thread, _prio))throw SystemException("cannot set thread priority");}#if defined(_DLL)DWORD WINAPI ThreadImpl::callableEntry(LPVOID pThread)#elseunsigned __stdcall ThreadImpl::callableEntry(void* pThread)#endif{_currentThreadHolder.set(reinterpret_cast<ThreadImpl*>(pThread));#if defined(_DEBUG) && defined(POCO_WIN32_DEBUGGER_THREAD_NAMES)setThreadName(-1, reinterpret_cast<Thread*>(pThread)->getName().c_str());#endiftry{ThreadImpl* pTI = reinterpret_cast<ThreadImpl*>(pThread);pTI->_callbackTarget.callback(pTI->_callbackTarget.pData);}catch (Exception& exc){ErrorHandler::handle(exc);}catch (std::exception& exc){ErrorHandler::handle(exc);}catch (...){ErrorHandler::handle();}return 0;}
在ThreadImpl::createImpl(Entry ent, void* pData)函数中创建线程时beginthreadex带入了this指针,也就是线程对象本身。
_thread = (HANDLE) _beginthreadex(NULL, _stackSize, ent, this, 0, &threadId);
线程对象本身存在一个结构体CallbackData,其中callback指向了真实的业务路口。不同线程对象在初始化时,会被赋值不同的业务入口函数。
而在静态函数callableEntry中,通过调用this指针可以运行真正的业务函数。
ThreadImpl* pTI = reinterpret_cast<ThreadImpl*>(pThread);pTI->_callbackTarget.callback(pTI->_callbackTarget.pData);
最后用一段代码实例来结束吧
#include "Poco/Thread.h"#include "Poco/Runnable.h"#include <iostream>class HelloRunnable: public Poco::Runnable{ virtual void run() { std::cout << "Hello, world!" << std::endl; }};int main(int argc, char** argv){ HelloRunnable runnable; Poco::Thread thread; thread.start(runnable); thread.join(); return 0;}
- POCO C++库学习和分析 -- 线程 (一)
- POCO C++库学习和分析 -- 线程 (一)
- POCO C++库学习和分析 -- 线程 (二)
- POCO C++库学习和分析 -- 线程 (三)
- POCO C++库学习和分析 -- 线程 (四)
- POCO C++库学习和分析 -- 线程 (二)
- POCO C++库学习和分析 -- 线程 (三)
- POCO C++库学习和分析 -- 内存管理 (一)
- POCO C++库学习和分析 -- 日志 (一)
- POCO C++库学习和分析 -- 流 (一)
- POCO C++库学习和分析 -- 日志 (一)
- POCO C++库学习和分析 -- 内存管理 (一)
- POCO C++库学习和分析 -- 日志 (一)
- POCO C++库学习和分析 -- 日志 (一)
- POCO C++库学习和分析 -- 序
- POCO C++库学习和分析 -- 任务
- POCO C++库学习和分析 -- 进程
- POCO C++库学习和分析 -- 哈希
- Loadrunner使用遇到的问题总汇,不断更新~
- java获取网页内容
- java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
- Android address already in use
- 千头万绪不知从何说起
- POCO C++库学习和分析 -- 线程 (一)
- Linux下的Memcache安装方法
- How to Fix compstui.dll Error
- .NET中事务的隔离级别
- 迭代器模式(Iterator)
- CE下基于Zylonite硬件平台的SD卡驱动开发
- git cherry-pick + commit id 单独merge 任意一个branch的任意一个commit到本branch上
- 显示无法删除nul,参数不正确 的解决之道
- maven pom.xml详解