Bitcoin Core  27.99.0
P2P Digital Currency
scheduler.h
Go to the documentation of this file.
1 // Copyright (c) 2015-2022 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #ifndef BITCOIN_SCHEDULER_H
6 #define BITCOIN_SCHEDULER_H
7 
8 #include <attributes.h>
9 #include <sync.h>
10 #include <threadsafety.h>
11 #include <util/task_runner.h>
12 
13 #include <chrono>
14 #include <condition_variable>
15 #include <cstddef>
16 #include <functional>
17 #include <list>
18 #include <map>
19 #include <thread>
20 #include <utility>
21 
40 {
41 public:
43  ~CScheduler();
44 
45  std::thread m_service_thread;
46 
47  typedef std::function<void()> Function;
48 
50  void schedule(Function f, std::chrono::steady_clock::time_point t) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex);
51 
53  void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
54  {
55  schedule(std::move(f), std::chrono::steady_clock::now() + delta);
56  }
57 
64  void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex);
65 
71  void MockForward(std::chrono::seconds delta_seconds) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex);
72 
77 
80  {
81  WITH_LOCK(newTaskMutex, stopRequested = true);
82  newTaskScheduled.notify_all();
83  if (m_service_thread.joinable()) m_service_thread.join();
84  }
87  {
88  WITH_LOCK(newTaskMutex, stopWhenEmpty = true);
89  newTaskScheduled.notify_all();
90  if (m_service_thread.joinable()) m_service_thread.join();
91  }
92 
97  size_t getQueueInfo(std::chrono::steady_clock::time_point& first,
98  std::chrono::steady_clock::time_point& last) const
100 
103 
104 private:
106  std::condition_variable newTaskScheduled;
107  std::multimap<std::chrono::steady_clock::time_point, Function> taskQueue GUARDED_BY(newTaskMutex);
108  int nThreadsServicingQueue GUARDED_BY(newTaskMutex){0};
109  bool stopRequested GUARDED_BY(newTaskMutex){false};
110  bool stopWhenEmpty GUARDED_BY(newTaskMutex){false};
111  bool shouldStop() const EXCLUSIVE_LOCKS_REQUIRED(newTaskMutex) { return stopRequested || (stopWhenEmpty && taskQueue.empty()); }
112 };
113 
125 {
126 private:
128 
130 
131  // We are not allowed to assume the scheduler only runs in one thread,
132  // but must ensure all callbacks happen in-order, so we end up creating
133  // our own queue here :(
134  std::list<std::function<void()>> m_callbacks_pending GUARDED_BY(m_callbacks_mutex);
135  bool m_are_callbacks_running GUARDED_BY(m_callbacks_mutex) = false;
136 
139 
140 public:
141  explicit SerialTaskRunner(CScheduler& scheduler LIFETIMEBOUND) : m_scheduler{scheduler} {}
142 
149  void insert(std::function<void()> func) override EXCLUSIVE_LOCKS_REQUIRED(!m_callbacks_mutex);
150 
156 
157  size_t size() override EXCLUSIVE_LOCKS_REQUIRED(!m_callbacks_mutex);
158 };
159 
160 #endif // BITCOIN_SCHEDULER_H
#define LIFETIMEBOUND
Definition: attributes.h:16
Simple class for background tasks that should be run periodically or once "after a while".
Definition: scheduler.h:40
void MockForward(std::chrono::seconds delta_seconds) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Mock the scheduler to fast forward in time.
Definition: scheduler.cpp:80
bool stopWhenEmpty GUARDED_BY(newTaskMutex)
Definition: scheduler.h:110
void serviceQueue() EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Services the queue 'forever'.
Definition: scheduler.cpp:23
bool stopRequested GUARDED_BY(newTaskMutex)
Definition: scheduler.h:109
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
Definition: scheduler.cpp:108
std::multimap< std::chrono::steady_clock::time_point, Function > taskQueue GUARDED_BY(newTaskMutex)
size_t getQueueInfo(std::chrono::steady_clock::time_point &first, std::chrono::steady_clock::time_point &last) const EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Returns number of tasks waiting to be serviced, and first and last task times.
Definition: scheduler.cpp:113
std::function< void()> Function
Definition: scheduler.h:47
std::thread m_service_thread
Definition: scheduler.h:45
bool AreThreadsServicingQueue() const EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Returns true if there are threads actively running in serviceQueue()
Definition: scheduler.cpp:125
bool shouldStop() const EXCLUSIVE_LOCKS_REQUIRED(newTaskMutex)
Definition: scheduler.h:111
void StopWhenDrained() EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Tell any threads running serviceQueue to stop when there is no work left to be done.
Definition: scheduler.h:86
std::condition_variable newTaskScheduled
Definition: scheduler.h:106
void stop() EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Tell any threads running serviceQueue to stop as soon as the current task is done.
Definition: scheduler.h:79
Mutex newTaskMutex
Definition: scheduler.h:105
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
Definition: scheduler.h:53
void schedule(Function f, std::chrono::steady_clock::time_point t) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call func at/after time t.
Definition: scheduler.cpp:71
Class used by CScheduler clients which may schedule multiple jobs which are required to be run serial...
Definition: scheduler.h:125
bool m_are_callbacks_running GUARDED_BY(m_callbacks_mutex)
void MaybeScheduleProcessQueue() EXCLUSIVE_LOCKS_REQUIRED(!m_callbacks_mutex)
Definition: scheduler.cpp:132
void ProcessQueue() EXCLUSIVE_LOCKS_REQUIRED(!m_callbacks_mutex)
Definition: scheduler.cpp:145
size_t size() override EXCLUSIVE_LOCKS_REQUIRED(!m_callbacks_mutex)
Returns the number of currently pending events.
Definition: scheduler.cpp:196
void insert(std::function< void()> func) override EXCLUSIVE_LOCKS_REQUIRED(!m_callbacks_mutex)
Add a callback to be executed.
Definition: scheduler.cpp:176
std::list< std::function< void()> > m_callbacks_pending GUARDED_BY(m_callbacks_mutex)
Mutex m_callbacks_mutex
Definition: scheduler.h:129
CScheduler & m_scheduler
Definition: scheduler.h:127
void flush() override EXCLUSIVE_LOCKS_REQUIRED(!m_callbacks_mutex)
Processes all remaining queue members on the calling thread, blocking until queue is empty Must be ca...
Definition: scheduler.cpp:185
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:301
This header provides an interface and simple implementation for a task runner.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49