EventLoopThread (30)
来源:互联网 发布:福州seo基础培训 编辑:程序博客网 时间:2024/06/02 10:59
任何一个线程,只要创建并运行了EventLoop,都称之为IO线程
IO线程不一定是主线程
muduo并发模型one loop per thread + threadpool
为了方便今后使用,定义了EventLoopThread类,该类封装了IO线程EventLoopThread创建了一个线程
在线程函数中创建了一个EvenLoop对象并调用EventLoop::loop
EventLoopThread头文件
eventloopthread.h
// Copyright 2010, Shuo Chen. All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)//// This is a public header file, it must only include public header files.#ifndef MUDUO_NET_EVENTLOOPTHREAD_H#define MUDUO_NET_EVENTLOOPTHREAD_H#include <muduo/base/Condition.h>#include <muduo/base/Mutex.h>#include <muduo/base/Thread.h>#include <boost/noncopyable.hpp>namespace muduo{namespace net{class EventLoop;class EventLoopThread : boost::noncopyable{ public: typedef boost::function<void(EventLoop*)> ThreadInitCallback; EventLoopThread(const ThreadInitCallback& cb =ThreadInitCallback()); ~EventLoopThread(); EventLoop* startLoop(); // 启动线程,该线程就成为了IO线程 private: void threadFunc(); // 线程函数 ,这个线程函数启动起来之后,会创建一个eventloop对象,loop_指针会指向这个对象 EventLoop* loop_; // loop_指针指向一个EventLoop对象,一个IO线程有且只有一个eventloop对象 bool exiting_; Thread thread_; //线程对象 MutexLock mutex_; Condition cond_; ThreadInitCallback callback_; // 回调函数在EventLoop::loop IO线程的事件循环之前被调用};}}#endif // MUDUO_NET_EVENTLOOPTHREAD_H
EventLoopThread源文件
eventloopthread.cc
// Copyright 2010, Shuo Chen. All rights reserved.// http://code.google.com/p/muduo///// Use of this source code is governed by a BSD-style license// that can be found in the License file.// Author: Shuo Chen (chenshuo at chenshuo dot com)#include <muduo/net/EventLoopThread.h>#include <muduo/net/EventLoop.h>#include <boost/bind.hpp>using namespace muduo;using namespace muduo::net;// typedef boost::function<void(EventLoop*)> ThreadInitCallback;EventLoopThread::EventLoopThread(const ThreadInitCallback& cb) : loop_(NULL), exiting_(false), thread_(boost::bind(&EventLoopThread::threadFunc, this)), mutex_(), cond_(mutex_), callback_(cb) //cb 默认为空{}EventLoopThread::~EventLoopThread(){ exiting_ = true; loop_->quit(); // 退出IO线程,让IO线程的loop循环退出,从而退出了IO线程 thread_.join();}/*启动线程,也就是启动loop函数EventLoopThread::threadFunc这个函数*/EventLoop* EventLoopThread::startLoop(){ assert(!thread_.started()); /*线程启动时会调用*/ thread_.start(); { MutexLockGuard lock(mutex_); /*eventloop对象创建完成*/ while (loop_ == NULL) { cond_.wait(); } } return loop_;}/*loop 的初始化函数*/void EventLoopThread::threadFunc(){ EventLoop loop; /*创建eventloop对象*/ if (callback_) { callback_(&loop); } { MutexLockGuard lock(mutex_); // loop_指针指向了一个栈上的对象,threadFunc函数退出之后,这个指针就失效了 // threadFunc函数退出,就意味着线程退出了,EventLoopThread对象也就没有存在的价值了。 // 因而不会有什么大的问题 loop_ = &loop; cond_.notify(); } /*启动loop()函数*/ loop.loop(); //assert(exiting_);}
测试程序
#include <muduo/net/EventLoop.h>#include <muduo/net/EventLoopThread.h>#include <stdio.h>using namespace muduo;using namespace muduo::net;void runInThread(){ printf("runInThread(): pid = %d, tid = %d\n", getpid(), CurrentThread::tid());}int main(){ printf("main(): pid = %d, tid = %d\n", getpid(), CurrentThread::tid()); EventLoopThread loopThread; EventLoop* loop = loopThread.startLoop(); // 异步调用runInThread,即将runInThread添加到loop对象所在IO线程,让该IO线程执行 loop->runInLoop(runInThread); sleep(1); // runAfter内部也调用了runInLoop,所以这里也是异步调用 loop->runAfter(2, runInThread); sleep(3); loop->quit(); printf("exit main().\n");}/*TimerId TimerQueue::addTimer(const TimerCallback& cb, Timestamp when, double interval){ Timer* timer = new Timer(cb, when, interval); loop_->runInLoop( boost::bind(&TimerQueue::addTimerInLoop, this, timer)); //addTimerInLoop(timer); 不能用这个,如果直接调用,那么addTimerInLoop断言失败 return TimerId(timer, timer->sequence());}void TimerQueue::addTimerInLoop(Timer* timer){ loop_->assertInLoopThread(); // 插入一个定时器,有可能会使得最早到期的定时器发生改变 bool earliestChanged = insert(timer); if (earliestChanged) { // 重置定时器的超时时刻(timerfd_settime) resetTimerfd(timerfd_, timer->expiration()); }}bool TimerQueue::insert(Timer* timer){ loop_->assertInLoopThread(); assert(timers_.size() == activeTimers_.size()); // 最早到期时间是否改变 bool earliestChanged = false; Timestamp when = timer->expiration(); TimerList::iterator it = timers_.begin(); // 如果timers_为空或者when小于timers_中的最早到期时间 if (it == timers_.end() || when < it->first) { earliestChanged = true; } { // 插入到timers_中 std::pair<TimerList::iterator, bool> result = timers_.insert(Entry(when, timer)); assert(result.second); (void)result; } { // 插入到activeTimers_中 std::pair<ActiveTimerSet::iterator, bool> result = activeTimers_.insert(ActiveTimer(timer, timer->sequence())); assert(result.second); (void)result; } assert(timers_.size() == activeTimers_.size()); return earliestChanged;}*/
程序输出
ubuntu@ubuntu-virtual-machine:~/pro/30$ ./build/debug/bin/reactor_test06 main(): pid = 29731, tid = 2973120131022 03:03:50.315042Z 29732 TRACE updateChannel fd = 4 events = 3 - EPollPoller.cc:10420131022 03:03:50.315588Z 29732 TRACE EventLoop EventLoop created 0xB786BF94 in thread 29732 - EventLoop.cc:6220131022 03:03:50.315643Z 29732 TRACE updateChannel fd = 5 events = 3 - EPollPoller.cc:10420131022 03:03:50.315708Z 29732 TRACE loop EventLoop 0xB786BF94 start looping - EventLoop.cc:9420131022 03:03:50.315976Z 29732 TRACE poll 1 events happended - EPollPoller.cc:6520131022 03:03:50.316472Z 29732 TRACE printActiveChannels {5: IN } - EventLoop.cc:257runInThread(): pid = 29731, tid = 2973220131022 03:03:51.316968Z 29732 TRACE poll 1 events happended - EPollPoller.cc:6520131022 03:03:51.317092Z 29732 TRACE printActiveChannels {5: IN } - EventLoop.cc:25720131022 03:03:53.317414Z 29732 TRACE poll 1 events happended - EPollPoller.cc:6520131022 03:03:53.317539Z 29732 TRACE printActiveChannels {4: IN } - EventLoop.cc:25720131022 03:03:53.317639Z 29732 TRACE readTimerfd TimerQueue::handleRead() 1 at 1382411033.317576 - TimerQueue.cc:62runInThread(): pid = 29731, tid = 29732exit main().20131022 03:03:54.317901Z 29732 TRACE poll 1 events happended - EPollPoller.cc:6520131022 03:03:54.317966Z 29732 TRACE printActiveChannels {5: IN } - EventLoop.cc:25720131022 03:03:54.317990Z 29732 TRACE loop EventLoop 0xB786BF94 stop looping - EventLoop.cc:119ubuntu@ubuntu-virtual-machine:~/pro/30$
- EventLoopThread (30)
- muduo网络库学习之EventLoop(四):EventLoopThread 类、EventLoopThreadPool 类
- Muduo网络库源码分析(四)EventLoopThread和EventLoopThreadPool的封装
- Muduo网络库源码分析(四)EventLoopThread和EventLoopThreadPool的封装
- muduo源码分析---EventLoopThread
- muduo::EventLoopThread、EventLoopThreadPool分析
- muduo库阅读(35)——Net部分:用于执行事件循环(EventLoop)的线程类EventLoopThread
- muduo源码解析之EventLoopThread
- 将任务加入到Eventloopthread
- muduo源码学习(18)-EventLoopThread
- muduo库的EventLoopThread类剖析
- 黑洞(30集)
- 谋划(30)
- 谋划(30)
- 无题(2011.11.30)
- 30、注解(Annotation)
- 周末(30)
- 30、注解(Annotation)
- EventLoop再分析之IO线程(29)
- sicily9161
- Spring MVC过滤器-字符集过滤器(CharacterEncodingFilter)
- C#远程连接mstscax组件和upnp组件
- 方格遍历问题
- EventLoopThread (30)
- XP系统ftp服务器的搭建
- Socket封装(31)
- ural 1963. Kite
- HSSFCell:You cannot get a string value from a numeric cell
- ios 获取视频数据每一帧播放
- HDU4533 威威猫系列故事――晒被子
- 每天学点Linux--(File_status_flag和File_description_flag的区别/atoi函数的使用
- window下memcached安装