带有TimerQueue的EventLoop

       muduo的事件循环EventLoop可以完成:指定描述符上的事件监听及处理,指定时间的回调处理,用户向EventLoop发送任务并让其执行任务回调。

       几个关键的类如下:

       Poller:就是select/poll/epoll等IO复用功能的封装,用于监听指定事件集合的注册事件,并返回就绪的事件集合

       Channel:每一个Channel负责一个文件描述符fd但不拥有fd,主要负责记录fd的注册事件,就绪事件,回调函数,及执行fd上的事件回调

       Timer:定时器,封装了超时时间和超时的回调函数

       TimerQueue:定时器队列,用于管理定时器,具备插入定时器,删除定时器,重置定时器,找出超时的那部分定时器,执行超时定时器的超时回调。关键采用了timerfd

       EventLoop:通过Poller找出就绪的事件集合,再对集合中每个fd调用Channel执行事件回调。EventLoop通过TimerQueue实现定时回调功能,通过向TimerQueue添加定时器从而执行定时回调。EventLoop通过runInLoop实现执行用户回调任务功能,用户向EventLoop添加任务回调,若是其它线程向拥有此EventLoop的线程添加任务,那么任务将会添加到一个任务队列中,由于用户任务可能较紧急所以需要唤醒EventLoop,唤醒的。

#include<iostream>
#include<vector>
#include<map>
#include<utility>
#include<set>
#include<boost/noncopyable.hpp>
#include<boost/function.hpp>
#include<boost/bind.hpp>
#include<boost/scoped_ptr.hpp>
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/syscall.h>
#include<pthread.h>
#include<unistd.h>
#include<poll.h>
#include<errno.h>
#include<stdint.h>
#include<sys/timerfd.h>
#include<sys/time.h>
#include<sys/eventfd.h>
#include"Thread.hpp"//参见http://blog.csdn.net/liuxuejiang158blog/article/details/16332485
using namespace std;
using namespace boost;
# define UINTPTR_MAX       (4294967295U)//一个无符号大数
class Channel;//前向声明,事件分发器主要用于事件注册与事件处理(事件回调)
class Poller;//IO复用机制,主要功能是监听事件集合,即select,poll,epoll的功能
class Timestamp;
class TimerQueue;
/*
*事件循环,一个线程一个事件循环即one loop per thread,其主要功能是运行事件循环如等待事件发生然后处理发生的事件
*/
class EventLoop:noncopyable{
    public:
        typedef function<void()> TimerCallback;//定时器回调
        typedef function<void()> Functor;//回调函数
        EventLoop();
        ~EventLoop();
        void loop();//事件循环主体
        void quit();//终止事件循环,通过设定标志位所以有一定延迟
        void updateChannel(Channel* channel);//更新事件分发器Channel,完成文件描述符fd向事件集合注册事件及事件回调函数
        void assertInLoopThread(){//若运行线程不拥有EventLoop则退出,保证one loop per thread
            if(!isInLoopThread()){
                abortNotInLoopThread();
            }
        }
        bool isInLoopThread() const{return threadID_==syscall(SYS_gettid);}//判断运行线程是否为拥有此EventLoop的线程
        void runAt(const Timestamp& time,const TimerCallback& cb);//绝对时间执行定时器回调cb
        void runAfter(double delay,const TimerCallback& cb);//相对时间执行定时器回调
        void runEvery(double interval,const TimerCallback& cb);//每隔interval执行定时器回调
        //Timestamp pollReturnTime() const{return pollReturnTime_;}
        void runInLoop(const Functor& cb);//用于IO线程执行用户回调(如EventLoop由于执行事件回调阻塞了,此时用户希望唤醒EventLoop执行用户指定的任务)
        void queueInLoop(const Functor& cb);//唤醒IO线程(拥有此EventLoop的线程)并将用户指定的任务回调放入队列
        void wakeup();//唤醒IO线程
    private:
        void abortNotInLoopThread();//在不拥有EventLoop线程中终止
        void handleRead();//timerfd上可读事件回调
        void doPendingFunctors();//执行队列pendingFunctors中的用户任务回调
        typedef vector<Channel*> ChannelList;//事件分发器Channel容器,一个Channel只负责一个文件描述符fd的事件分发
        bool looping_;//事件循环主体loop是运行标志
        bool quit_;//取消循环主体标志
        const pid_t threadID_;//EventLoop的附属线程ID
        scoped_ptr<Poller> poller_;//IO复用器Poller用于监听事件集合
        ChannelList activeChannels_;//类似与poll的就绪事件集合,这里集合换成Channel(事件分发器具备就绪事件回调功能)
        //Timestamp pollReturnTime_;
        int wakeupFd_;//eventfd用于唤醒EventLoop所在线程
        scoped_ptr<Channel> wakeupChannel_;//通过wakeupChannel_观察wakeupFd_上的可读事件,当可读时表明需要唤醒EventLoop所在线程执行用户回调
        Mutex mutex_;//互斥量用以保护队列
        vector<Functor> pendingFunctors_;//用户任务回调队列
        scoped_ptr<TimerQueue> timerQueue_;//定时器队列用于存放定时器
        bool callingPendingFunctors_;//是否有用户任务回调标志
};

/*
*IO Multiplexing Poller即poll的封装,主要完成事件集合的监听
*/
class Poller:noncopyable{
    public:
        typedef vector<Channel*> ChannelList;//Channel容器(Channel包含了文件描述符fd和fd注册的事件及事件回调函数),Channel包含文件描述符及其注册事件及其事件回调函数,这里主要用于返回就绪事件集合
        Poller(EventLoop* loop);
        ~Poller();
        void Poll(int timeoutMs,ChannelList* activeChannels);//监听事件集合,通过activeChannels返回就绪事件集合
        void updateChannel(Channel* channel);//向事件集合中添加描述符欲监听的事件(channel中含有fd及其事件)
        void assertInLoopThread(){//判定是否和EventLoop的隶属关系,EventLoop要拥有此Poller
            ownerLoop_->assertInLoopThread();
        }
    private:
        void fillActiveChannels(int numEvents,ChannelList* activeChannels) const;//将就绪的事件添加到activeChannels中用于返回就绪事件集合
        typedef vector<struct pollfd> PollFdList;//struct pollfd是poll系统调用监听的事件集合参数
        typedef map<int,Channel*> ChannelMap;//文件描述符fd到IO分发器Channel的映射,通过fd可以快速找到Channel
        //注意:Channel中有fd成员可以完成Channel映射到fd的功能,所以fd和Channel可以完成双射
        EventLoop* ownerLoop_;//隶属的EventLoop
        PollFdList pollfds_;//监听事件集合
        ChannelMap channels_;//文件描述符fd到Channel的映射
};

/*
*事件分发器该类包含:文件描述符fd、fd欲监听的事件、事件的处理函数(事件回调函数)
*/
class Channel:noncopyable{
    public:
        typedef function<void()> EventCallback;//事件回调函数类型,回调函数的参数为空,这里将参数类型已经写死了
        Channel(EventLoop* loop,int fd);//一个Channel只负责一个文件描述符fd但Channel不拥有fd,可见结构应该是这样的:EventLoop调用Poller监听事件集合,就绪的事件集合元素就是Channel。但Channel的功能不仅是返回就绪事件,还具备事件处理功能
        void handleEvent();//处理事件回调
        void setReadCallBack(const EventCallback& cb){//可读事件回调
            readCallback=cb;
        }
        void setWriteCallback(const EventCallback& cb){//可写事件回调
            writeCallback=cb;
        }
        void setErrorCallback(const EventCallback& cb){//出错事件回调
            errorCallback=cb;
        }
        int fd() const{return fd_;}//返回Channel负责的文件描述符fd,即建立Channel到fd的映射
        int events() const{return events_;}//返回fd域注册的事件类型
        void set_revents(int revt){//设定fd的就绪事件类型,再poll返回就绪事件后将就绪事件类型传给此函数,然后此函数传给handleEvent,handleEvent根据就绪事件的类型决定执行哪个事件回调函数
            revents_=revt;
        }
        bool isNoneEvent() const{//fd没有想要注册的事件
            return events_==kNoneEvent;
        }
        void enableReading(){//fd注册可读事件
            events_|=kReadEvent;
            update();
        }
        void enableWriting(){//fd注册可写事件
            events_|=kWriteEvent;
            update();
        }
        int index(){return index_;}//index_是本Channel负责的fd在poll监听事件集合的下标,用于快速索引到fd的pollfd
        void set_index(int idx){index_=idx;}
        EventLoop* ownerLoop(){return loop_;}
    private:
        void update();
        static const int kNoneEvent;//无任何事件
        static const int kReadEvent;//可读事件
        static const int kWriteEvent;//可写事件

        EventLoop* loop_;//Channel隶属的EventLoop(原则上EventLoop,Poller,Channel都是一个IO线程)
        const int fd_;//每个Channel唯一负责的文件描述符,Channel不拥有fd
        int events_;//fd_注册的事件
        int revents_;//通过poll返回的就绪事件类型
        int index_;//在poll的监听事件集合pollfd的下标,用于快速索引到fd的pollfd
        EventCallback readCallback;//可读事件回调函数,当poll返回fd_的可读事件时调用此函数执行相应的事件处理,该函数由用户指定
        EventCallback writeCallback;//可写事件回调函数
        EventCallback errorCallback;//出错事件回调函数
};

/*
*时间戳,采用一个整数表示微秒数
*/
class Timestamp{
    public:
        Timestamp():microSecondsSinceEpoch_(0){}
        explicit Timestamp(int64_t microseconds):microSecondsSinceEpoch_(microseconds){}
        void swap(Timestamp& that){
            std::swap(microSecondsSinceEpoch_,that.microSecondsSinceEpoch_);
        }
        bool valid() const{return microSecondsSinceEpoch_>0;}
        int64_t microSecondsSinceEpoch() const {return microSecondsSinceEpoch_;}
        static Timestamp now(){
            struct timeval tv;
            gettimeofday(&tv, NULL);
            int64_t seconds = tv.tv_sec;
            return Timestamp(seconds * kMicroSecondsPerSecond + tv.tv_usec);
        }
        static Timestamp invalid(){return Timestamp();}
        static const int kMicroSecondsPerSecond=1000*1000;
    private:
        int64_t microSecondsSinceEpoch_;
};
//时间戳的比较
inline bool operator<(Timestamp lhs, Timestamp rhs)
{
  return lhs.microSecondsSinceEpoch() < rhs.microSecondsSinceEpoch();
}

inline bool operator==(Timestamp lhs, Timestamp rhs)
{
  return lhs.microSecondsSinceEpoch() == rhs.microSecondsSinceEpoch();
}
inline double timeDifference(Timestamp high, Timestamp low)
{
  int64_t diff = high.microSecondsSinceEpoch() - low.microSecondsSinceEpoch();
  return static_cast<double>(diff) / Timestamp::kMicroSecondsPerSecond;
}
inline Timestamp addTime(Timestamp timestamp, double seconds)
{
  int64_t delta = static_cast<int64_t>(seconds * Timestamp::kMicroSecondsPerSecond);
  return Timestamp(timestamp.microSecondsSinceEpoch() + delta);
}

/*
*定时器
*/
class Timer : boost::noncopyable
{
    public:
        typedef function<void()> TimerCallback;//定时器回调函数
        //typedef function<void()> callback;
        Timer(const TimerCallback& cb, Timestamp when, double interval)
            : callback_(cb),expiration_(when),interval_(interval),repeat_(interval > 0.0){}
        void run() const {//执行定时器回调
            callback_();
        }
        Timestamp expiration() const  { return expiration_; }//返回定时器的超时时间戳
        bool repeat() const { return repeat_; }//是否周期性定时
        void restart(Timestamp now);//重置定时器

     private:
        const TimerCallback callback_;
        Timestamp expiration_;
        const double interval_;
        const bool repeat_;
};
void Timer::restart(Timestamp now){
    if (repeat_){//周期定时
        expiration_ = addTime(now, interval_);
    }
    else{
        expiration_ = Timestamp::invalid();
    }
}

int createTimerfd(){//创建timerfd
    int timerfd = ::timerfd_create(CLOCK_MONOTONIC,TFD_NONBLOCK | TFD_CLOEXEC);
    if (timerfd < 0){
        printf("Timderfd::create() error\n");
    }
    return timerfd;
}
struct timespec howMuchTimeFromNow(Timestamp when){
    int64_t microseconds = when.microSecondsSinceEpoch()- Timestamp::now().microSecondsSinceEpoch();
    if (microseconds < 100){
        microseconds = 100;
    }
    struct timespec ts;
    ts.tv_sec = static_cast<time_t>(microseconds / Timestamp::kMicroSecondsPerSecond);
    ts.tv_nsec = static_cast<long>((microseconds % Timestamp::kMicroSecondsPerSecond) * 1000);
    return ts;
}
void readTimerfd(int timerfd, Timestamp now){//timerfd的可读事件回调
    uint64_t howmany;
    ssize_t n = ::read(timerfd, &howmany, sizeof howmany);
    if (n != sizeof howmany){
        printf("readTimerfd error\n");
    }
}
void resetTimerfd(int timerfd, Timestamp expiration)//重置timerfd的计时
{
    struct itimerspec newValue;
    struct itimerspec oldValue;
    bzero(&newValue, sizeof newValue);
    bzero(&oldValue, sizeof oldValue);
    newValue.it_value = howMuchTimeFromNow(expiration);
    int ret = ::timerfd_settime(timerfd, 0, &newValue, &oldValue);
    if (ret){
        printf("timerfd_settime erro\n");
    }
}

/*
*定时器队列
*/
class TimerQueue : boost::noncopyable
{
     public:
         typedef function<void()> TimerCallback;//定时器回调
        TimerQueue(EventLoop* loop);
        ~TimerQueue();
        void addTimer(const TimerCallback& cb,Timestamp when,double interval);//添加定时器到定时器队列中
     private:
        typedef pair<Timestamp, Timer*> Entry;//采用此作为键值
        typedef set<Entry> TimerList;//set只有key无value且有序

        void handleRead();//timerfd的可读回调
        void addTimerInLoop(Timer* timer);//添加定时器
        std::vector<Entry> getExpired(Timestamp now);//获取所有超时的定时器
        void reset(const std::vector<Entry>& expired, Timestamp now);//超时的定时器是否需要重新定时
        bool insert(Timer* timer);//插入定时器到队列中

        EventLoop* loop_;//TimerQueue所属的EventLoop
        const int timerfd_;//定时器队列本身需要在定时器超时后执行队列中所有超时定时器的回调
        Channel timerfdChannel_;//采用timerfdChannel_观察timerfd_的可读事件啊,当timerfd_可读表明定时器队列中有定时器超时
        TimerList timers_;//定时器队列
};
TimerQueue::TimerQueue(EventLoop* loop):loop_(loop),timerfd_(createTimerfd()),timerfdChannel_(loop, timerfd_),timers_()
{
    timerfdChannel_.setReadCallBack(bind(&TimerQueue::handleRead, this));
    timerfdChannel_.enableReading();//timerfd注册可读事件
}
TimerQueue::~TimerQueue(){
    ::close(timerfd_);
    for (TimerList::iterator it = timers_.begin();it != timers_.end(); ++it)
    {
        delete it->second;
    }
}
void TimerQueue::addTimer(const TimerCallback& cb,Timestamp when,double interval)//其它线程向IO线程添加用户回调时将添加操作转移到IO线程中去,从而保证线程安全one loop per thread
{//由EventLoop::runAt等函数调用
    Timer* timer = new Timer(cb, when, interval);
    loop_->runInLoop(bind(&TimerQueue::addTimerInLoop,this,timer));//通过EventLoop::runInLoop()->TimerQueue::queueInLoop()
    //runInLoop语义是若是本IO线程想要添加定时器则直接由addTimerInLoop添加,若是其它线程向IO线程添加定时器则需要间接通过queueInLoop添加
}
void TimerQueue::addTimerInLoop(Timer* timer){//IO线程自己向自己添加定时器
    loop_->assertInLoopThread();
    bool earliestChanged=insert(timer);//若当前插入的定时器比队列中的定时器都早则返回真
    if(earliestChanged){
        resetTimerfd(timerfd_,timer->expiration());//timerfd重新设置超时时间
    }
}
void TimerQueue::handleRead(){//timerfd的回调函数
    loop_->assertInLoopThread();
    Timestamp now(Timestamp::now());
    readTimerfd(timerfd_, now);
    std::vector<Entry> expired = getExpired(now);//TimerQueue::timerfd可读表明队列中有定时器超时,则需要找出那些超时的定时器
    for (std::vector<Entry>::iterator it = expired.begin();it!= expired.end(); ++it)//
    {
        it->second->run();//执行定时器Timer的超时回调
    }
    reset(expired, now);//查看已经执行完的超市定时器是否需要再次定时
}
std::vector<TimerQueue::Entry> TimerQueue::getExpired(Timestamp now)//获取队列中的超时的定时器(可能多个)
{
    std::vector<Entry> expired;
    Entry sentry = std::make_pair(now, reinterpret_cast<Timer*>(UINTPTR_MAX));
    TimerList::iterator it = timers_.lower_bound(sentry);//返回比参数小的下界,即返回第一个当前未超时的定时器(可能没有这样的定时器)
    //lower_bound(value_type& val)调用key_comp返回第一个不小于val的迭代器
    assert(it == timers_.end() || now < it->first);
    std::copy(timers_.begin(), it, back_inserter(expired));
    timers_.erase(timers_.begin(), it);
    return expired;//返回已经超时的那部分定时器
}

void TimerQueue::reset(const std::vector<Entry>& expired, Timestamp now)//已经执行完超时回调的定时器是否需要重置定时
{
    Timestamp nextExpire;
    for (std::vector<Entry>::const_iterator it = expired.begin();it != expired.end(); ++it)
    {
        if (it->second->repeat()){//需要再次定时
		it->second->restart(now);
            	insert(it->second);
        }
        else{//否则删除该定时器
        	delete it->second;
        }
    }
    if (!timers_.empty()){//为超时定时器重新定时后需要获取当前最小的超时时间给timerfd,以防重置的这些超市定时器中含有最小的超时时间
        nextExpire = timers_.begin()->second->expiration();
    }
    if (nextExpire.valid()){
        resetTimerfd(timerfd_, nextExpire);//重置timerfd的超时时间
    }
}
bool TimerQueue::insert(Timer* timer)//向超时队列中插入定时器
{
    bool earliestChanged = false;
    Timestamp when = timer->expiration();
    TimerList::iterator it = timers_.begin();
    if (it == timers_.end() || when < it->first)
    {
        earliestChanged = true;//当前插入的定时器是队列中最小的定时器,此时外层函数需要重置timerfd的超时时间
    }
    std::pair<TimerList::iterator, bool> result=timers_.insert(std::make_pair(when, timer));
    assert(result.second);
    return earliestChanged;
}

/*
*EventLoop成员实现
*/
__thread EventLoop* t_loopInThisThread=0;//线程私有数据表示线程是否拥有EventLoop
const int kPollTimeMs=10000;//poll等待时间
static int createEventfd(){//创建eventfd,eventfd用于唤醒
    int evtfd=eventfd(0,EFD_NONBLOCK|EFD_CLOEXEC);
    if(evtfd<0){
        printf("Failed in eventfd\n");
        abort();
    }
    return evtfd;
}
EventLoop::EventLoop()
    :looping_(false),
    quit_(false),
    threadID_(syscall(SYS_gettid)),
    poller_(new Poller(this)),
    timerQueue_(new TimerQueue(this)),//EventLoop用于一个定时器队列
    wakeupFd_(createEventfd()),
    wakeupChannel_(new Channel(this,wakeupFd_)),//通过Channel观察wakeupFd_
    callingPendingFunctors_(false)
{
    if(!t_loopInThisThread){
        t_loopInThisThread=this;//EventLoop构造时线程私有数据记录
    }
    wakeupChannel_->setReadCallBack(bind(&EventLoop::handleRead,this));//设置eventfd的回调
    wakeupChannel_->enableReading();//eventfd的可读事件
}
EventLoop::~EventLoop(){
    assert(!looping_);
    close(wakeupFd_);
    t_loopInThisThread=NULL;//EventLoop析构将其置空
}
void EventLoop::loop(){//EventLoop主循环,主要功能是监听事件集合,执行就绪事件的处理函数
    assert(!looping_);
    assertInLoopThread();
    looping_=true;
    quit_=false;
    while(!quit_){
        activeChannels_.clear();
        poller_->Poll(kPollTimeMs,&activeChannels_);//activeChannels是就绪事件
        for(ChannelList::iterator it=activeChannels_.begin();it!=activeChannels_.end();it++){
            (*it)->handleEvent();//处理就绪事件的回调函数,处理事件回调
        }
        doPendingFunctors();//处理用户任务回调
    }
    looping_=false;
}
void EventLoop::quit(){
    quit_=true;//停止主循环标志,主循环不会马上停止有延迟
    if(!isInLoopThread()){
        wakeup();//其它线程唤醒EventLoop线程且终止它
    }
}
void EventLoop::updateChannel(Channel* channel){//主要用于文件描述符添加到poll的监听事件集合中
    assert(channel->ownerLoop()==this);
    assertInLoopThread();
    poller_->updateChannel(channel);
}
void EventLoop::abortNotInLoopThread(){
    printf("abort not in Loop Thread\n");
    abort();//非本线程调用强行终止
}
void EventLoop::runAt(const Timestamp& time, const TimerCallback& cb)//绝对时间执行回调
{
    timerQueue_->addTimer(cb, time, 0.0);
}
void EventLoop::runAfter(double delay, const TimerCallback& cb)//相对时间执行回调
{
    Timestamp n=Timestamp::now();
    Timestamp time(addTime(Timestamp::now(), delay));
    runAt(time, cb);
}
void EventLoop::runEvery(double interval, const TimerCallback& cb)//周期性回调
{
    Timestamp time(addTime(Timestamp::now(), interval));//Timestamp::addTime
    timerQueue_->addTimer(cb, time, interval);
}
void EventLoop::runInLoop(const Functor& cb){
    if(isInLoopThread()){//本IO线程调用则直接执行执行用户回调
        cb();
    }
    else{//其它线程调用runInLoop则向用户回调队列添加,保证线程安全one loop per thread
        queueInLoop(cb);
    }
}
void EventLoop::queueInLoop(const Functor& cb){
    {
        MutexLockGuard lock(mutex_);//互斥量保护用户回调队列
        pendingFunctors_.push_back(cb);
    }
    if(!isInLoopThread()||callingPendingFunctors_){
        wakeup();//其它线程添加用户回调任务或者EventLoop的IO线程正在处理用户任务回调时,若阻塞则唤醒IO线程
    }
}
void EventLoop::handleRead(){//eventfd可读回调
    uint64_t one=1;
    ssize_t n=read(wakeupFd_,&one,sizeof(one));
    if(n!=sizeof(one)){
        printf("EventLoop::handleRead() error\n");
    }
}
void EventLoop::doPendingFunctors(){//执行用户任务回调
    vector<Functor> functors;
    callingPendingFunctors_=true;
    {
        MutexLockGuard lock(mutex_);
        functors.swap(pendingFunctors_);//采用swap而不是在这里执行回调是为了缩小临界区
    }
    for(size_t i=0;i<functors.size();i++){
        functors[i]();
    }
    callingPendingFunctors_=false;
}
void EventLoop::wakeup(){
    uint64_t one=1;
    ssize_t n=write(wakeupFd_,&one,sizeof(one));//通过eventfd通知
    if(n!=sizeof(one)){
        cout<<n<<" "<<strerror(errno)<<endl;
        printf("EventLoop::wakeup() write error\n");
    }
}

/*
*Poller成员实现
*/
Poller::Poller(EventLoop* loop):ownerLoop_(loop){}//Poller明确所属的EventLoop
Poller::~Poller(){}
void Poller::Poll(int timeoutMs,ChannelList* activeChannels){
    int numEvents=poll(&*pollfds_.begin(),pollfds_.size(),timeoutMs);//poll监听事件集合pollfds_
    if(numEvents>0){
        fillActiveChannels(numEvents,activeChannels);//将就绪的事件添加到activeChannels
    }
    else if(numEvents==0){
    }
    else{
        printf("Poller::Poll error\n");
    }
}
void Poller::fillActiveChannels(int numEvents,ChannelList* activeChannels) const{//将就绪事件通过activeChannels返回
    for(PollFdList::const_iterator pfd=pollfds_.begin();pfd!=pollfds_.end()&&numEvents>0;++pfd){
        if(pfd->revents>0){
            --numEvents;//若numEvents个事件全部找到就不需要再遍历容器剩下的部分
            ChannelMap::const_iterator ch=channels_.find(pfd->fd);
            assert(ch!=channels_.end());
            Channel* channel=ch->second;
            assert(channel->fd()==pfd->fd);
            channel->set_revents(pfd->revents);
            activeChannels->push_back(channel);
        }
    }
}
void Poller::updateChannel(Channel* channel){
    assertInLoopThread();
    if(channel->index()<0){//若channel的文件描述符fd没有添加到poll的监听事件集合中
        assert(channels_.find(channel->fd())==channels_.end());
        struct pollfd pfd;
        pfd.fd=channel->fd();
        pfd.events=static_cast<short>(channel->events());
        pfd.revents=0;
        pollfds_.push_back(pfd);
        int idx=static_cast<int>(pollfds_.size())-1;
        channel->set_index(idx);
        channels_[pfd.fd]=channel;
    }
    else{//若已经添加到监听事件集合中,但是需要修改
        assert(channels_.find(channel->fd())!=channels_.end());
        assert(channels_[channel->fd()]==channel);
        int idx=channel->index();
        assert(0<=idx&&idx<static_cast<int>(pollfds_.size()));
        struct pollfd& pfd=pollfds_[idx];
        assert(pfd.fd==channel->fd()||pfd.fd==-1);
        pfd.events=static_cast<short>(channel->events());//修改注册事件类型
        pfd.revents=0;
        if(channel->isNoneEvent()){
            pfd.fd=-1;//若无事件则poll忽略
        }
    }
}
/*
*Channel成员实现
*/
const int Channel::kNoneEvent=0;//无事件
const int Channel::kReadEvent=POLLIN|POLLPRI;//可读事件
const int Channel::kWriteEvent=POLLOUT;//可写事件
Channel::Channel(EventLoop* loop,int fdArg):loop_(loop),fd_(fdArg),events_(0),revents_(0),index_(-1){}
void Channel::update(){//添加或修改文件描述符的事件类型
    loop_->updateChannel(this);
}
void Channel::handleEvent(){//处理就绪事件的处理函数
    if(revents_&POLLNVAL){
        printf("Channel::handleEvent() POLLNVAL\n");
    }
    if(revents_&(POLLERR|POLLNVAL)){//出错回调
        if(errorCallback)
            errorCallback();
    }
    if(revents_&(POLLIN|POLLPRI|POLLRDHUP)){//可读回调
        if(readCallback)
            readCallback();
    }
    if(revents_&POLLOUT){//可写回调
        if(writeCallback)
            writeCallback();
    }
}

/*
*开启一个线程执行一个EventLoop,这才是one loop per thread
*/
class EventLoopThread:noncopyable{
    public:
        EventLoopThread():loop_(NULL),exiting_(false),thread_(bind(&EventLoopThread::threadFunc,this)),
                mutex_(),cond_(mutex_){}
        ~EventLoopThread(){
            exiting_=true;
            loop_->quit();
            thread_.join();
        }
        EventLoop* startLoop(){
            //assert(!thread_.started());
            thread_.start();
            {
                MutexLockGuard lock(mutex_);
                while(loop_==NULL){
                    cond_.wait();
                }
            }
            return loop_;
        }
    private:
        void threadFunc(){
            EventLoop loop;
            {
                MutexLockGuard lock(mutex_);
                loop_=&loop;
                cond_.notify();
            }
            loop.loop();
        }
        EventLoop* loop_;
        bool exiting_;
        Thread thread_;
        Mutex mutex_;
        Condition cond_;
};

/*
*测试代码
*/
/*1
void runInThread()
{
  printf("runInThread(): pid = %d, tid = %d\n",getpid(), syscall(SYS_gettid));
}

int main()
{
  printf("main(): pid = %d, tid = %d\n",getpid(), syscall(SYS_gettid));

  EventLoopThread loopThread;
  EventLoop* loop = loopThread.startLoop();
  loop->runInLoop(runInThread);
  sleep(1);
  loop->runAfter(2, runInThread);
  sleep(3);
  loop->quit();

  printf("exit main().\n");
}
*/


执行结果:

main(): pid = 3178, tid = 3178
runInThread(): pid = 3178, tid = 3179
runInThread(): pid = 3178, tid = 3179
exit main().

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值