aboutsummaryrefslogtreecommitdiff
path: root/src/scheduler.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/scheduler.h')
-rw-r--r--src/scheduler.h95
1 files changed, 51 insertions, 44 deletions
diff --git a/src/scheduler.h b/src/scheduler.h
index 1e64195484..d7fe00d1b4 100644
--- a/src/scheduler.h
+++ b/src/scheduler.h
@@ -5,11 +5,6 @@
#ifndef BITCOIN_SCHEDULER_H
#define BITCOIN_SCHEDULER_H
-//
-// NOTE:
-// boost::thread should be ported to std::thread
-// when we support C++11.
-//
#include <condition_variable>
#include <functional>
#include <list>
@@ -17,24 +12,23 @@
#include <sync.h>
-//
-// Simple class for background tasks that should be run
-// periodically or once "after a while"
-//
-// Usage:
-//
-// CScheduler* s = new CScheduler();
-// s->scheduleFromNow(doSomething, std::chrono::milliseconds{11}); // Assuming a: void doSomething() { }
-// s->scheduleFromNow([=] { this->func(argument); }, std::chrono::milliseconds{3});
-// boost::thread* t = new boost::thread(std::bind(CScheduler::serviceQueue, s));
-//
-// ... then at program shutdown, make sure to call stop() to clean up the thread(s) running serviceQueue:
-// s->stop();
-// t->join();
-// delete t;
-// delete s; // Must be done after thread is interrupted/joined.
-//
-
+/**
+ * Simple class for background tasks that should be run
+ * periodically or once "after a while"
+ *
+ * Usage:
+ *
+ * CScheduler* s = new CScheduler();
+ * s->scheduleFromNow(doSomething, std::chrono::milliseconds{11}); // Assuming a: void doSomething() { }
+ * s->scheduleFromNow([=] { this->func(argument); }, std::chrono::milliseconds{3});
+ * std::thread* t = new std::thread([&] { s->serviceQueue(); });
+ *
+ * ... then at program shutdown, make sure to call stop() to clean up the thread(s) running serviceQueue:
+ * s->stop();
+ * t->join();
+ * delete t;
+ * delete s; // Must be done after thread is interrupted/joined.
+ */
class CScheduler
{
public:
@@ -43,7 +37,7 @@ public:
typedef std::function<void()> Function;
- // Call func at/after time t
+ /** Call func at/after time t */
void schedule(Function f, std::chrono::system_clock::time_point t);
/** Call f once after the delta has passed */
@@ -67,23 +61,33 @@ public:
*/
void MockForward(std::chrono::seconds delta_seconds);
- // To keep things as simple as possible, there is no unschedule.
-
- // Services the queue 'forever'. Should be run in a thread,
- // and interrupted using boost::interrupt_thread
+ /**
+ * Services the queue 'forever'. Should be run in a thread,
+ * and interrupted using boost::interrupt_thread
+ */
void serviceQueue();
- // Tell any threads running serviceQueue to stop as soon as they're
- // done servicing whatever task they're currently servicing (drain=false)
- // or when there is no work left to be done (drain=true)
- void stop(bool drain=false);
+ /** Tell any threads running serviceQueue to stop as soon as the current task is done */
+ void stop()
+ {
+ WITH_LOCK(newTaskMutex, stopRequested = true);
+ newTaskScheduled.notify_all();
+ }
+ /** Tell any threads running serviceQueue to stop when there is no work left to be done */
+ void StopWhenDrained()
+ {
+ WITH_LOCK(newTaskMutex, stopWhenEmpty = true);
+ newTaskScheduled.notify_all();
+ }
- // Returns number of tasks waiting to be serviced,
- // and first and last task times
- size_t getQueueInfo(std::chrono::system_clock::time_point &first,
- std::chrono::system_clock::time_point &last) const;
+ /**
+ * Returns number of tasks waiting to be serviced,
+ * and first and last task times
+ */
+ size_t getQueueInfo(std::chrono::system_clock::time_point& first,
+ std::chrono::system_clock::time_point& last) const;
- // Returns true if there are threads actively running in serviceQueue()
+ /** Returns true if there are threads actively running in serviceQueue() */
bool AreThreadsServicingQueue() const;
private:
@@ -106,19 +110,20 @@ private:
* B() will be able to observe all of the effects of callback A() which executed
* before it.
*/
-class SingleThreadedSchedulerClient {
+class SingleThreadedSchedulerClient
+{
private:
- CScheduler *m_pscheduler;
+ CScheduler* m_pscheduler;
RecursiveMutex m_cs_callbacks_pending;
- std::list<std::function<void ()>> m_callbacks_pending GUARDED_BY(m_cs_callbacks_pending);
+ std::list<std::function<void()>> m_callbacks_pending GUARDED_BY(m_cs_callbacks_pending);
bool m_are_callbacks_running GUARDED_BY(m_cs_callbacks_pending) = false;
void MaybeScheduleProcessQueue();
void ProcessQueue();
public:
- explicit SingleThreadedSchedulerClient(CScheduler *pschedulerIn) : m_pscheduler(pschedulerIn) {}
+ explicit SingleThreadedSchedulerClient(CScheduler* pschedulerIn) : m_pscheduler(pschedulerIn) {}
/**
* Add a callback to be executed. Callbacks are executed serially
@@ -126,10 +131,12 @@ public:
* Practically, this means that callbacks can behave as if they are executed
* in order by a single thread.
*/
- void AddToProcessQueue(std::function<void ()> func);
+ void AddToProcessQueue(std::function<void()> func);
- // Processes all remaining queue members on the calling thread, blocking until queue is empty
- // Must be called after the CScheduler has no remaining processing threads!
+ /**
+ * Processes all remaining queue members on the calling thread, blocking until queue is empty
+ * Must be called after the CScheduler has no remaining processing threads!
+ */
void EmptyQueue();
size_t CallbacksPending();