muduo線程的啟動

來源:互聯網
上載者:User

上篇說了多執行緒的概述,這篇說說具體實現。

muduo的多線程是由線程池中啟動的。線程池類EventLoopThreadPool在TcpServer類中建立一個心得執行個體。發現在muduo中,各種類的關係基本上引用和包含即組合關係,很少有派生關係的,沒有繼承關係就沒有虛函數的應用了。

可能陳碩覺得繼承關係比較複雜,耦合度太高,破壞整體設計。但是我覺得muduo中那麼多不同種類的智能指標,還有基於boost或std的函數綁定,本身就夠複雜的了。所以我打算有時間用c語言來改寫一下muduo,把那些智能指標,函數綁定等弱化,只關注網路架構本身。不過說實話,muduo本身就是基於C++的,用智能指標和函數綁定很正常,而且人家還用得非常到位。所以要想往C++方面發展,還是得精通上面的知識。我本身是搞C++,而且搞了很久,而且決定一直搞下去。不過在接觸c項目,指令碼語言,還有現代網路並發語言golang之後,還是覺得用C++寫項目開發效率太低了,而且很難駕馭,指標就是一個雷區。精通C++的時間與其收穫性價比是很低的,所以我決定以後不再畫太多的時間在C++上,對於C++項目,我只是關注其架構本身。

好了廢話少說。EventLoopThreadPool的start在TcpServer的start中調用,他會建立n個線程並啟動,n是EventLoopThreadPool的成員變數,可以配置,也可以是0個。每個線程是EventLoopThread的執行個體。而EventLoopThread有個組合對象Thread,他才是線程建立和啟動真正的地方。代碼如下:

void TcpServer::start(){  if (started_.getAndSet(1) == 0)  {    threadPool_->start(threadInitCallback_);    assert(!acceptor_->listenning());    loop_->runInLoop(        std::bind(&Acceptor::listen, get_pointer(acceptor_)));  }}
void EventLoopThreadPool::start(const ThreadInitCallback& cb){  assert(!started_);  baseLoop_->assertInLoopThread();  started_ = true;  for (int i = 0; i < numThreads_; ++i)  {    char buf[name_.size() + 32];    snprintf(buf, sizeof buf, "%s%d", name_.c_str(), i);    EventLoopThread* t = new EventLoopThread(cb, buf);    threads_.push_back(std::unique_ptr<EventLoopThread>(t));    loops_.push_back(t->startLoop());  }  if (numThreads_ == 0 && cb)  {    cb(baseLoop_);  }}
void Thread::start(){  assert(!started_);  started_ = true;  // FIXME: move(func_)  detail::ThreadData* data = new detail::ThreadData(func_, name_, &tid_, &latch_);  if (pthread_create(&pthreadId_, NULL, &detail::startThread, data))  {    started_ = false;    delete data; // or no delete?    LOG_SYSFATAL << "Failed in pthread_create";  }  else  {    latch_.wait();    assert(tid_ > 0);  }}

Thread的線程函數已經綁定在了EventLoopThread::threadFunc裡,這個是在EventLoopThread建構函式是初始化的。代碼如下:

void EventLoopThread::threadFunc(){  EventLoop loop;  if (callback_)  {    callback_(&loop);  }  {    MutexLockGuard lock(mutex_);    loop_ = &loop;    cond_.notify();  }  loop.loop();  //assert(exiting_);  loop_ = NULL;}

這裡有個問題是,主線程會加入新線程的loop執行個體,而這個loop執行個體又是線上程的線程函數裡建立的。所以很顯然主線程和新線程有個同步的過程,並且多個新線程之間有臨界區的問題。這些是用條件變數pthread_cond_t和互斥變數mutext來實現的。

新線程線程函數在棧上申明一個EventLoop對象之後,便通知主線程了。這使得主線程返回,而新線程函數中loop開始運作迴圈了。那麼主線程又是如何跨線程調用新線程的函數的呢?這個下篇再說。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.