Separating scheduler into bunch of files
diff --git a/include/event-scheduler.h b/include/event-scheduler.h
deleted file mode 100644
index 5f2c7b2..0000000
--- a/include/event-scheduler.h
+++ /dev/null
@@ -1,253 +0,0 @@
-#ifndef EVENT_SCHEDULER_H
-#define EVENT_SCHEDULER_H
-
-// use pthread
-
-#include <event2/event.h>
-#include <event2/thread.h>
-#include <event2/event-config.h>
-#include <event2/util.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;
-
-// callback used by libevent
-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:
-  // callback of this task
-  typedef boost::function<void ()> Callback;
-  // tag identifies this task, should be unique
-  typedef string Tag;
-  // used to match tasks
-  typedef boost::function<bool (const TaskPtr &task)> TaskMatcher;
-
-
-  // Task is associated with Schedulers due to the requirement that libevent event is associated with an libevent event_base
-  Task(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler);
-  virtual ~Task();
-
-  virtual void
-  run() = 0;
-
-  Tag
-  tag() { return m_tag; }
-
-  event *
-  ev() { return m_event; }
-
-  timeval *
-  tv() { return m_tv; }
-
-  // Task needs to be resetted after the callback is invoked if it is to be schedule again; just for safety
-  // it's called by scheduler automatically when addTask or rescheduleTask is called;
-  // Tasks should do preparation work here (e.g. set up new delay, etc. )
-  virtual void
-  reset() = 0;
-
-  // set delay
-  // This overrides whatever delay kept in m_tv
-  void
-  setTv(double delay);
-
-protected:
-  Callback m_callback;
-  Tag m_tag;
-  SchedulerPtr m_scheduler;
-  bool m_invoked;
-  event *m_event;
-  timeval *m_tv;
-};
-
-class OneTimeTask : public Task
-{
-public:
-  OneTimeTask(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler, double delay);
-  virtual ~OneTimeTask(){}
-
-  // invoke callback and mark self as invoked and deregister self from scheduler
-  virtual void
-  run() _OVERRIDE;
-
-  // after reset, the task is marked as un-invoked and can be add to scheduler again, with same delay
-  // if not invoked yet, no effect
-  virtual void
-  reset() _OVERRIDE;
-
-private:
-  // this is to deregister itself from scheduler automatically after invoke
-  void
-  deregisterSelf();
-};
-
-class PeriodicTask : public Task
-{
-public:
-  // generator is needed only when this is a periodic task
-  // two simple generators implementation (SimpleIntervalGenerator and RandomIntervalGenerator) are provided;
-  // if user needs more complex pattern in the intervals between calls, extend class IntervalGenerator
-  PeriodicTask(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler, const IntervalGeneratorPtr &generator);
-  virtual ~PeriodicTask(){}
-
-  // invoke callback, reset self and ask scheduler to schedule self with the next delay interval
-  virtual void
-  run() _OVERRIDE;
-
-  // set the next delay and mark as un-invoke
-  virtual void
-  reset() _OVERRIDE;
-
-private:
-  IntervalGeneratorPtr m_generator;
-};
-
-struct SchedulerException : virtual boost::exception, virtual exception { };
-
-class Scheduler
-{
-public:
-  Scheduler();
-  virtual ~Scheduler();
-
-  // start event scheduling
-  virtual void
-  start();
-
-  // stop event scheduling
-  virtual void
-  shutdown();
-
-  // if task with the same tag exists, the task is not added and return false
-  virtual bool
-  addTask(const TaskPtr &task);
-
-  // delete task by tag, regardless of whether it's invoked or not
-  // if no task is found, no effect
-  virtual void
-  deleteTask(const Task::Tag &tag);
-
-  // delete tasks by matcher, regardless of whether it's invoked or not
-  // this is flexiable in that you can use any form of criteria in finding tasks to delete
-  // but keep in mind this is a linear scan
-
-  // if no task is found, no effect
-  virtual void
-  deleteTask(const Task::TaskMatcher &matcher);
-
-  // task must already have been added to the scheduler, otherwise this is no effect
-  // this is usually used by PeriodicTask
-  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;
-  bool m_running;
-  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;
-};
-
-// generates intervals with uniform distribution
-class RandomIntervalGenerator : public IntervalGenerator
-{
-public:
-  typedef enum
-  {
-    UP = 1,
-    DOWN = 2,
-    EVEN = 3
-  } Direction;
-
-public:
-  // percent is random-range/interval; e.g. if interval is 10 and you wish the random-range to be 2
-  // e.g. 9 ~ 11, percent = 0.2
-  // direction shifts the random range; e.g. in the above example, UP would produce a range of
-  // 10 ~ 12, DOWN of 8 ~ 10, and EVEN of 9 ~ 11
-  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_percent;
-  double m_interval;
-
-};
-#endif // EVENT_SCHEDULER_H
diff --git "a/scheduler/.\043task.h" "b/scheduler/.\043task.h"
new file mode 120000
index 0000000..383dd59
--- /dev/null
+++ "b/scheduler/.\043task.h"
@@ -0,0 +1 @@
+cawka@cawka-mac.11861
\ No newline at end of file
diff --git a/scheduler/interval-generator.h b/scheduler/interval-generator.h
new file mode 100644
index 0000000..ce95b5a
--- /dev/null
+++ b/scheduler/interval-generator.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef INTERVAL_GENERATOR_H
+#define INTERVAL_GENERATOR_H
+
+#include <boost/shared_ptr.hpp>
+
+using namespace std;
+
+class IntervalGenerator;
+typedef boost::shared_ptr<IntervalGenerator> IntervalGeneratorPtr;
+
+class IntervalGenerator
+{
+public:
+  virtual double
+  nextInterval() = 0;
+};
+
+
+#endif // INTERVAL_GENERATOR_H
diff --git a/scheduler/one-time-task.cc b/scheduler/one-time-task.cc
new file mode 100644
index 0000000..e31c951
--- /dev/null
+++ b/scheduler/one-time-task.cc
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "one-time-task.h"
+#include "scheduler.h"
+
+OneTimeTask::OneTimeTask(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler, double delay)
+            : Task(callback, tag, scheduler)
+{
+  setTv(delay);
+}
+
+void
+OneTimeTask::run()
+{
+  if (!m_invoked)
+  {
+    m_callback();
+    m_invoked = true;
+    deregisterSelf();
+  }
+}
+
+void
+OneTimeTask::deregisterSelf()
+{
+  m_scheduler->deleteTask(m_tag);
+}
+
+void
+OneTimeTask::reset()
+{
+  m_invoked = false;
+}
diff --git a/scheduler/one-time-task.h b/scheduler/one-time-task.h
new file mode 100644
index 0000000..1b900e1
--- /dev/null
+++ b/scheduler/one-time-task.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef ONE_TIME_TASK_H
+#define ONE_TIME_TASK_H
+
+#include "task.h"
+
+class OneTimeTask : public Task
+{
+public:
+  OneTimeTask(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler, double delay);
+  virtual ~OneTimeTask(){}
+
+  // invoke callback and mark self as invoked and deregister self from scheduler
+  virtual void
+  run() _OVERRIDE;
+
+  // after reset, the task is marked as un-invoked and can be add to scheduler again, with same delay
+  // if not invoked yet, no effect
+  virtual void
+  reset() _OVERRIDE;
+
+private:
+  // this is to deregister itself from scheduler automatically after invoke
+  void
+  deregisterSelf();
+};
+
+
+#endif // EVENT_SCHEDULER_H
diff --git a/scheduler/periodic-task.cc b/scheduler/periodic-task.cc
new file mode 100644
index 0000000..b8fd3a7
--- /dev/null
+++ b/scheduler/periodic-task.cc
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "periodic-task.h"
+#include <utility>
+
+PeriodicTask::PeriodicTask(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler, const IntervalGeneratorPtr &generator)
+             : Task(callback, tag, scheduler)
+             , m_generator(generator)
+{
+}
+
+void
+PeriodicTask::run()
+{
+  if (!m_invoked)
+  {
+    m_callback();
+    m_invoked = true;
+    m_scheduler->rescheduleTask(m_tag);
+  }
+}
+
+void
+PeriodicTask::reset()
+{
+  m_invoked = false;
+  double interval = m_generator->nextInterval();
+  setTv(interval);
+}
diff --git a/scheduler/periodic-task.h b/scheduler/periodic-task.h
new file mode 100644
index 0000000..8536b6f
--- /dev/null
+++ b/scheduler/periodic-task.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef PERIODIC_TASK_H
+#define PERIODIC_TASK_H
+
+#include "task.h"
+#include "scheduler.h"
+#include "interval-generator.h"
+
+class PeriodicTask : public Task
+{
+public:
+  // generator is needed only when this is a periodic task
+  // two simple generators implementation (SimpleIntervalGenerator and RandomIntervalGenerator) are provided;
+  // if user needs more complex pattern in the intervals between calls, extend class IntervalGenerator
+  PeriodicTask(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler, const IntervalGeneratorPtr &generator);
+  virtual ~PeriodicTask(){}
+
+  // invoke callback, reset self and ask scheduler to schedule self with the next delay interval
+  virtual void
+  run() _OVERRIDE;
+
+  // set the next delay and mark as un-invoke
+  virtual void
+  reset() _OVERRIDE;
+
+private:
+  IntervalGeneratorPtr m_generator;
+};
+
+#endif // PERIODIC_TASK_H
diff --git a/scheduler/random-interval-generator.h b/scheduler/random-interval-generator.h
new file mode 100644
index 0000000..c0f6276
--- /dev/null
+++ b/scheduler/random-interval-generator.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef RANDOM_INTERVAL_GENERATOR_H
+#define RANDOM_INTERVAL_GENERATOR_H
+
+#include "interval-generator.h"
+
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/random/uniform_real.hpp>
+#include <boost/random/variate_generator.hpp>
+
+// generates intervals with uniform distribution
+class RandomIntervalGenerator : public IntervalGenerator
+{
+public:
+  typedef enum
+  {
+    UP = 1,
+    DOWN = 2,
+    EVEN = 3
+  } Direction;
+
+public:
+  // percent is random-range/interval; e.g. if interval is 10 and you wish the random-range to be 2
+  // e.g. 9 ~ 11, percent = 0.2
+  // direction shifts the random range; e.g. in the above example, UP would produce a range of
+  // 10 ~ 12, DOWN of 8 ~ 10, and EVEN of 9 ~ 11
+  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_percent;
+  double m_interval;
+
+};
+#endif // RANDOM_INTERVAL_GENERATOR_H
diff --git a/scheduler/scheduler.cc b/scheduler/scheduler.cc
new file mode 100644
index 0000000..e4f93e4
--- /dev/null
+++ b/scheduler/scheduler.cc
@@ -0,0 +1,184 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "scheduler.h"
+#include <utility>
+
+using namespace std;
+
+#define EVLOOP_NO_EXIT_ON_EMPTY 0x04
+
+// IntervalGeneratorPtr
+// IntervalGenerator:: Null;
+
+void errorCallback(int err)
+{
+  cout << "Fatal error: " << err << endl;
+}
+
+Scheduler::Scheduler()
+  : m_running(false)
+{
+  event_set_fatal_callback(errorCallback);
+  evthread_use_pthreads();
+  m_base = event_base_new();
+}
+
+Scheduler::~Scheduler()
+{
+  event_base_free(m_base);
+}
+
+void
+Scheduler::eventLoop()
+{
+  while(true)
+  {
+    if (event_base_loop(m_base, EVLOOP_NO_EXIT_ON_EMPTY) < 0)
+    {
+      cout << "scheduler loop break error" << endl;
+    }
+    ReadLock lock(m_mutex);
+    if (!m_running)
+    {
+      cout << "scheduler loop break normal" << endl;
+      break;
+    }
+  }
+}
+
+void
+Scheduler::start()
+{
+  WriteLock lock(m_mutex);
+  if (!m_running)
+  {
+    m_thread = boost::thread(&Scheduler::eventLoop, this);
+    m_running = true;
+  }
+}
+
+void
+Scheduler::shutdown()
+{
+  WriteLock lock(m_mutex);
+  if (m_running)
+  {
+    event_base_loopbreak(m_base);
+    m_thread.join();
+    m_running = false;
+  }
+}
+
+bool
+Scheduler::addTask(const TaskPtr &task)
+{
+  TaskPtr newTask = task;
+
+  if (addToMap(newTask))
+  {
+    newTask->reset();
+    int res = evtimer_add(newTask->ev(), newTask->tv());
+    if (res < 0)
+    {
+      cout << "evtimer_add failed for " << task->tag() << endl;
+    }
+    return true;
+  }
+  else
+  {
+    cout << "fail to add task: " << task->tag() << endl;
+  }
+
+  return false;
+}
+
+void
+Scheduler::rescheduleTask(const Task::Tag &tag)
+{
+  ReadLock lock(m_mutex);
+  TaskMapIt it = m_taskMap.find(tag);
+  if (it != m_taskMap.end())
+  {
+    TaskPtr task = it->second;
+    task->reset();
+    int res = evtimer_add(task->ev(), task->tv());
+    if (res < 0)
+    {
+      cout << "evtimer_add failed for " << task->tag() << endl;
+    }
+  }
+}
+
+bool
+Scheduler::addToMap(const TaskPtr &task)
+{
+  WriteLock lock(m_mutex);
+  if (m_taskMap.find(task->tag()) == m_taskMap.end())
+  {
+    m_taskMap.insert(make_pair(task->tag(), task));
+    return true;
+  }
+  return false;
+}
+
+void
+Scheduler::deleteTask(const Task::Tag &tag)
+{
+  WriteLock lock(m_mutex);
+  TaskMapIt it = m_taskMap.find(tag);
+  if (it != m_taskMap.end())
+  {
+    TaskPtr task = it->second;
+    evtimer_del(task->ev());
+    m_taskMap.erase(it);
+  }
+}
+
+void
+Scheduler::deleteTask(const Task::TaskMatcher &matcher)
+{
+  WriteLock lock(m_mutex);
+  TaskMapIt it = m_taskMap.begin();
+  while(it != m_taskMap.end())
+  {
+    TaskPtr task = it->second;
+    if (matcher(task))
+    {
+      evtimer_del(task->ev());
+      // Use post increment; map.erase invalidate the iterator that is beening erased,
+      // but does not invalidate other iterators. This seems to be the convention to
+      // erase something from C++ STL map while traversing.
+      m_taskMap.erase(it++);
+    }
+    else
+    {
+      ++it;
+    }
+  }
+}
+
+int
+Scheduler::size()
+{
+  ReadLock lock(m_mutex);
+  return m_taskMap.size();
+}
diff --git a/scheduler/scheduler.h b/scheduler/scheduler.h
new file mode 100644
index 0000000..f6f1fe8
--- /dev/null
+++ b/scheduler/scheduler.h
@@ -0,0 +1,113 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef SCHEDULER_H
+#define SCHEDULER_H
+
+#include <event2/event.h>
+#include <event2/thread.h>
+#include <event2/event-config.h>
+#include <event2/util.h>
+
+#include <boost/function.hpp>
+#include <boost/shared_ptr.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>
+
+#include "task.h"
+
+/**
+ * @brief Scheduler class
+ */
+class Scheduler
+{
+public:
+  Scheduler();
+  virtual ~Scheduler();
+
+  // start event scheduling
+  virtual void
+  start();
+
+  // stop event scheduling
+  virtual void
+  shutdown();
+
+  // if task with the same tag exists, the task is not added and return false
+  virtual bool
+  addTask(const TaskPtr &task);
+
+  // delete task by tag, regardless of whether it's invoked or not
+  // if no task is found, no effect
+  virtual void
+  deleteTask(const Task::Tag &tag);
+
+  // delete tasks by matcher, regardless of whether it's invoked or not
+  // this is flexiable in that you can use any form of criteria in finding tasks to delete
+  // but keep in mind this is a linear scan
+
+  // if no task is found, no effect
+  virtual void
+  deleteTask(const Task::TaskMatcher &matcher);
+
+  // task must already have been added to the scheduler, otherwise this method has no effect
+  // this is usually used by PeriodicTask
+  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 std::map<Task::Tag, TaskPtr> TaskMap;
+  typedef std::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;
+  bool m_running;
+  event_base *m_base;
+  boost::thread m_thread;
+};
+
+class Scheduler;
+typedef boost::shared_ptr<Scheduler> SchedulerPtr;
+
+struct SchedulerException : virtual boost::exception, virtual std::exception { };
+
+#endif // SCHEDULER_H
diff --git a/scheduler/simple-interval-generator.h b/scheduler/simple-interval-generator.h
new file mode 100644
index 0000000..06b1181
--- /dev/null
+++ b/scheduler/simple-interval-generator.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef SIMPLE_INTERVAL_GENERATOR_H
+#define SIMPLE_INTERVAL_GENERATOR_H
+
+#include "interval-generator.h"
+
+class SimpleIntervalGenerator : public IntervalGenerator
+{
+public:
+  SimpleIntervalGenerator(double interval) : m_interval (interval) {}
+  virtual ~SimpleIntervalGenerator() {}
+  
+  virtual double
+  nextInterval() _OVERRIDE { return m_interval; }
+
+private:
+  double m_interval;
+};
+
+#endif // SIMPLE_INTERVAL_GENERATOR_H
diff --git a/scheduler/task.cc b/scheduler/task.cc
new file mode 100644
index 0000000..980df48
--- /dev/null
+++ b/scheduler/task.cc
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "task.h"
+#include "scheduler.h"
+
+void
+eventCallback(evutil_socket_t fd, short what, void *arg)
+{
+  Task *task = static_cast<Task *>(arg);
+  task->run();
+  task = NULL;
+}
+
+Task::Task(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler)
+     : m_callback(callback)
+     , m_tag(tag)
+     , m_scheduler(scheduler)
+     , m_invoked(false)
+     , m_event(NULL)
+     , m_tv(NULL)
+{
+  m_event = evtimer_new(scheduler->base(), eventCallback, this);
+  m_tv = new timeval;
+}
+
+Task::~Task()
+{
+  if (m_event != NULL)
+  {
+    event_free(m_event);
+    m_event = NULL;
+  }
+
+  if (m_tv != NULL)
+  {
+    delete m_tv;
+    m_tv = NULL;
+  }
+}
+
+void
+Task::setTv(double delay)
+{
+  double intPart, fraction;
+  fraction = modf(abs(delay), &intPart);
+  m_tv->tv_sec = static_cast<int>(intPart);
+  m_tv->tv_usec = static_cast<int>((fraction * 1000000));
+}
diff --git a/scheduler/task.h b/scheduler/task.h
new file mode 100644
index 0000000..8289c57
--- /dev/null
+++ b/scheduler/task.h
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef TASK_H
+#define TASK_H
+
+#define _OVERRIDE
+#ifdef __GNUC__
+#if __GNUC_MAJOR >= 4 && __GNUC_MINOR__ >= 7
+  #undef _OVERRIDE
+  #define _OVERRIDE override
+#endif // __GNUC__ version
+#endif // __GNUC__
+
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <sys/time.h>
+
+//////////////////////////////////////////////////
+// forward declarations
+class Task;
+typedef boost::shared_ptr<Task> TaskPtr;
+
+class Scheduler;
+typedef boost::shared_ptr<Scheduler> SchedulerPtr;
+
+struct event;
+//////////////////////////////////////////////////
+
+
+/**
+ * @brief Base class for a task
+ */
+class Task
+{
+public:
+  // callback of this task
+  typedef boost::function<void ()> Callback;
+  // tag identifies this task, should be unique
+  typedef std::string Tag;
+  // used to match tasks
+  typedef boost::function<bool (const TaskPtr &task)> TaskMatcher;
+
+  // Task is associated with Schedulers due to the requirement that libevent event is associated with an libevent event_base
+  Task(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler);
+  virtual ~Task();
+
+  virtual void
+  run() = 0;
+
+  Tag
+  tag() { return m_tag; }
+
+  event *
+  ev() { return m_event; }
+
+  timeval *
+  tv() { return m_tv; }
+
+  // Task needs to be resetted after the callback is invoked if it is to be schedule again; just for safety
+  // it's called by scheduler automatically when addTask or rescheduleTask is called;
+  // Tasks should do preparation work here (e.g. set up new delay, etc. )
+  virtual void
+  reset() = 0;
+
+  // set delay
+  // This overrides whatever delay kept in m_tv
+  void
+  setTv(double delay);
+
+protected:
+  Callback m_callback;
+  Tag m_tag;
+  SchedulerPtr m_scheduler;
+  bool m_invoked;
+  event *m_event;
+  timeval *m_tv;
+};
+
+
+#endif // TASK_H
diff --git a/src/event-scheduler.cpp b/src/event-scheduler.cpp
deleted file mode 100644
index ec4b104..0000000
--- a/src/event-scheduler.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-#include "event-scheduler.h"
-#include <utility>
-
-#define EVLOOP_NO_EXIT_ON_EMPTY 0x04
-
-IntervalGeneratorPtr
-IntervalGenerator:: Null;
-
-void
-eventCallback(evutil_socket_t fd, short what, void *arg)
-{
-  Task *task = static_cast<Task *>(arg);
-  task->run();
-  task = NULL;
-}
-
-void errorCallback(int err)
-{
-  cout << "Fatal error: " << err << endl;
-}
-
-Task::Task(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler)
-     : m_callback(callback)
-     , m_tag(tag)
-     , m_scheduler(scheduler)
-     , m_invoked(false)
-     , m_event(NULL)
-     , m_tv(NULL)
-{
-  m_event = evtimer_new(scheduler->base(), eventCallback, this);
-  m_tv = new timeval;
-}
-
-Task::~Task()
-{
-  if (m_event != NULL)
-  {
-    event_free(m_event);
-    m_event = NULL;
-  }
-
-  if (m_tv != NULL)
-  {
-    delete m_tv;
-    m_tv = NULL;
-  }
-}
-
-void
-Task::setTv(double delay)
-{
-  double intPart, fraction;
-  fraction = modf(abs(delay), &intPart);
-  m_tv->tv_sec = static_cast<int>(intPart);
-  m_tv->tv_usec = static_cast<int>((fraction * 1000000));
-}
-
-OneTimeTask::OneTimeTask(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler, double delay)
-            : Task(callback, tag, scheduler)
-{
-  setTv(delay);
-}
-
-void
-OneTimeTask::run()
-{
-  if (!m_invoked)
-  {
-    m_callback();
-    m_invoked = true;
-    deregisterSelf();
-  }
-}
-
-void
-OneTimeTask::deregisterSelf()
-{
-  m_scheduler->deleteTask(m_tag);
-}
-
-void
-OneTimeTask::reset()
-{
-  m_invoked = false;
-}
-
-PeriodicTask::PeriodicTask(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler, const IntervalGeneratorPtr &generator)
-             : Task(callback, tag, scheduler)
-             , m_generator(generator)
-{
-}
-
-void
-PeriodicTask::run()
-{
-  if (!m_invoked)
-  {
-    m_callback();
-    m_invoked = true;
-    m_scheduler->rescheduleTask(m_tag);
-  }
-}
-
-void
-PeriodicTask::reset()
-{
-  m_invoked = false;
-  double interval = m_generator->nextInterval();
-  setTv(interval);
-}
-
-RandomIntervalGenerator::RandomIntervalGenerator(double interval, double percent, Direction direction)
-                        : m_interval(interval)
-                        , m_rng(time(NULL))
-                        , m_percent(percent)
-                        , m_dist(0.0, fractional(percent))
-                        , m_random(m_rng, m_dist)
-                        , m_direction(direction)
-{
-}
-
-double
-RandomIntervalGenerator::nextInterval()
-{
-  double percent = m_random();
-  double interval = m_interval;
-  switch (m_direction)
-  {
-  case UP: interval = m_interval * (1.0 + percent); break;
-  case DOWN: interval = m_interval * (1.0 - percent); break;
-  case EVEN: interval = m_interval * (1.0 - m_percent/2.0 + percent); break;
-  default: break;
-  }
-
-  return interval;
-}
-
-Scheduler::Scheduler() : m_running(false)
-{
-  event_set_fatal_callback(errorCallback);
-  evthread_use_pthreads();
-  m_base = event_base_new();
-}
-
-Scheduler::~Scheduler()
-{
-  event_base_free(m_base);
-}
-
-void
-Scheduler::eventLoop()
-{
-  while(true)
-  {
-    if (event_base_loop(m_base, EVLOOP_NO_EXIT_ON_EMPTY) < 0)
-    {
-      cout << "scheduler loop break error" << endl;
-    }
-    ReadLock lock(m_mutex);
-    if (!m_running)
-    {
-      cout << "scheduler loop break normal" << endl;
-      break;
-    }
-  }
-}
-
-void
-Scheduler::start()
-{
-  WriteLock lock(m_mutex);
-  if (!m_running)
-  {
-    m_thread = boost::thread(&Scheduler::eventLoop, this);
-    m_running = true;
-  }
-}
-
-void
-Scheduler::shutdown()
-{
-  WriteLock lock(m_mutex);
-  if (m_running)
-  {
-    event_base_loopbreak(m_base);
-    m_thread.join();
-    m_running = false;
-  }
-}
-
-bool
-Scheduler::addTask(const TaskPtr &task)
-{
-  TaskPtr newTask = task;
-
-  if (addToMap(newTask))
-  {
-    newTask->reset();
-    int res = evtimer_add(newTask->ev(), newTask->tv());
-    if (res < 0)
-    {
-      cout << "evtimer_add failed for " << task->tag() << endl;
-    }
-    return true;
-  }
-  else
-  {
-    cout << "fail to add task: " << task->tag() << endl;
-  }
-
-  return false;
-}
-
-void
-Scheduler::rescheduleTask(const Task::Tag &tag)
-{
-  ReadLock lock(m_mutex);
-  TaskMapIt it = m_taskMap.find(tag);
-  if (it != m_taskMap.end())
-  {
-    TaskPtr task = it->second;
-    task->reset();
-    int res = evtimer_add(task->ev(), task->tv());
-    if (res < 0)
-    {
-      cout << "evtimer_add failed for " << task->tag() << endl;
-    }
-  }
-}
-
-bool
-Scheduler::addToMap(const TaskPtr &task)
-{
-  WriteLock lock(m_mutex);
-  if (m_taskMap.find(task->tag()) == m_taskMap.end())
-  {
-    m_taskMap.insert(make_pair(task->tag(), task));
-    return true;
-  }
-  return false;
-}
-
-void
-Scheduler::deleteTask(const Task::Tag &tag)
-{
-  WriteLock lock(m_mutex);
-  TaskMapIt it = m_taskMap.find(tag);
-  if (it != m_taskMap.end())
-  {
-    TaskPtr task = it->second;
-    evtimer_del(task->ev());
-    m_taskMap.erase(it);
-  }
-}
-
-void
-Scheduler::deleteTask(const Task::TaskMatcher &matcher)
-{
-  WriteLock lock(m_mutex);
-  TaskMapIt it = m_taskMap.begin();
-  while(it != m_taskMap.end())
-  {
-    TaskPtr task = it->second;
-    if (matcher(task))
-    {
-      evtimer_del(task->ev());
-      // Use post increment; map.erase invalidate the iterator that is beening erased,
-      // but does not invalidate other iterators. This seems to be the convention to
-      // erase something from C++ STL map while traversing.
-      m_taskMap.erase(it++);
-    }
-    else
-    {
-      ++it;
-    }
-  }
-}
-
-int
-Scheduler::size()
-{
-  ReadLock lock(m_mutex);
-  return m_taskMap.size();
-}