1b37003a7SShuo Chen// excerpts from http://code.google.com/p/muduo/
2b37003a7SShuo Chen//
3b37003a7SShuo Chen// Use of this source code is governed by a BSD-style license
4b37003a7SShuo Chen// that can be found in the License file.
5b37003a7SShuo Chen//
6b37003a7SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
7b37003a7SShuo Chen
8b37003a7SShuo Chen#include "EventLoop.h"
9b37003a7SShuo Chen
10b37003a7SShuo Chen#include "Channel.h"
11b37003a7SShuo Chen#include "Poller.h"
12b37003a7SShuo Chen#include "TimerQueue.h"
13b37003a7SShuo Chen
14b37003a7SShuo Chen#include "logging/Logging.h"
15b37003a7SShuo Chen
16b37003a7SShuo Chen#include <boost/bind.hpp>
17b37003a7SShuo Chen
18b37003a7SShuo Chen#include <assert.h>
19a4e9058bSShuo Chen#include <signal.h>
20b37003a7SShuo Chen#include <sys/eventfd.h>
21b37003a7SShuo Chen
22b37003a7SShuo Chenusing namespace muduo;
23b37003a7SShuo Chen
24b37003a7SShuo Chen__thread EventLoop* t_loopInThisThread = 0;
25b37003a7SShuo Chenconst int kPollTimeMs = 10000;
26b37003a7SShuo Chen
27b37003a7SShuo Chenstatic int createEventfd()
28b37003a7SShuo Chen{
29b37003a7SShuo Chen  int evtfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
30b37003a7SShuo Chen  if (evtfd < 0)
31b37003a7SShuo Chen  {
32b37003a7SShuo Chen    LOG_SYSERR << "Failed in eventfd";
33b37003a7SShuo Chen    abort();
34b37003a7SShuo Chen  }
35b37003a7SShuo Chen  return evtfd;
36b37003a7SShuo Chen}
37b37003a7SShuo Chen
38a4e9058bSShuo Chenclass IgnoreSigPipe
39a4e9058bSShuo Chen{
40a4e9058bSShuo Chen public:
41a4e9058bSShuo Chen  IgnoreSigPipe()
42a4e9058bSShuo Chen  {
43a4e9058bSShuo Chen    ::signal(SIGPIPE, SIG_IGN);
44a4e9058bSShuo Chen  }
45a4e9058bSShuo Chen};
46a4e9058bSShuo Chen
47a4e9058bSShuo ChenIgnoreSigPipe initObj;
48a4e9058bSShuo Chen
49b37003a7SShuo ChenEventLoop::EventLoop()
50b37003a7SShuo Chen  : looping_(false),
51b37003a7SShuo Chen    quit_(false),
52b37003a7SShuo Chen    callingPendingFunctors_(false),
53b37003a7SShuo Chen    threadId_(CurrentThread::tid()),
54b37003a7SShuo Chen    poller_(new Poller(this)),
55b37003a7SShuo Chen    timerQueue_(new TimerQueue(this)),
56b37003a7SShuo Chen    wakeupFd_(createEventfd()),
57b37003a7SShuo Chen    wakeupChannel_(new Channel(this, wakeupFd_))
58b37003a7SShuo Chen{
59b37003a7SShuo Chen  LOG_TRACE << "EventLoop created " << this << " in thread " << threadId_;
60b37003a7SShuo Chen  if (t_loopInThisThread)
61b37003a7SShuo Chen  {
62b37003a7SShuo Chen    LOG_FATAL << "Another EventLoop " << t_loopInThisThread
63b37003a7SShuo Chen              << " exists in this thread " << threadId_;
64b37003a7SShuo Chen  }
65b37003a7SShuo Chen  else
66b37003a7SShuo Chen  {
67b37003a7SShuo Chen    t_loopInThisThread = this;
68b37003a7SShuo Chen  }
69b37003a7SShuo Chen  wakeupChannel_->setReadCallback(
70b37003a7SShuo Chen      boost::bind(&EventLoop::handleRead, this));
71b37003a7SShuo Chen  // we are always reading the wakeupfd
72b37003a7SShuo Chen  wakeupChannel_->enableReading();
73b37003a7SShuo Chen}
74b37003a7SShuo Chen
75b37003a7SShuo ChenEventLoop::~EventLoop()
76b37003a7SShuo Chen{
77b37003a7SShuo Chen  assert(!looping_);
78b37003a7SShuo Chen  ::close(wakeupFd_);
79b37003a7SShuo Chen  t_loopInThisThread = NULL;
80b37003a7SShuo Chen}
81b37003a7SShuo Chen
82b37003a7SShuo Chenvoid EventLoop::loop()
83b37003a7SShuo Chen{
84b37003a7SShuo Chen  assert(!looping_);
85b37003a7SShuo Chen  assertInLoopThread();
86b37003a7SShuo Chen  looping_ = true;
87b37003a7SShuo Chen  quit_ = false;
88b37003a7SShuo Chen
89b37003a7SShuo Chen  while (!quit_)
90b37003a7SShuo Chen  {
91b37003a7SShuo Chen    activeChannels_.clear();
92b37003a7SShuo Chen    pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannels_);
93b37003a7SShuo Chen    for (ChannelList::iterator it = activeChannels_.begin();
94b37003a7SShuo Chen        it != activeChannels_.end(); ++it)
95b37003a7SShuo Chen    {
96b37003a7SShuo Chen      (*it)->handleEvent(pollReturnTime_);
97b37003a7SShuo Chen    }
98b37003a7SShuo Chen    doPendingFunctors();
99b37003a7SShuo Chen  }
100b37003a7SShuo Chen
101b37003a7SShuo Chen  LOG_TRACE << "EventLoop " << this << " stop looping";
102b37003a7SShuo Chen  looping_ = false;
103b37003a7SShuo Chen}
104b37003a7SShuo Chen
105b37003a7SShuo Chenvoid EventLoop::quit()
106b37003a7SShuo Chen{
107b37003a7SShuo Chen  quit_ = true;
108b37003a7SShuo Chen  if (!isInLoopThread())
109b37003a7SShuo Chen  {
110b37003a7SShuo Chen    wakeup();
111b37003a7SShuo Chen  }
112b37003a7SShuo Chen}
113b37003a7SShuo Chen
114b37003a7SShuo Chenvoid EventLoop::runInLoop(const Functor& cb)
115b37003a7SShuo Chen{
116b37003a7SShuo Chen  if (isInLoopThread())
117b37003a7SShuo Chen  {
118b37003a7SShuo Chen    cb();
119b37003a7SShuo Chen  }
120b37003a7SShuo Chen  else
121b37003a7SShuo Chen  {
122b37003a7SShuo Chen    queueInLoop(cb);
123b37003a7SShuo Chen  }
124b37003a7SShuo Chen}
125b37003a7SShuo Chen
126b37003a7SShuo Chenvoid EventLoop::queueInLoop(const Functor& cb)
127b37003a7SShuo Chen{
128b37003a7SShuo Chen  {
129b37003a7SShuo Chen  MutexLockGuard lock(mutex_);
130b37003a7SShuo Chen  pendingFunctors_.push_back(cb);
131b37003a7SShuo Chen  }
132b37003a7SShuo Chen
1330f776063SShuo Chen  if (!isInLoopThread() || callingPendingFunctors_)
134b37003a7SShuo Chen  {
135b37003a7SShuo Chen    wakeup();
136b37003a7SShuo Chen  }
137b37003a7SShuo Chen}
138b37003a7SShuo Chen
139b37003a7SShuo ChenTimerId EventLoop::runAt(const Timestamp& time, const TimerCallback& cb)
140b37003a7SShuo Chen{
141b37003a7SShuo Chen  return timerQueue_->addTimer(cb, time, 0.0);
142b37003a7SShuo Chen}
143b37003a7SShuo Chen
144b37003a7SShuo ChenTimerId EventLoop::runAfter(double delay, const TimerCallback& cb)
145b37003a7SShuo Chen{
146b37003a7SShuo Chen  Timestamp time(addTime(Timestamp::now(), delay));
147b37003a7SShuo Chen  return runAt(time, cb);
148b37003a7SShuo Chen}
149b37003a7SShuo Chen
150b37003a7SShuo ChenTimerId EventLoop::runEvery(double interval, const TimerCallback& cb)
151b37003a7SShuo Chen{
152b37003a7SShuo Chen  Timestamp time(addTime(Timestamp::now(), interval));
153b37003a7SShuo Chen  return timerQueue_->addTimer(cb, time, interval);
154b37003a7SShuo Chen}
155b37003a7SShuo Chen
156b37003a7SShuo Chenvoid EventLoop::updateChannel(Channel* channel)
157b37003a7SShuo Chen{
158b37003a7SShuo Chen  assert(channel->ownerLoop() == this);
159b37003a7SShuo Chen  assertInLoopThread();
160b37003a7SShuo Chen  poller_->updateChannel(channel);
161b37003a7SShuo Chen}
162b37003a7SShuo Chen
163b37003a7SShuo Chenvoid EventLoop::removeChannel(Channel* channel)
164b37003a7SShuo Chen{
165b37003a7SShuo Chen  assert(channel->ownerLoop() == this);
166b37003a7SShuo Chen  assertInLoopThread();
167b37003a7SShuo Chen  poller_->removeChannel(channel);
168b37003a7SShuo Chen}
169b37003a7SShuo Chen
170b37003a7SShuo Chenvoid EventLoop::abortNotInLoopThread()
171b37003a7SShuo Chen{
172b37003a7SShuo Chen  LOG_FATAL << "EventLoop::abortNotInLoopThread - EventLoop " << this
173b37003a7SShuo Chen            << " was created in threadId_ = " << threadId_
174b37003a7SShuo Chen            << ", current thread id = " <<  CurrentThread::tid();
175b37003a7SShuo Chen}
176b37003a7SShuo Chen
177b37003a7SShuo Chenvoid EventLoop::wakeup()
178b37003a7SShuo Chen{
179b37003a7SShuo Chen  uint64_t one = 1;
180b37003a7SShuo Chen  ssize_t n = ::write(wakeupFd_, &one, sizeof one);
181b37003a7SShuo Chen  if (n != sizeof one)
182b37003a7SShuo Chen  {
183b37003a7SShuo Chen    LOG_ERROR << "EventLoop::wakeup() writes " << n << " bytes instead of 8";
184b37003a7SShuo Chen  }
185b37003a7SShuo Chen}
186b37003a7SShuo Chen
187b37003a7SShuo Chenvoid EventLoop::handleRead()
188b37003a7SShuo Chen{
189b37003a7SShuo Chen  uint64_t one = 1;
190b37003a7SShuo Chen  ssize_t n = ::read(wakeupFd_, &one, sizeof one);
191b37003a7SShuo Chen  if (n != sizeof one)
192b37003a7SShuo Chen  {
193b37003a7SShuo Chen    LOG_ERROR << "EventLoop::handleRead() reads " << n << " bytes instead of 8";
194b37003a7SShuo Chen  }
195b37003a7SShuo Chen}
196b37003a7SShuo Chen
197b37003a7SShuo Chenvoid EventLoop::doPendingFunctors()
198b37003a7SShuo Chen{
199b37003a7SShuo Chen  std::vector<Functor> functors;
200b37003a7SShuo Chen  callingPendingFunctors_ = true;
201b37003a7SShuo Chen
202b37003a7SShuo Chen  {
203b37003a7SShuo Chen  MutexLockGuard lock(mutex_);
204b37003a7SShuo Chen  functors.swap(pendingFunctors_);
205b37003a7SShuo Chen  }
206b37003a7SShuo Chen
207b37003a7SShuo Chen  for (size_t i = 0; i < functors.size(); ++i)
208b37003a7SShuo Chen  {
209b37003a7SShuo Chen    functors[i]();
210b37003a7SShuo Chen  }
211b37003a7SShuo Chen  callingPendingFunctors_ = false;
212b37003a7SShuo Chen}
213b37003a7SShuo Chen
214