blob: b2aa929019ace33983d36b914422ffe0df7dd0bb [file] [log] [blame]
#ifndef EVENT_SCHEDULER_H
#define EVENT_SCHEDULER_H
// use pthread
#include <event2/event.h>
#include <event2/thread.h>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/exception/all.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/thread.hpp>
#include <math.h>
#include <map>
#include <sys/time.h>
#define _OVERRIDE
#ifdef __GNUC__
#if __GNUC_MAJOR >= 4 && __GNUC_MINOR__ >= 7
#undef _OVERRIDE
#define _OVERRIDE override
#endif // __GNUC__ version
#endif // __GNUC__
using namespace std;
static void
eventCallback(evutil_socket_t fd, short what, void *arg);
class Scheduler;
typedef boost::shared_ptr<Scheduler> SchedulerPtr;
class IntervalGenerator;
typedef boost::shared_ptr<IntervalGenerator> IntervalGeneratorPtr;
class Task;
typedef boost::shared_ptr<Task> TaskPtr;
class IntervalGenerator
{
public:
virtual double
nextInterval() = 0;
static IntervalGeneratorPtr Null;
};
class Task
{
public:
typedef boost::function<void ()> Callback;
typedef string Tag;
typedef boost::function<bool (const TaskPtr &task)> TaskMatcher;
Task(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler, const IntervalGeneratorPtr &generator = IntervalGenerator::Null);
~Task();
virtual void
run();
Tag
tag() { return m_tag; }
event *
ev() { return m_event; }
timeval *
tv() { return m_tv; }
void
setTv(double delay);
bool
isPeriodic() { return m_generator != IntervalGenerator::Null; }
void
reset();
protected:
void
selfClean();
protected:
Callback m_callback;
Tag m_tag;
SchedulerPtr m_scheduler;
bool m_invoked;
event *m_event;
timeval *m_tv;
IntervalGeneratorPtr m_generator;
};
struct SchedulerException : virtual boost::exception, virtual exception { };
class Scheduler
{
public:
Scheduler();
virtual ~Scheduler();
virtual void
start();
virtual void
shutdown();
virtual bool
addTask(const TaskPtr &task, double delay);
virtual bool
addTask(const TaskPtr &task);
virtual void
deleteTask(const Task::Tag &tag);
virtual void
deleteTask(const Task::TaskMatcher &matcher);
virtual void
rescheduleTask(const Task::Tag &tag);
void
eventLoop();
event_base *
base() { return m_base; }
// used in test
int
size();
protected:
bool
addToMap(const TaskPtr &task);
protected:
typedef map<Task::Tag, TaskPtr> TaskMap;
typedef map<Task::Tag, TaskPtr>::iterator TaskMapIt;
typedef boost::shared_mutex Mutex;
typedef boost::unique_lock<Mutex> WriteLock;
typedef boost::shared_lock<Mutex> ReadLock;
TaskMap m_taskMap;
Mutex m_mutex;
event_base *m_base;
boost::thread m_thread;
};
class SimpleIntervalGenerator : public IntervalGenerator
{
public:
SimpleIntervalGenerator(double interval) : m_interval(interval) {}
~SimpleIntervalGenerator(){}
virtual double
nextInterval() _OVERRIDE { return m_interval; }
private:
double m_interval;
};
class RandomIntervalGenerator : public IntervalGenerator
{
public:
typedef enum
{
UP = 1,
DOWN = 2,
EVEN = 3
} Direction;
public:
RandomIntervalGenerator(double interval, double percent, Direction direction = EVEN);
~RandomIntervalGenerator(){}
virtual double
nextInterval() _OVERRIDE;
private:
inline double fractional(double x) { double dummy; return abs(modf(x, &dummy)); }
private:
typedef boost::mt19937 RNG_TYPE;
RNG_TYPE m_rng;
boost::uniform_real<> m_dist;
boost::variate_generator<RNG_TYPE &, boost::uniform_real<> > m_random;
Direction m_direction;
double m_interval;
double m_percent;
};
#endif // EVENT_SCHEDULER_H