5
5
#ifndef BITCOIN_SCHEDULER_H
6
6
#define BITCOIN_SCHEDULER_H
7
7
8
- //
9
- // NOTE:
10
- // boost::thread should be ported to std::thread
11
- // when we support C++11.
12
- //
13
8
#include < condition_variable>
14
9
#include < functional>
15
10
#include < list>
16
11
#include < map>
17
12
18
13
#include < sync.h>
19
14
20
- //
21
- // Simple class for background tasks that should be run
22
- // periodically or once "after a while"
23
- //
24
- // Usage:
25
- //
26
- // CScheduler* s = new CScheduler();
27
- // s->scheduleFromNow(doSomething, std::chrono::milliseconds{11}); // Assuming a: void doSomething() { }
28
- // s->scheduleFromNow([=] { this->func(argument); }, std::chrono::milliseconds{3});
29
- // boost::thread* t = new boost::thread(std::bind(CScheduler::serviceQueue, s));
30
- //
31
- // ... then at program shutdown, make sure to call stop() to clean up the thread(s) running serviceQueue:
32
- // s->stop();
33
- // t->join();
34
- // delete t;
35
- // delete s; // Must be done after thread is interrupted/joined.
36
- //
37
-
15
+ /* *
16
+ * Simple class for background tasks that should be run
17
+ * periodically or once "after a while"
18
+ *
19
+ * Usage:
20
+ *
21
+ * CScheduler* s = new CScheduler();
22
+ * s->scheduleFromNow(doSomething, std::chrono::milliseconds{11}); // Assuming a: void doSomething() { }
23
+ * s->scheduleFromNow([=] { this->func(argument); }, std::chrono::milliseconds{3});
24
+ * std::thread* t = new std::thread([&] { s->serviceQueue(); });
25
+ *
26
+ * ... then at program shutdown, make sure to call stop() to clean up the thread(s) running serviceQueue:
27
+ * s->stop();
28
+ * t->join();
29
+ * delete t;
30
+ * delete s; // Must be done after thread is interrupted/joined.
31
+ */
38
32
class CScheduler
39
33
{
40
34
public:
@@ -43,7 +37,7 @@ class CScheduler
43
37
44
38
typedef std::function<void ()> Function;
45
39
46
- // Call func at/after time t
40
+ /* * Call func at/after time t */
47
41
void schedule (Function f, std::chrono::system_clock::time_point t);
48
42
49
43
/* * Call f once after the delta has passed */
@@ -67,23 +61,33 @@ class CScheduler
67
61
*/
68
62
void MockForward (std::chrono::seconds delta_seconds);
69
63
70
- // To keep things as simple as possible, there is no unschedule.
71
-
72
- // Services the queue 'forever'. Should be run in a thread,
73
- // and interrupted using boost::interrupt_thread
64
+ /* *
65
+ * Services the queue 'forever'. Should be run in a thread,
66
+ * and interrupted using boost::interrupt_thread
67
+ */
74
68
void serviceQueue ();
75
69
76
- // Tell any threads running serviceQueue to stop as soon as they're
77
- // done servicing whatever task they're currently servicing (drain=false)
78
- // or when there is no work left to be done (drain=true)
79
- void stop (bool drain=false );
70
+ /* * Tell any threads running serviceQueue to stop as soon as the current task is done */
71
+ void stop ()
72
+ {
73
+ WITH_LOCK (newTaskMutex, stopRequested = true );
74
+ newTaskScheduled.notify_all ();
75
+ }
76
+ /* * Tell any threads running serviceQueue to stop when there is no work left to be done */
77
+ void StopWhenDrained ()
78
+ {
79
+ WITH_LOCK (newTaskMutex, stopWhenEmpty = true );
80
+ newTaskScheduled.notify_all ();
81
+ }
80
82
81
- // Returns number of tasks waiting to be serviced,
82
- // and first and last task times
83
- size_t getQueueInfo (std::chrono::system_clock::time_point &first,
84
- std::chrono::system_clock::time_point &last) const ;
83
+ /* *
84
+ * Returns number of tasks waiting to be serviced,
85
+ * and first and last task times
86
+ */
87
+ size_t getQueueInfo (std::chrono::system_clock::time_point& first,
88
+ std::chrono::system_clock::time_point& last) const ;
85
89
86
- // Returns true if there are threads actively running in serviceQueue()
90
+ /* * Returns true if there are threads actively running in serviceQueue() */
87
91
bool AreThreadsServicingQueue () const ;
88
92
89
93
private:
@@ -106,30 +110,33 @@ class CScheduler
106
110
* B() will be able to observe all of the effects of callback A() which executed
107
111
* before it.
108
112
*/
109
- class SingleThreadedSchedulerClient {
113
+ class SingleThreadedSchedulerClient
114
+ {
110
115
private:
111
- CScheduler * m_pscheduler;
116
+ CScheduler* m_pscheduler;
112
117
113
118
RecursiveMutex m_cs_callbacks_pending;
114
- std::list<std::function<void ()>> m_callbacks_pending GUARDED_BY (m_cs_callbacks_pending);
119
+ std::list<std::function<void ()>> m_callbacks_pending GUARDED_BY (m_cs_callbacks_pending);
115
120
bool m_are_callbacks_running GUARDED_BY (m_cs_callbacks_pending) = false;
116
121
117
122
void MaybeScheduleProcessQueue ();
118
123
void ProcessQueue ();
119
124
120
125
public:
121
- explicit SingleThreadedSchedulerClient (CScheduler * pschedulerIn) : m_pscheduler(pschedulerIn) {}
126
+ explicit SingleThreadedSchedulerClient (CScheduler* pschedulerIn) : m_pscheduler(pschedulerIn) {}
122
127
123
128
/* *
124
129
* Add a callback to be executed. Callbacks are executed serially
125
130
* and memory is release-acquire consistent between callback executions.
126
131
* Practically, this means that callbacks can behave as if they are executed
127
132
* in order by a single thread.
128
133
*/
129
- void AddToProcessQueue (std::function<void ()> func);
134
+ void AddToProcessQueue (std::function<void ()> func);
130
135
131
- // Processes all remaining queue members on the calling thread, blocking until queue is empty
132
- // Must be called after the CScheduler has no remaining processing threads!
136
+ /* *
137
+ * Processes all remaining queue members on the calling thread, blocking until queue is empty
138
+ * Must be called after the CScheduler has no remaining processing threads!
139
+ */
133
140
void EmptyQueue ();
134
141
135
142
size_t CallbacksPending ();
0 commit comments