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


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更恰當些。

先來看下它的具體定義。

   1: struct ThreadContext
   2: {
   3:     WorkerContext* mWorkerContext;
   4:  
   5:     WorkQueue* mWorkQueue;
   6:     uint32_t   mNodeMask;
   7:     uint32_t   mProcessorMask;
   8:     bool       mRunning;
   9:     bool       mStarted;
  10:     Thread*    mThread;
  11: };

這里有2個東西可能比較困惑。一是,WorkerContext;二是,WorkQueue。除此以外,應該沒有不難理解的東西。WorkerContext和WorkQueue暫時先擱置下,等講到ThreadPool線程池的時候我們再來說這兩個東西。

ThreadPool class

說到ThreadPool,我想大家應該都不怎么陌生。在操作系統級別都提供了線程池相關的函數。這里需要強調一點的是,Theron中線程池中的線程不是Thread而是ThreadContext。為什么這么說?等到說Framework類的時候,你就更清楚了。

ThreadPool是一個模版類。

   1: template <class WorkQueue, class WorkProcessor, class WorkerContext>
   2: class ThreadPool;

這個類在Framework類中被這樣使用:

   1: typedef ThreadSafeQueue<Mailbox> WorkQueue;
   2: 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是這樣定義的:

   1: void ThreadEntryPoint(void* context)
   2: {
   3:     ThreadContext* threadContext(reinterpret_cast<ThreadContext*>(context));
   4:  
   5:     threadContext->mStarted = true;
   6:  
   7:     uint32_t backoff(0);
   8:     while (threadContext->mRunning)
   9:     {
  10:         if (typename WorkQueue::ItemType* item = threadContext->mWorkQueu->Pop())
  11:         {
  12:             WorkProcessor::Process(item, threadContext->mWorkerContext);
  13:             backoff = 0;
  14:         }
  15:         else
  16:         {
  17:             Utils::Backoff(backoff);
  18:         }
  19:     }
  20: }

ItemType就是Mailbox。WorkProcessor在這里是WorkItem類。至於WorkItem::Process到底做了什么事情,還是留等后面我們對Theron了解更深入了之后再進行深入分析。這里你只要知道線程池道理這里就是逐一處理Mailbox里的信息了。

另外,這里還要注意的一個點是這里的while是一個死循環。所以當線程池把線程啟動之后,除非特定操作,不然這個線程是不會退出的。

線程池類還提供了StopThread和DestroyThread兩個函數,這里就不多做介紹了。

WorkerThreadStore and ProcessorContext

這兩個結構放到后面再議。

說完了線程相關的內容,我們開始介紹Theron中和Actor Model概念有密切聯系的幾個類。先說Framework。

先到這里。。。未完待續。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM