Bitcoin Core 28.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{
41public:
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
104private:
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{
126private:
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
140public:
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
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
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
std::multimap< std::chrono::steady_clock::time_point, Function > taskQueue GUARDED_BY(newTaskMutex)
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