源码下载以及安装点击链接https://blog.csdn.net/YoungSusie/article/details/90021742
EventLoop class 新增了quit() 成员函数,可以终止事件循环,令标志变量quit_ 的值为 true 即可,但是调用quit() 并不是立马起作用,而是在下一次检查 loop() 的while(!quit_) 的时候起效。 如果EventLoop::loop 正阻塞在某个调用中,quit() 不会立刻生效。
1、学习笔记
- EventLoop 通过 scoped_ptr 间接持有Poller ,因此EventLoop.h 不需要包含 Poller.h 头文件;只需要向前声明 Poller class。因此,EventLoop 的析构函数必须在EventLoop.cc 中显示定义。
- 智能指针
scoped_ptr ,独享其管理权,不支持赋值,管理的对象在离开作用域之后会主动释放。 - 一定要注意class 函数的声明,private public protect 等区别,如果将留给外界的接口声明为private ,编译的时候会报错。同时要注意区别类对象调用类成员/成员函数 与 指向类额指针调用 的区别。 敲代码的时候一定要特别注意。
==================================EventLoop.cc ====================================
#include "EventLoop.h"
#include "Channel.h"
#include "Poller.h"
#include <assert.h>
#include <poll.h>
using namespace std;
__thread EventLoop * t_LoopInThisThread = 0;
EventLoop::EventLoop()
:looping_(false),
quit_(false),
threadId_(gettid()),
poller_(new Poller(this))
{
cout << "EventLoop created" << this << " in thread " << threadId_ << "\n";
t_LoopInThisThread = this;
}
EventLoop::~EventLoop()
{
assert(!looping_);
t_LoopInThisThread = NULL;
}
void EventLoop::loop()
{
assert(!looping_);
looping_ = true;
quit_ = false;
while(!quit_){
activeChannels_.clear();
poller_->poll(&activeChannels_);
for(ChannelList::iterator it = activeChannels_.begin(); it != activeChannels_.end();++it){
(*it)->handleEvent();
}
}
std::cout << "EVentLoop loop " << this << " stop looping";
looping_ = false;
}
void EventLoop::quit()
{
quit_ = true;
}
void EventLoop::updateChannel(Channel * channel)
{
assert(channel->ownerLoop() == this);
poller_->updateChannel(channel);
}
==================================EventLoop.h ====================================
#ifndef _EVENTLOOP_H
#define _EVENTLOOP_H
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <iostream>
#include <vector>
pid_t gettid(void);
class Channel;
class Poller;
class EventLoop : boost::noncopyable
{
public:
EventLoop();
~EventLoop();
void loop();
void quit();
void updateChannel(Channel * channel);
/*void assertInLoopThread()
{
if (!isInLoopThread())
{
abortNotInLoopThread();
}
}*/
bool isInLoopThread() const
{
return threadId_ == gettid();
}
private:
// void abortNotInLoopThread;
typedef std::vector<Channel *> ChannelList;
bool looping_;
bool quit_;
const pid_t threadId_;
boost::scoped_ptr<Poller> poller_;
ChannelList activeChannels_;
};
#endif
=================================== gettid.cc =======================================
#include "EventLoop.h"
pid_t gettid()
{
return static_cast<pid_t>(syscall( __NR_gettid));
}
=================================== Makefile =======================================
LIB_SRC = EventLoop.cc Gettid.cc Channel.cc Poller.cc
BINARIES = test3
all: $(BINARIES)
CXXFLAGS = -O0 -g -Wall -I -pthread
LDFLAGS = -lpthread
$(BINARIES):
g++ $(CXXFLAGS) -o $@ $(LIB_SRC) $(filter %.cc,$^) $(LDFLAGS)
clean:
rm -f $(BINARIES) core
test3: test3.cc
=================================== test3.cc=======================================
#include "Channel.h"
#include "EventLoop.h"
#include <stdio.h>
#include <sys/timerfd.h>
EventLoop* g_loop;
void timeout()
{
printf("Timeout!\n");
g_loop->quit();
}
int main()
{
EventLoop loop;
g_loop = &loop;
int timerfd = ::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
Channel channel(&loop, timerfd);
channel.setReadCallback(timeout);
channel.enableReading();
struct itimerspec howlong;
bzero(&howlong, sizeof howlong);
howlong.it_value.tv_sec = 5;
::timerfd_settime(timerfd, 0, &howlong, NULL);
loop.loop();
::close(timerfd);
}
将以上的代码在一个文件夹下编译。