一. Reactor模式簡介
Reactor釋義“反應堆”,是一種事件驅動機制。和普通函數調用的不同之處在於:應用程序不是主動的調用某個API完成處理,而是恰恰相反,Reactor逆置了事件處理流程,應用程序需要提供相應的接口並注冊到Reactor上,如果相應的時間發生,Reactor將主動調用應用程序注冊的接口,這些接口又稱為“回調函數”。
二. moduo庫Reactor模式的實現
muduo主要通過3個類來實現Reactor模式:EventLoop,Channel,Poller。
1. EventLoop
事件循環。moduo的線程模型為one loop per thread,即每個線程只能有一個EventLoop對象。EventLoop對象的生命周期通常和其所屬的線程一樣長。
數據成員:
const pid_t threadId_;保存當前EventLoop所屬線程id
boost::scoped_ptr poller_; 實現I/O復用 boost::scoped_ptr timerQueue_;
int wakeupFd_;
boost::scoped_ptr wakeupChannel_; 用於處理wakeupFd_上的可讀事件,將事件分發到handlRead() ChannelList activeChannels_; 有事件就緒的 Channel Channel* currentActiveChannel_;
MutexLock mutex_; pendingFunctors_回暴露給其他線程,所以需要加鎖 std::vectorpendingFunctors_;
主要功能函數:
loop(),在該函數中會循環執行以下過程:調用Poller::poll(),通過此調用獲得一個vector<channel*>activeChannels_的就緒事件集合,再遍歷該容器,執行每個Channel的Channel::handleEvent()完成相應就緒事件回調,最後執行pendingFunctors_排隊的函數。上述一次循環就是一次Reactor模式完成。
runInLoop(boost::function<void()>),實現用戶指定任務回調,若是EventLoop隸屬的線程調用EventLoop::runInLoop()則EventLoop馬上執行;若是其它線程調用則執行EventLoop::queueInLoop(boost::function<void()>將任務添加到隊列中(線程轉移)。EventLoop如何獲得有任務這一事實呢?通過eventfd可以實現線程間通信,具體做法是:其它線程向EventLoop::vector<boost::function<void()> >添加任務T,然後通過EventLoop::wakeup()向eventfd寫一個int,eventfd的回調函數EventLoop::handleRead()讀取這個int,從而相當於EventLoop被喚醒,此時loop中遍歷隊列執行堆積的任務。這裡采用Channel管理eventfd,Poller偵聽eventfd體現了eventfd可以統一事件源的優勢。