refactor class Task
diff --git a/include/event-scheduler.h b/include/event-scheduler.h
index 2a10b67..2055598 100644
--- a/include/event-scheduler.h
+++ b/include/event-scheduler.h
@@ -58,16 +58,13 @@
// used to match tasks
typedef boost::function<bool (const TaskPtr &task)> TaskMatcher;
- // 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
// 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, const IntervalGeneratorPtr &generator = IntervalGenerator::Null);
- ~Task();
+ Task(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler);
+ virtual ~Task();
virtual void
- run();
+ run() = 0;
Tag
tag() { return m_tag; }
@@ -78,20 +75,17 @@
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);
- bool
- isPeriodic() { return m_generator != IntervalGenerator::Null; }
-
- // Task needs to be resetted after the callback is invoked if it is to be schedule again; just for safety
- void
- reset();
-
-protected:
- void
- selfClean();
-
protected:
Callback m_callback;
Tag m_tag;
@@ -99,9 +93,49 @@
bool m_invoked;
event *m_event;
timeval *m_tv;
- IntervalGeneratorPtr m_generator;
};
+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 { };
@@ -119,13 +153,7 @@
virtual void
shutdown();
- // add a one time task, delay is in seconds
- // if task with the same tag exists, return false
- virtual bool
- addTask(const TaskPtr &task, double delay);
-
- // add periodic task; task must have an interval generator
- // if task with the same tag exists, return false
+ // if task with the same tag exists, the task is not added and return false
virtual bool
addTask(const TaskPtr &task);
@@ -142,8 +170,8 @@
virtual void
deleteTask(const Task::TaskMatcher &matcher);
- // for periodic tasks, reschedule the next invoke
// 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);
diff --git a/src/event-scheduler.cpp b/src/event-scheduler.cpp
index 77b86d2..be67aad 100644
--- a/src/event-scheduler.cpp
+++ b/src/event-scheduler.cpp
@@ -14,14 +14,13 @@
task = NULL;
}
-Task::Task(const Callback &callback, const Tag &tag, const SchedulerPtr &scheduler, const IntervalGeneratorPtr &generator)
+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_generator(generator)
{
m_event = evtimer_new(scheduler->base(), eventCallback, this);
m_tv = new timeval;
@@ -43,42 +42,6 @@
}
void
-Task::run()
-{
- if (!m_invoked)
- {
- m_callback();
- m_invoked = true;
- }
- if (isPeriodic())
- {
- reset();
- m_scheduler->rescheduleTask(m_tag);
- }
- else
- {
- selfClean();
- }
-}
-
-void
-Task::selfClean()
-{
- m_scheduler->deleteTask(m_tag);
-}
-
-void
-Task::reset()
-{
- m_invoked = false;
- if (isPeriodic())
- {
- double interval = m_generator->nextInterval();
- setTv(interval);
- }
-}
-
-void
Task::setTv(double delay)
{
double intPart, fraction;
@@ -87,6 +50,60 @@
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))
@@ -144,26 +161,9 @@
}
bool
-Scheduler::addTask(const TaskPtr &task, double delay)
-{
- TaskPtr newTask = task;
- newTask->setTv(delay);
- if (addToMap(newTask))
- {
- evtimer_add(newTask->ev(), newTask->tv());
- return true;
- }
- return false;
-}
-
-bool
Scheduler::addTask(const TaskPtr &task)
{
TaskPtr newTask = task;
- if (!newTask->isPeriodic())
- {
- return false;
- }
if (addToMap(newTask))
{
@@ -183,10 +183,8 @@
if (it != m_taskMap.end())
{
TaskPtr task = it->second;
- if (task->isPeriodic())
- {
- evtimer_add(task->ev(), task->tv());
- }
+ task->reset();
+ evtimer_add(task->ev(), task->tv());
}
}
diff --git a/src/sync-core.h b/src/sync-core.h
index 97d559d..7e787d3 100644
--- a/src/sync-core.h
+++ b/src/sync-core.h
@@ -24,6 +24,7 @@
#include "sync-log.h"
#include <ccnx-wrapper.h>
+#include <event-scheduler.h>
using namespace std;
using namespace Ccnx;
@@ -31,12 +32,13 @@
class SyncCore
{
public:
- SyncCore(const string &path, const Name &localName, CcnxWrapperPtr handle);
+ SyncCore(const string &path, const Name &localName, CcnxWrapperPtr handle, SchedulerPtr scheduler);
~SyncCore();
protected:
SyncLog m_log;
CcnxWrapperPtr m_handle;
+ SchedulerPtr m_scheduler;
};
#endif // SYNC_CORE_H
diff --git a/test/test-event-scheduler.cc b/test/test-event-scheduler.cc
index 950a69e..4642d95 100644
--- a/test/test-event-scheduler.cc
+++ b/test/test-event-scheduler.cc
@@ -42,33 +42,29 @@
string tag2 = "world";
string tag3 = "period";
- TaskPtr task1(new Task(boost::bind(func, tag1), tag1, scheduler));
- TaskPtr task2(new Task(boost::bind(func, tag2), tag2, scheduler));
- TaskPtr task3(new Task(boost::bind(func, tag3), tag3, scheduler, generator));
+ TaskPtr task1(new OneTimeTask(boost::bind(func, tag1), tag1, scheduler, 0.5));
+ TaskPtr task2(new OneTimeTask(boost::bind(func, tag2), tag2, scheduler, 0.5));
+ TaskPtr task3(new PeriodicTask(boost::bind(func, tag3), tag3, scheduler, generator));
scheduler->start();
- scheduler->addTask(task1, 0.5);
- scheduler->addTask(task2, 0.5);
+ scheduler->addTask(task1);
+ scheduler->addTask(task2);
scheduler->addTask(task3);
BOOST_CHECK_EQUAL(scheduler->size(), 3);
usleep(600000);
BOOST_CHECK_EQUAL(scheduler->size(), 1);
- task1->reset();
- scheduler->addTask(task1, 0.5);
+ scheduler->addTask(task1);
BOOST_CHECK_EQUAL(scheduler->size(), 2);
usleep(600000);
- task1->reset();
- scheduler->addTask(task1, 0.5);
+ scheduler->addTask(task1);
BOOST_CHECK_EQUAL(scheduler->size(), 2);
usleep(400000);
scheduler->deleteTask(task1->tag());
BOOST_CHECK_EQUAL(scheduler->size(), 1);
usleep(200000);
- task1->reset();
- task2->reset();
- scheduler->addTask(task1, 0.5);
- scheduler->addTask(task2, 0.5);
+ scheduler->addTask(task1);
+ scheduler->addTask(task2);
BOOST_CHECK_EQUAL(scheduler->size(), 3);
usleep(100000);
scheduler->deleteTask(bind(matcher, _1));