PIVX Core  5.6.99
P2P Digital Currency
scheduler.h
Go to the documentation of this file.
1 // Copyright (c) 2015 The Bitcoin Core developers
2 // Copyright (c) 2017-2021 The PIVX Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #ifndef PIVX_SCHEDULER_H
7 #define PIVX_SCHEDULER_H
8 
9 //
10 // NOTE:
11 // boost::thread should be ported to std::thread
12 // when we support C++11.
13 //
14 #include <condition_variable>
15 #include <functional>
16 #include <list>
17 #include <map>
18 
19 #include "sync.h"
20 
21 //
22 // Simple class for background tasks that should be run
23 // periodically or once "after a while"
24 //
25 // Usage:
26 //
27 // CScheduler* s = new CScheduler();
28 // s->scheduleFromNow(doSomething, 11); // Assuming a: void doSomething() { }
29 // s->scheduleFromNow(std::bind(Class::func, this, argument), 3);
30 // boost::thread* t = new boost::thread(std::bind(CScheduler::serviceQueue, s));
31 //
32 // ... then at program shutdown, make sure to call stop() to clean up the thread(s) running serviceQueue:
33 // s->stop();
34 // t->join();
35 // delete t;
36 // delete s; // Must be done after thread is interrupted/joined.
37 //
38 
40 {
41 public:
42  CScheduler();
43  ~CScheduler();
44 
45  typedef std::function<void(void)> Function;
46 
47  // Call func at/after time t
49 
50  // Convenience method: call f once deltaMilliSeconds from now
51  void scheduleFromNow(Function f, int64_t deltaMilliSeconds);
52 
53  // Another convenience method: call f approximately
54  // every deltaMilliSeconds forever, starting deltaMilliSeconds from now.
55  // To be more precise: every time f is finished, it
56  // is rescheduled to run deltaMilliSeconds later. If you
57  // need more accurate scheduling, don't use this method.
58  void scheduleEvery(Function f, int64_t deltaMilliSeconds);
59 
60  // To keep things as simple as possible, there is no unschedule.
61 
62  // Services the queue 'forever'. Should be run in a thread,
63  // and interrupted using boost::interrupt_thread
64  void serviceQueue();
65 
66  // Tell any threads running serviceQueue to stop as soon as they're
67  // done servicing whatever task they're currently servicing (drain=false)
68  // or when there is no work left to be done (drain=true)
69  void stop(bool drain=false);
70 
71  // Returns number of tasks waiting to be serviced,
72  // and first and last task times
75 
76  // Returns true if there are threads actively running in serviceQueue()
77  bool AreThreadsServicingQueue() const;
78 
79 private:
81  std::condition_variable newTaskScheduled;
82  std::multimap<std::chrono::system_clock::time_point, Function> taskQueue GUARDED_BY(newTaskMutex);
83  int nThreadsServicingQueue GUARDED_BY(newTaskMutex);
84  bool stopRequested GUARDED_BY(newTaskMutex);
85  bool stopWhenEmpty GUARDED_BY(newTaskMutex);
86  bool shouldStop() const EXCLUSIVE_LOCKS_REQUIRED(newTaskMutex) { return stopRequested || (stopWhenEmpty && taskQueue.empty()); }
87 };
88 
100 private:
102 
104  std::list<std::function<void (void)>> m_callbacks_pending;
106 
108  void ProcessQueue();
109 
110 public:
111  explicit SingleThreadedSchedulerClient(CScheduler *pschedulerIn) : m_pscheduler(pschedulerIn) {}
112 
119  void AddToProcessQueue(std::function<void (void)> func);
120 
121  // Processes all remaining queue members on the calling thread, blocking until queue is empty
122  // Must be called after the CScheduler has no remaining processing threads!
123  void EmptyQueue();
124 
125  size_t CallbacksPending();
126 };
127 
128 #endif // PIVX_SCHEDULER_H
bool stopWhenEmpty GUARDED_BY(newTaskMutex)
void serviceQueue()
Definition: scheduler.cpp:22
bool stopRequested GUARDED_BY(newTaskMutex)
void stop(bool drain=false)
Definition: scheduler.cpp:73
void schedule(Function f, std::chrono::system_clock::time_point t)
Definition: scheduler.cpp:85
std::multimap< std::chrono::system_clock::time_point, Function > taskQueue GUARDED_BY(newTaskMutex)
std::function< void(void)> Function
Definition: scheduler.h:45
int nThreadsServicingQueue GUARDED_BY(newTaskMutex)
void scheduleFromNow(Function f, int64_t deltaMilliSeconds)
Definition: scheduler.cpp:94
size_t getQueueInfo(std::chrono::system_clock::time_point &first, std::chrono::system_clock::time_point &last) const
Definition: scheduler.cpp:110
void scheduleEvery(Function f, int64_t deltaMilliSeconds)
Definition: scheduler.cpp:105
bool shouldStop() const EXCLUSIVE_LOCKS_REQUIRED(newTaskMutex)
Definition: scheduler.h:86
bool AreThreadsServicingQueue() const
Definition: scheduler.cpp:122
std::condition_variable newTaskScheduled
Definition: scheduler.h:81
Mutex newTaskMutex
Definition: scheduler.h:80
Class used by CScheduler clients which may schedule multiple jobs which are required to be run serial...
Definition: scheduler.h:99
RecursiveMutex m_cs_callbacks_pending
Definition: scheduler.h:103
std::list< std::function< void(void)> > m_callbacks_pending
Definition: scheduler.h:104
SingleThreadedSchedulerClient(CScheduler *pschedulerIn)
Definition: scheduler.h:111
void AddToProcessQueue(std::function< void(void)> func)
Add a callback to be executed.
Definition: scheduler.cpp:168
clock::time_point time_point
Definition: bench.h:48
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:50