blob: b2aa929019ace33983d36b914422ffe0df7dd0bb [file] [log] [blame]
Zhenkai Zhu97019eb2013-01-08 00:21:43 -08001#ifndef EVENT_SCHEDULER_H
2#define EVENT_SCHEDULER_H
Zhenkai Zhubc2f6282013-01-08 16:40:58 -08003
4// use pthread
5
Zhenkai Zhu97019eb2013-01-08 00:21:43 -08006#include <event2/event.h>
Zhenkai Zhu97019eb2013-01-08 00:21:43 -08007#include <event2/thread.h>
8
9#include <boost/function.hpp>
10#include <boost/shared_ptr.hpp>
11#include <boost/random/mersenne_twister.hpp>
12#include <boost/random/uniform_real.hpp>
13#include <boost/random/variate_generator.hpp>
14#include <boost/exception/all.hpp>
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080015#include <boost/thread/shared_mutex.hpp>
16#include <boost/thread/thread.hpp>
Zhenkai Zhu97019eb2013-01-08 00:21:43 -080017#include <math.h>
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080018#include <map>
19#include <sys/time.h>
Zhenkai Zhu97019eb2013-01-08 00:21:43 -080020
21#define _OVERRIDE
22#ifdef __GNUC__
23#if __GNUC_MAJOR >= 4 && __GNUC_MINOR__ >= 7
24 #undef _OVERRIDE
25 #define _OVERRIDE override
26#endif // __GNUC__ version
27#endif // __GNUC__
28
29using namespace std;
30
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080031static void
32eventCallback(evutil_socket_t fd, short what, void *arg);
33
34class Scheduler;
35typedef boost::shared_ptr<Scheduler> SchedulerPtr;
36class IntervalGenerator;
37typedef boost::shared_ptr<IntervalGenerator> IntervalGeneratorPtr;
38class Task;
39typedef boost::shared_ptr<Task> TaskPtr;
40
41class IntervalGenerator
42{
43public:
44 virtual double
45 nextInterval() = 0;
46 static IntervalGeneratorPtr Null;
47};
Zhenkai Zhu97019eb2013-01-08 00:21:43 -080048
49class Task
50{
51public:
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080052 typedef boost::function<void ()> Callback;
Zhenkai Zhu97019eb2013-01-08 00:21:43 -080053 typedef string Tag;
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080054 typedef boost::function<bool (const TaskPtr &task)> TaskMatcher;
Zhenkai Zhu97019eb2013-01-08 00:21:43 -080055
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080056 Task(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler, const IntervalGeneratorPtr &generator = IntervalGenerator::Null);
57 ~Task();
Zhenkai Zhu97019eb2013-01-08 00:21:43 -080058
59 virtual void
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080060 run();
Zhenkai Zhu97019eb2013-01-08 00:21:43 -080061
62 Tag
63 tag() { return m_tag; }
64
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080065 event *
66 ev() { return m_event; }
67
68 timeval *
69 tv() { return m_tv; }
70
71 void
72 setTv(double delay);
73
74 bool
75 isPeriodic() { return m_generator != IntervalGenerator::Null; }
76
77 void
78 reset();
79
80protected:
81 void
82 selfClean();
Zhenkai Zhu97019eb2013-01-08 00:21:43 -080083
84protected:
85 Callback m_callback;
86 Tag m_tag;
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080087 SchedulerPtr m_scheduler;
88 bool m_invoked;
89 event *m_event;
90 timeval *m_tv;
91 IntervalGeneratorPtr m_generator;
Zhenkai Zhu97019eb2013-01-08 00:21:43 -080092};
93
Zhenkai Zhubc2f6282013-01-08 16:40:58 -080094
Zhenkai Zhu97019eb2013-01-08 00:21:43 -080095struct SchedulerException : virtual boost::exception, virtual exception { };
96
Zhenkai Zhu97019eb2013-01-08 00:21:43 -080097class Scheduler
98{
99public:
100 Scheduler();
101 virtual ~Scheduler();
102
103 virtual void
104 start();
105
106 virtual void
107 shutdown();
108
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800109 virtual bool
110 addTask(const TaskPtr &task, double delay);
111
112 virtual bool
113 addTask(const TaskPtr &task);
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800114
115 virtual void
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800116 deleteTask(const Task::Tag &tag);
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800117
118 virtual void
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800119 deleteTask(const Task::TaskMatcher &matcher);
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800120
121 virtual void
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800122 rescheduleTask(const Task::Tag &tag);
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800123
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800124 void
125 eventLoop();
126
127 event_base *
128 base() { return m_base; }
129
130 // used in test
131 int
132 size();
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800133
134protected:
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800135 bool
136 addToMap(const TaskPtr &task);
137
138protected:
139 typedef map<Task::Tag, TaskPtr> TaskMap;
140 typedef map<Task::Tag, TaskPtr>::iterator TaskMapIt;
141 typedef boost::shared_mutex Mutex;
142 typedef boost::unique_lock<Mutex> WriteLock;
143 typedef boost::shared_lock<Mutex> ReadLock;
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800144 TaskMap m_taskMap;
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800145 Mutex m_mutex;
146 event_base *m_base;
147 boost::thread m_thread;
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800148};
149
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800150class SimpleIntervalGenerator : public IntervalGenerator
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800151{
152public:
153 SimpleIntervalGenerator(double interval) : m_interval(interval) {}
154 ~SimpleIntervalGenerator(){}
155 virtual double
156 nextInterval() _OVERRIDE { return m_interval; }
157private:
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800158 double m_interval;
159};
160
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800161class RandomIntervalGenerator : public IntervalGenerator
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800162{
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800163public:
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800164 typedef enum
165 {
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800166 UP = 1,
167 DOWN = 2,
168 EVEN = 3
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800169 } Direction;
170
171public:
172 RandomIntervalGenerator(double interval, double percent, Direction direction = EVEN);
173 ~RandomIntervalGenerator(){}
174 virtual double
175 nextInterval() _OVERRIDE;
176
177private:
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800178 inline double fractional(double x) { double dummy; return abs(modf(x, &dummy)); }
179
180private:
181 typedef boost::mt19937 RNG_TYPE;
182 RNG_TYPE m_rng;
183 boost::uniform_real<> m_dist;
Zhenkai Zhubc2f6282013-01-08 16:40:58 -0800184 boost::variate_generator<RNG_TYPE &, boost::uniform_real<> > m_random;
Zhenkai Zhu97019eb2013-01-08 00:21:43 -0800185 Direction m_direction;
186 double m_interval;
187 double m_percent;
188
189};
190#endif // EVENT_SCHEDULER_H