]>
Commit | Line | Data |
---|---|---|
928b950e GA |
1 | // Copyright (c) 2015 The Bitcoin Core developers |
2 | // Distributed under the MIT software license, see the accompanying | |
bc909a7a | 3 | // file COPYING or https://www.opensource.org/licenses/mit-license.php . |
928b950e GA |
4 | |
5 | #ifndef BITCOIN_SCHEDULER_H | |
6 | #define BITCOIN_SCHEDULER_H | |
7 | ||
8 | // | |
9 | // NOTE: | |
10 | // boost::thread / boost::function / boost::chrono should be ported to | |
11 | // std::thread / std::function / std::chrono when we support C++11. | |
12 | // | |
13 | #include <boost/function.hpp> | |
14 | #include <boost/chrono/chrono.hpp> | |
15 | #include <boost/thread.hpp> | |
16 | #include <map> | |
17 | ||
18 | // | |
19 | // Simple class for background tasks that should be run | |
20 | // periodically or once "after a while" | |
21 | // | |
22 | // Usage: | |
23 | // | |
24 | // CScheduler* s = new CScheduler(); | |
25 | // s->scheduleFromNow(doSomething, 11); // Assuming a: void doSomething() { } | |
26 | // s->scheduleFromNow(boost::bind(Class::func, this, argument), 3); | |
27 | // boost::thread* t = new boost::thread(boost::bind(CScheduler::serviceQueue, s)); | |
28 | // | |
29 | // ... then at program shutdown, clean up the thread running serviceQueue: | |
30 | // t->interrupt(); | |
31 | // t->join(); | |
32 | // delete t; | |
33 | // delete s; // Must be done after thread is interrupted/joined. | |
34 | // | |
35 | ||
36 | class CScheduler | |
37 | { | |
38 | public: | |
39 | CScheduler(); | |
40 | ~CScheduler(); | |
41 | ||
42 | typedef boost::function<void(void)> Function; | |
43 | ||
44 | // Call func at/after time t | |
45 | void schedule(Function f, boost::chrono::system_clock::time_point t); | |
46 | ||
47 | // Convenience method: call f once deltaSeconds from now | |
48 | void scheduleFromNow(Function f, int64_t deltaSeconds); | |
49 | ||
50 | // Another convenience method: call f approximately | |
51 | // every deltaSeconds forever, starting deltaSeconds from now. | |
52 | // To be more precise: every time f is finished, it | |
53 | // is rescheduled to run deltaSeconds later. If you | |
54 | // need more accurate scheduling, don't use this method. | |
55 | void scheduleEvery(Function f, int64_t deltaSeconds); | |
56 | ||
57 | // To keep things as simple as possible, there is no unschedule. | |
58 | ||
59 | // Services the queue 'forever'. Should be run in a thread, | |
60 | // and interrupted using boost::interrupt_thread | |
61 | void serviceQueue(); | |
62 | ||
f5010548 GA |
63 | // Tell any threads running serviceQueue to stop as soon as they're |
64 | // done servicing whatever task they're currently servicing (drain=false) | |
65 | // or when there is no work left to be done (drain=true) | |
66 | void stop(bool drain=false); | |
67 | ||
68 | // Returns number of tasks waiting to be serviced, | |
69 | // and first and last task times | |
70 | size_t getQueueInfo(boost::chrono::system_clock::time_point &first, | |
71 | boost::chrono::system_clock::time_point &last) const; | |
72 | ||
928b950e GA |
73 | private: |
74 | std::multimap<boost::chrono::system_clock::time_point, Function> taskQueue; | |
75 | boost::condition_variable newTaskScheduled; | |
f5010548 | 76 | mutable boost::mutex newTaskMutex; |
928b950e | 77 | int nThreadsServicingQueue; |
f5010548 GA |
78 | bool stopRequested; |
79 | bool stopWhenEmpty; | |
80 | bool shouldStop() { return stopRequested || (stopWhenEmpty && taskQueue.empty()); } | |
928b950e GA |
81 | }; |
82 | ||
83 | #endif |