1048f6023SShuo Chen // excerpts from http://code.google.com/p/muduo/
2048f6023SShuo Chen //
3048f6023SShuo Chen // Use of this source code is governed by a BSD-style license
4048f6023SShuo Chen // that can be found in the License file.
5048f6023SShuo Chen //
6048f6023SShuo Chen // Author: Shuo Chen (chenshuo at chenshuo dot com)
7048f6023SShuo Chen 
8048f6023SShuo Chen #ifndef MUDUO_NET_EVENTLOOP_H
9048f6023SShuo Chen #define MUDUO_NET_EVENTLOOP_H
10048f6023SShuo Chen 
11048f6023SShuo Chen #include "datetime/Timestamp.h"
12048f6023SShuo Chen #include "thread/Mutex.h"
13048f6023SShuo Chen #include "thread/Thread.h"
14048f6023SShuo Chen #include "Callbacks.h"
15048f6023SShuo Chen #include "TimerId.h"
16048f6023SShuo Chen 
17048f6023SShuo Chen #include <boost/scoped_ptr.hpp>
18048f6023SShuo Chen #include <vector>
19048f6023SShuo Chen 
20048f6023SShuo Chen namespace muduo
21048f6023SShuo Chen {
22048f6023SShuo Chen 
23048f6023SShuo Chen class Channel;
24048f6023SShuo Chen class Poller;
25048f6023SShuo Chen class TimerQueue;
26048f6023SShuo Chen 
27048f6023SShuo Chen class EventLoop : boost::noncopyable
28048f6023SShuo Chen {
29048f6023SShuo Chen  public:
30048f6023SShuo Chen   typedef boost::function<void()> Functor;
31048f6023SShuo Chen 
32048f6023SShuo Chen   EventLoop();
33048f6023SShuo Chen 
34048f6023SShuo Chen   // force out-line dtor, for scoped_ptr members.
35048f6023SShuo Chen   ~EventLoop();
36048f6023SShuo Chen 
37048f6023SShuo Chen   ///
38048f6023SShuo Chen   /// Loops forever.
39048f6023SShuo Chen   ///
40048f6023SShuo Chen   /// Must be called in the same thread as creation of the object.
41048f6023SShuo Chen   ///
42048f6023SShuo Chen   void loop();
43048f6023SShuo Chen 
44048f6023SShuo Chen   void quit();
45048f6023SShuo Chen 
46048f6023SShuo Chen   ///
47048f6023SShuo Chen   /// Time when poll returns, usually means data arrivial.
48048f6023SShuo Chen   ///
49048f6023SShuo Chen   Timestamp pollReturnTime() const { return pollReturnTime_; }
50048f6023SShuo Chen 
51048f6023SShuo Chen   /// Runs callback immediately in the loop thread.
52048f6023SShuo Chen   /// It wakes up the loop, and run the cb.
53048f6023SShuo Chen   /// If in the same loop thread, cb is run within the function.
54048f6023SShuo Chen   /// Safe to call from other threads.
55048f6023SShuo Chen   void runInLoop(const Functor& cb);
56048f6023SShuo Chen   /// Queues callback in the loop thread.
57048f6023SShuo Chen   /// Runs after finish pooling.
58048f6023SShuo Chen   /// Safe to call from other threads.
59048f6023SShuo Chen   void queueInLoop(const Functor& cb);
60048f6023SShuo Chen 
61048f6023SShuo Chen   // timers
62048f6023SShuo Chen 
63048f6023SShuo Chen   ///
64048f6023SShuo Chen   /// Runs callback at 'time'.
65048f6023SShuo Chen   /// Safe to call from other threads.
66048f6023SShuo Chen   ///
67048f6023SShuo Chen   TimerId runAt(const Timestamp& time, const TimerCallback& cb);
68048f6023SShuo Chen   ///
69048f6023SShuo Chen   /// Runs callback after @c delay seconds.
70048f6023SShuo Chen   /// Safe to call from other threads.
71048f6023SShuo Chen   ///
72048f6023SShuo Chen   TimerId runAfter(double delay, const TimerCallback& cb);
73048f6023SShuo Chen   ///
74048f6023SShuo Chen   /// Runs callback every @c interval seconds.
75048f6023SShuo Chen   /// Safe to call from other threads.
76048f6023SShuo Chen   ///
77048f6023SShuo Chen   TimerId runEvery(double interval, const TimerCallback& cb);
78048f6023SShuo Chen 
79048f6023SShuo Chen   // void cancel(TimerId timerId);
80048f6023SShuo Chen 
81048f6023SShuo Chen   // internal use only
82048f6023SShuo Chen   void wakeup();
83048f6023SShuo Chen   void updateChannel(Channel* channel);
84048f6023SShuo Chen!  void removeChannel(Channel* channel);
85048f6023SShuo Chen 
86048f6023SShuo Chen   void assertInLoopThread()
87048f6023SShuo Chen   {
88048f6023SShuo Chen     if (!isInLoopThread())
89048f6023SShuo Chen     {
90048f6023SShuo Chen       abortNotInLoopThread();
91048f6023SShuo Chen     }
92048f6023SShuo Chen   }
93048f6023SShuo Chen 
94048f6023SShuo Chen   bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); }
95048f6023SShuo Chen 
96048f6023SShuo Chen  private:
97048f6023SShuo Chen 
98048f6023SShuo Chen   void abortNotInLoopThread();
99048f6023SShuo Chen   void handleRead();  // waked up
100048f6023SShuo Chen   void doPendingFunctors();
101048f6023SShuo Chen 
102048f6023SShuo Chen   typedef std::vector<Channel*> ChannelList;
103048f6023SShuo Chen 
104048f6023SShuo Chen   bool looping_; /* atomic */
105048f6023SShuo Chen   bool quit_; /* atomic */
106048f6023SShuo Chen   bool callingPendingFunctors_; /* atomic */
107048f6023SShuo Chen   const pid_t threadId_;
108048f6023SShuo Chen   Timestamp pollReturnTime_;
109048f6023SShuo Chen   boost::scoped_ptr<Poller> poller_;
110048f6023SShuo Chen   boost::scoped_ptr<TimerQueue> timerQueue_;
111048f6023SShuo Chen   int wakeupFd_;
112048f6023SShuo Chen   // unlike in TimerQueue, which is an internal class,
113048f6023SShuo Chen   // we don't expose Channel to client.
114048f6023SShuo Chen   boost::scoped_ptr<Channel> wakeupChannel_;
115048f6023SShuo Chen   ChannelList activeChannels_;
116048f6023SShuo Chen   MutexLock mutex_;
117fd65b0afSShuo Chen   std::vector<Functor> pendingFunctors_; // @GuardedBy mutex_
118048f6023SShuo Chen };
119048f6023SShuo Chen 
120048f6023SShuo Chen }
121048f6023SShuo Chen 
122048f6023SShuo Chen #endif  // MUDUO_NET_EVENTLOOP_H
123