个人网站的首页,wordpress怎么清空所有内容,九江网站建设制作,浙江建设工程信息网站项目完整在#xff1a; 文章目录 一、eventloop模块#xff1a;进行事件监控#xff0c;以及事件处理的模块二、提供的功能三、实现思想#xff08;一#xff09;功能#xff08;二#xff09;意义#xff08;三#xff09;功能设计 四、框架五、代码 一、eventloop模…项目完整在 文章目录 一、eventloop模块进行事件监控以及事件处理的模块二、提供的功能三、实现思想一功能二意义三功能设计 四、框架五、代码 一、eventloop模块进行事件监控以及事件处理的模块 进行事件监控管理的模块这个模块就是我们所说的One thread one loop 中的loop也就是我们所说的Reactor这个模块必定是一个模块对于一个线程
二、提供的功能
这个模块和线程是一一对应的 监听了一个链接如果这个连接一旦就绪就要进行事件处理 但是如果这个描述符在多个线程中都触发了了事件进行处理就会存在线程安全问题 因此我们需要将一个链接的事件监控 以及连接事件处理以及其他操作都放在同一个线程中 如何保证一个连接的所有操作都在eventloop对应的线程中 给eventLOOP模块中都添加一个任务队列 对连接的所有操作都进行一次封装将对连接的操作当作任务都添加到任务队列中
三、实现思想
一功能
在线程中对描述符进行事件监控有描述符就绪则对描述符进行事件处理如何保证处理回调函数中的操作都在线程中所有的就绪事件处理完了这时候再去将任务队列中的所有任务一一执行 这样能够保证对于所有链接的所有操作都是在一个线程中进行的不涉及线程安全问题 但是对于任务队列中的操作有线程安全的问题只需要给task的操作架一把锁即可
二意义
对于服务器的所有事件都是由EventLoop模块来完成 每一个Connection连接都会绑定一个EventLoop模块和线程因为外界对于连接的所有操作都要放到同一个线程中进行
三功能设计
事件监控 使用Poller模块 有事件就绪则进行事件处理执行任务队列中的任务 注意点 因为有可能因为等待描述符IO事件就绪执行流流程阻塞这个时候任务对立中的任务得不到执行 因此得有一个事件通知的东西能够唤醒事件监控的阻塞 当事件就绪需要处理的时候处理过程中如果对连接要进行某些操作 这些操作必须要在Eventloop对应的线程中进行保证对连接的各项操作都是线程安全的。如果执行的操作就在本线程中不需要将操作压入队列了可以直接执行如果执行的操作不在线程中才需要加入任务池等到事件处理完了之后就行执行任务
四、框架 class Eventloop {
private:std::thread::id _thread_id; // 线程IDint _event_fd // eventfd 唤醒IO事件监控有可能的阻塞Poller _poller; // 进行所有描述符的事件监控using Functor std::functionvoid();std::vectorFunctor _task; // 任务池std::mutex _mutex; // 实现任务池操作的线程安全
public:void runAllTask();
public:Eventloop();void runInLoop(const Functorcb); // 判断将要执行的任务是否处于当前线程中如果是则执行不是则压入队列。void queueInLoop(const Functorcb); // 将操作压入任务池bool isInLoop(); //永远判断当前线程是否是EventLoop所对应的线程void updateEvent(Channel* channel); // 添加/修改描述符的事件监控void removeEvent(Channel* channel); // 移除描述符的监控void Start(); // 任务监控完毕进行处理任务 三步走事件监控-》就绪事件处理-》执行任务};五、代码 class EventLoop {
private:using Functor std::functionvoid();std::thread::id _thread_id; // 线程IDint _event_fd; // eventfd 唤醒IO事件监控有可能的阻塞std::unique_ptrChannel _event_channel; Poller _poller;//进行所有描述符的事件监控std::vectorFunctor _tasks; // 任务池std::mutex _mutex; // 实现任务池操作的线程安全TimerWheel _timer_wheel;//定时器模块
public: // 执行任务池中的所有任务void runAllTask() {std::vectorFunctor functor; {std::unique_lockstd::mutex _lock(_mutex); // 出了作用域锁就会被解开_tasks.swap(functor);}for (auto f : functor) {f();}return ;}static int createEventFd() {int efd eventfd(0,EFD_CLOEXEC | EFD_NONBLOCK);if (efd 0) {ERR_LOG(CREATE ENVENTED FAILED !!!);abort();}return efd;}void readEventfd() {uint64_t res 0;int ret read(_event_fd,res,sizeof(res));if (ret 0) {if (errno EINTR || errno EAGAIN) {return;}ERR_LOG(READ EVENTFD FAILED!);abort();}return ;}void weakEventFd() {uint64_t val 1;int ret write(_event_fd,val,sizeof(val));if (ret 0) {if (errno EINTR) {return;}ERR_LOG(READ EVENTFD FAILED!);abort();}return ;}
public:EventLoop():_thread_id(std::this_thread::get_id()), _event_fd(createEventFd()), _event_channel(new Channel(this, _event_fd)),_timer_wheel(this) {//给eventfd添加可读事件回调函数读取eventfd事件通知次数_event_channel-setReadCallback(std::bind(EventLoop::readEventfd, this));//启动eventfd的读事件监控_event_channel-enableRead();}void runInLoop(const Functorcb) { // 判断将要执行的任务是否处于当前线程中如果是则执行不是则压入队列。if (isInLoop()) {return cb();}}void queueInLoop(const Functorcb) { // 将操作压入任务池std::unique_lockstd::mutex _lock(_mutex);//唤醒有可能因为没有事件就绪而导致的epoll阻塞//其实就是给eventfd写入一个数据eventfd就会触发可读事件_tasks.push_back(cb);weakEventFd();}bool isInLoop() { //永远判断当前线程是否是EventLoop所对应的线程return (_thread_id std::this_thread::get_id());}void updateEvent(Channel* channel) {// 添加/修改描述符的事件监控return _poller.UpdateEvent(channel); }void removeEvent(Channel* channel) { // 移除描述符的监控return _poller.removeEvent(channel);}void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc cb) { return _timer_wheel.TimerAdd(id, delay, cb); }void TimerRefresh(uint64_t id) { return _timer_wheel.TimerRefresh(id); }void TimerCancel(uint64_t id) { return _timer_wheel.TimerCancel(id); }bool HasTimer(uint64_t id) { return _timer_wheel.HasTimer(id); }void Start() { // 任务监控完毕进行处理任务 // 三步走事件监控-》就绪事件处理-》执行任务std::vectorChannel* actives;_poller.Poll(actives);for (auto channel : actives) {channel - handleEvent();}runAllTask();}};