您的位置:首页 > 编程语言 > C语言/C++

Theron, a lightweight C++ concurrency library, 源码分析(一)

2012-12-03 22:43 399 查看
Theron是一个基于Actor Model的轻量级C++并行库(Theron is a fast, portable, lightweight C++ concurrency library based on Actor Model)。

在分析Theron源代码前,先简单说一说Actor Model到底是一个什么东西。

Actor Model

Actor Model是一种并发模型,详细的信息你可以在wiki上找到。如果你觉得英文比较难理解,也可以看看老赵的博客,他写了3篇关于Actor Model的博文(123)。可以说,看完这三篇文章,你应该能够对Actor Model建立一个直观的认识。

我个人觉得并行编程的模型强调了一点,不要使用简单的线程来解决并发的问题,因为不容易处理好锁与锁之间的关系。要从整体业务上来考虑问题,以一个一个关联不是很紧密的流程为基础来进行并发。也就是说,以task为基础进行并发。

说到这,前戏算是完了,我们进入正题。。。。

在Theron中,或者说在Actor Model中有几个重要的概念,它们分别是:

Actor

Message

Address

Mailbox

Actor就不多说了。在Actor Model中,万事万物皆actor。和面向对象中强调万事万物皆对象是一样的。

Message就是消息吧。在Actor Model中,actor与actor之间通过消息进行通信。那么actor如何将指定的消息发送给它想通知的其他actor呢?靠Address。

Address就是地址,更严格地说是mailbox的地址。Actor和actor只能通过地址相互通信。因此,如果两个actors相互不知道对方的地址,那么它们就无法相互发送消息。接收消息的actor可以从message中提取到发信actor的地址。

Mailbox就是邮箱,用来存放收到的消息。

所以,Actor Model可以形象地理解成人和人之间相互寄信。人就是actor,信就是message,家庭地址就是address,邮箱就是mailbox,信封上有寄信人的地址。也正因为这种类比,我们可以想象:

不同actor之间是并行执行的

Actor可以顺序执行收到的消息,也可以并行执行。一般来说,顺序执行比较容易实现

在Theron中,除了上面4个重要的类之外,还有一个类也很重要,就是Framework类。事实上他有点像邮局。

既然Theron是一个并发库,那势必还要有线程相关的类。直接和线程相关的有4个,他们分别是:

Thread

ThreadContext

WorkerThreadStore

ThreadPool

间接关联的有一个:

ProcessorContext

我们先从线程相关的类开始说起。

Thread and ThreadPool

Thread class

根据运行环境的不同,Theron通过宏定义区别出了3种实现Thread类的方法,分别是:

基于Win32 API的实现

基于boost::thread的实现

基于C++11 std::thread的实现

你要定义一个具体的业务处理函数,该函数会在特定实现中的线程里被调用。

主要的几个成员函数是:

Start(EntryPoint entryPoint, void* context)

Join

ThreadContext struct

这个结构是ThreadPool中的内部被定义的。所以可以知道它和ThreadPool的关系要比Thread类和ThreadPool的关系来得更紧密。事实上也是这样的。ThreadPool所管理的具体线程事实上是通过ThreadConext来进行的。所以确切地说,线程池中的线程在这里指ThreadContext更恰当些。

先来看下它的具体定义。

struct ThreadContext


{


WorkerContext* mWorkerContext;




 WorkQueue* mWorkQueue;


 uint32_t mNodeMask;


 uint32_t mProcessorMask;


 bool mRunning;


 bool mStarted;


 Thread*mThread;


};


这里有2个东西可能比较困惑。一是,WorkerContext;二是,WorkQueue。除此以外,应该没有不难理解的东西。WorkerContext和WorkQueue暂时先搁置下,等讲到ThreadPool线程池的时候我们再来说这两个东西。

ThreadPool class

说到ThreadPool,我想大家应该都不怎么陌生。在操作系统级别都提供了线程池相关的函数。这里需要强调一点的是,Theron中线程池中的线程不是Thread而是ThreadContext。为什么这么说?等到说Framework类的时候,你就更清楚了。

ThreadPool是一个模版类。

template <class WorkQueue, class WorkProcessor, class WorkerContext>


class ThreadPool;


这个类在Framework类中被这样使用:

typedef ThreadSafeQueue<Mailbox> WorkQueue;


typedef ThreadPool<WorkQueue, WorkItem, WorkerThreadStore> ThreadPool;


所以,ThreadContext中的WorkQueue就是ThreadSafeQueue<Mailbox>类型,WorkerContxt就是WorkerThreadStore类型。WorkerThreadStore会在后面介绍,现在你可以认为他是工作线程保存相关信息的一个storage。

ThreadPool提供了几个重要的成员函数。

CreateThread(ThreadContext* threadContext)

创建一个Thread对象并把句柄保存到threadContext->mThread中。

StartThread(ThreadContext* threadContext, WorkQueue* workQueue, …)

启动线程。总共4个参数,这里罗列了前两个最重要的。

StartThread将workQueue保存到threadContext->mWorkQueue中,然后通过threadContext->mThread->Start启动线程,在线程中处理workQueue中的mailbox。

传递给Start函数的第一个参数EntryPoint是这样定义的:

void ThreadEntryPoint(void* context)


{


 ThreadContext* threadContext(reinterpret_cast<ThreadContext*>(context));




 threadContext->mStarted = true;




 uint32_t backoff(0);


 while (threadContext->mRunning)


{


 if (typename WorkQueue::ItemType* item = threadContext->mWorkQueu->Pop())


{


 WorkProcessor::Process(item, threadContext->mWorkerContext);


 backoff = 0;


}


 else


{


 Utils::Backoff(backoff);


}


}


}


ItemType就是Mailbox。WorkProcessor在这里是WorkItem类。至于WorkItem::Process到底做了什么事情,还是留等后面我们对Theron了解更深入了之后再进行深入分析。这里你只要知道线程池道理这里就是逐一处理Mailbox里的信息了。

另外,这里还要注意的一个点是这里的while是一个死循环。所以当线程池把线程启动之后,除非特定操作,不然这个线程是不会退出的。

线程池类还提供了StopThread和DestroyThread两个函数,这里就不多做介绍了。

WorkerThreadStore and ProcessorContext

这两个结构放到后面再议。

说完了线程相关的内容,我们开始介绍Theron中和Actor Model概念有密切联系的几个类。先说Framework。

先到这里。。。未完待续。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: