1f4e8e3d3SShuo Chen // excerpts from http://code.google.com/p/muduo/
2f4e8e3d3SShuo Chen //
3f4e8e3d3SShuo Chen // Use of this source code is governed by a BSD-style license
4f4e8e3d3SShuo Chen // that can be found in the License file.
5f4e8e3d3SShuo Chen //
6f4e8e3d3SShuo Chen // Author: Shuo Chen (chenshuo at chenshuo dot com)
7f4e8e3d3SShuo Chen 
8f4e8e3d3SShuo Chen #ifndef MUDUO_NET_EVENTLOOP_H
9f4e8e3d3SShuo Chen #define MUDUO_NET_EVENTLOOP_H
10f4e8e3d3SShuo Chen 
11f4e8e3d3SShuo Chen #include "datetime/Timestamp.h"
12f4e8e3d3SShuo Chen #include "thread/Mutex.h"
13f4e8e3d3SShuo Chen #include "thread/Thread.h"
14f4e8e3d3SShuo Chen #include "Callbacks.h"
15f4e8e3d3SShuo Chen #include "TimerId.h"
16f4e8e3d3SShuo Chen 
17f4e8e3d3SShuo Chen #include <boost/scoped_ptr.hpp>
18f4e8e3d3SShuo Chen #include <vector>
19f4e8e3d3SShuo Chen 
20f4e8e3d3SShuo Chen namespace muduo
21f4e8e3d3SShuo Chen {
22f4e8e3d3SShuo Chen 
23f4e8e3d3SShuo Chen class Channel;
24f4e8e3d3SShuo Chen class Poller;
25f4e8e3d3SShuo Chen class TimerQueue;
26f4e8e3d3SShuo Chen 
27f4e8e3d3SShuo Chen class EventLoop : boost::noncopyable
28f4e8e3d3SShuo Chen {
29f4e8e3d3SShuo Chen  public:
30f4e8e3d3SShuo Chen   typedef boost::function<void()> Functor;
31f4e8e3d3SShuo Chen 
32f4e8e3d3SShuo Chen   EventLoop();
33f4e8e3d3SShuo Chen 
34f4e8e3d3SShuo Chen   // force out-line dtor, for scoped_ptr members.
35f4e8e3d3SShuo Chen   ~EventLoop();
36f4e8e3d3SShuo Chen 
37f4e8e3d3SShuo Chen   ///
38f4e8e3d3SShuo Chen   /// Loops forever.
39f4e8e3d3SShuo Chen   ///
40f4e8e3d3SShuo Chen   /// Must be called in the same thread as creation of the object.
41f4e8e3d3SShuo Chen   ///
42f4e8e3d3SShuo Chen   void loop();
43f4e8e3d3SShuo Chen 
44f4e8e3d3SShuo Chen   void quit();
45f4e8e3d3SShuo Chen 
46f4e8e3d3SShuo Chen   ///
47f4e8e3d3SShuo Chen   /// Time when poll returns, usually means data arrivial.
48f4e8e3d3SShuo Chen   ///
49f4e8e3d3SShuo Chen   Timestamp pollReturnTime() const { return pollReturnTime_; }
50f4e8e3d3SShuo Chen 
51f4e8e3d3SShuo Chen   /// Runs callback immediately in the loop thread.
52f4e8e3d3SShuo Chen   /// It wakes up the loop, and run the cb.
53f4e8e3d3SShuo Chen   /// If in the same loop thread, cb is run within the function.
54f4e8e3d3SShuo Chen   /// Safe to call from other threads.
55f4e8e3d3SShuo Chen   void runInLoop(const Functor& cb);
56f4e8e3d3SShuo Chen   /// Queues callback in the loop thread.
57f4e8e3d3SShuo Chen   /// Runs after finish pooling.
58f4e8e3d3SShuo Chen   /// Safe to call from other threads.
59f4e8e3d3SShuo Chen   void queueInLoop(const Functor& cb);
60f4e8e3d3SShuo Chen 
61f4e8e3d3SShuo Chen   // timers
62f4e8e3d3SShuo Chen 
63f4e8e3d3SShuo Chen   ///
64f4e8e3d3SShuo Chen   /// Runs callback at 'time'.
65f4e8e3d3SShuo Chen   /// Safe to call from other threads.
66f4e8e3d3SShuo Chen   ///
67f4e8e3d3SShuo Chen   TimerId runAt(const Timestamp& time, const TimerCallback& cb);
68f4e8e3d3SShuo Chen   ///
69f4e8e3d3SShuo Chen   /// Runs callback after @c delay seconds.
70f4e8e3d3SShuo Chen   /// Safe to call from other threads.
71f4e8e3d3SShuo Chen   ///
72f4e8e3d3SShuo Chen   TimerId runAfter(double delay, const TimerCallback& cb);
73f4e8e3d3SShuo Chen   ///
74f4e8e3d3SShuo Chen   /// Runs callback every @c interval seconds.
75f4e8e3d3SShuo Chen   /// Safe to call from other threads.
76f4e8e3d3SShuo Chen   ///
77f4e8e3d3SShuo Chen   TimerId runEvery(double interval, const TimerCallback& cb);
78f4e8e3d3SShuo Chen 
79f4e8e3d3SShuo Chen-  // void cancel(TimerId timerId);
80f4e8e3d3SShuo Chen+  void cancel(TimerId timerId);
81f4e8e3d3SShuo Chen 
82f4e8e3d3SShuo Chen   // internal use only
83f4e8e3d3SShuo Chen   void wakeup();
84f4e8e3d3SShuo Chen   void updateChannel(Channel* channel);
85f4e8e3d3SShuo Chen   void removeChannel(Channel* channel);
86f4e8e3d3SShuo Chen 
87f4e8e3d3SShuo Chen   void assertInLoopThread()
88f4e8e3d3SShuo Chen   {
89f4e8e3d3SShuo Chen     if (!isInLoopThread())
90f4e8e3d3SShuo Chen     {
91f4e8e3d3SShuo Chen       abortNotInLoopThread();
92f4e8e3d3SShuo Chen     }
93f4e8e3d3SShuo Chen   }
94f4e8e3d3SShuo Chen 
95f4e8e3d3SShuo Chen   bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); }
96f4e8e3d3SShuo Chen 
97f4e8e3d3SShuo Chen  private:
98f4e8e3d3SShuo Chen 
99f4e8e3d3SShuo Chen   void abortNotInLoopThread();
100f4e8e3d3SShuo Chen   void handleRead();  // waked up
101f4e8e3d3SShuo Chen   void doPendingFunctors();
102f4e8e3d3SShuo Chen 
103f4e8e3d3SShuo Chen   typedef std::vector<Channel*> ChannelList;
104f4e8e3d3SShuo Chen 
105f4e8e3d3SShuo Chen   bool looping_; /* atomic */
106f4e8e3d3SShuo Chen   bool quit_; /* atomic */
107f4e8e3d3SShuo Chen   bool callingPendingFunctors_; /* atomic */
108f4e8e3d3SShuo Chen   const pid_t threadId_;
109f4e8e3d3SShuo Chen   Timestamp pollReturnTime_;
110f4e8e3d3SShuo Chen   boost::scoped_ptr<Poller> poller_;
111f4e8e3d3SShuo Chen   boost::scoped_ptr<TimerQueue> timerQueue_;
112f4e8e3d3SShuo Chen   int wakeupFd_;
113f4e8e3d3SShuo Chen   // unlike in TimerQueue, which is an internal class,
114f4e8e3d3SShuo Chen   // we don't expose Channel to client.
115f4e8e3d3SShuo Chen   boost::scoped_ptr<Channel> wakeupChannel_;
116f4e8e3d3SShuo Chen   ChannelList activeChannels_;
117f4e8e3d3SShuo Chen   MutexLock mutex_;
118f4e8e3d3SShuo Chen   std::vector<Functor> pendingFunctors_; // @BuardedBy mutex_
119f4e8e3d3SShuo Chen };
120f4e8e3d3SShuo Chen 
121f4e8e3d3SShuo Chen }
122f4e8e3d3SShuo Chen 
123f4e8e3d3SShuo Chen #endif  // MUDUO_NET_EVENTLOOP_H
124