PRCYCoin  2.0.0.7rc1
P2P Digital Currency
scheduler.cpp
Go to the documentation of this file.
1 // Copyright (c) 2015 The Bitcoin Core developers
2 // Copyright (c) 2015-2018 The PIVX developers
3 // Copyright (c) 2018-2020 The DAPS Project developers
4 // Distributed under the MIT software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include "scheduler.h"
8 #include "random.h"
9 #include "reverselock.h"
10 #include <assert.h>
11 #include <boost/bind.hpp>
12 #include <utility>
13 
14 CScheduler::CScheduler() : nThreadsServicingQueue(0), stopRequested(false), stopWhenEmpty(false) {
15 }
16 
18  assert(nThreadsServicingQueue == 0);
19 }
20 
22  boost::unique_lock <boost::mutex> lock(newTaskMutex);
24  // newTaskMutex is locked throughout this loop EXCEPT
25  // when the thread is waiting or when the user's function
26  // is called.
27  while (!shouldStop()) {
28  try {
29  if (!shouldStop() && taskQueue.empty()) {
31  // Use this chance to get a tiny bit more entropy
33  }
34  while (!shouldStop() && taskQueue.empty()) {
35  // Wait until there is something to do.
36  newTaskScheduled.wait(lock);
37  }
38  // Wait until either there is a new task, or until
39  // the time of the first item on the queue:
40  // Some boost versions have a conflicting overload of wait_until that returns void.
41  // Explicitly use a template here to avoid hitting that overload.
42  while (!shouldStop() && !taskQueue.empty() &&
43  newTaskScheduled.wait_until<>(lock, taskQueue.begin()->first) != boost::cv_status::timeout) {
44  // Keep waiting until timeout
45  }
46  // If there are multiple threads, the queue can empty while we're waiting (another
47  // thread may service the task we were waiting on).
48  if (shouldStop() || taskQueue.empty())
49  continue;
50  Function f = taskQueue.begin()->second;
51  taskQueue.erase(taskQueue.begin());
52  {
53  // Unlock before calling f, so it can reschedule itself or another task
54  // without deadlocking:
56  f();
57  }
58  } catch (...) {
60  throw;
61  }
62  }
64  newTaskScheduled.notify_one();
65 }
66 
67 void CScheduler::stop(bool drain) {
68  {
69  boost::unique_lock <boost::mutex> lock(newTaskMutex);
70  if (drain)
71  stopWhenEmpty = true;
72  else
73  stopRequested = true;
74  }
75  newTaskScheduled.notify_all();
76 }
77 
78 void CScheduler::schedule(CScheduler::Function f, boost::chrono::system_clock::time_point t) {
79  {
80  boost::unique_lock <boost::mutex> lock(newTaskMutex);
81  taskQueue.insert(std::make_pair(t, f));
82  }
83  newTaskScheduled.notify_one();
84 }
85 
86 void CScheduler::scheduleFromNow(CScheduler::Function f, int64_t deltaSeconds) {
87  schedule(f, boost::chrono::system_clock::now() + boost::chrono::seconds(deltaSeconds));
88 }
89 
90 static void Repeat(CScheduler *s, CScheduler::Function f, int64_t deltaSeconds) {
91  f();
92  s->scheduleFromNow(boost::bind(&Repeat, s, f, deltaSeconds), deltaSeconds);
93 }
94 
95 void CScheduler::scheduleEvery(CScheduler::Function f, int64_t deltaSeconds) {
96  scheduleFromNow(boost::bind(&Repeat, this, f, deltaSeconds), deltaSeconds);
97 }
98 
99 size_t CScheduler::getQueueInfo(boost::chrono::system_clock::time_point &first,
100  boost::chrono::system_clock::time_point &last) const {
101  boost::unique_lock <boost::mutex> lock(newTaskMutex);
102  size_t result = taskQueue.size();
103  if (!taskQueue.empty()) {
104  first = taskQueue.begin()->first;
105  last = taskQueue.rbegin()->first;
106  }
107  return result;
108 }
CScheduler
Definition: scheduler.h:37
CScheduler::shouldStop
bool shouldStop()
Definition: scheduler.h:81
CScheduler::CScheduler
CScheduler()
Definition: scheduler.cpp:14
CScheduler::scheduleFromNow
void scheduleFromNow(Function f, int64_t deltaSeconds)
Definition: scheduler.cpp:86
CScheduler::stopRequested
bool stopRequested
Definition: scheduler.h:78
CScheduler::~CScheduler
~CScheduler()
Definition: scheduler.cpp:17
scheduler.h
CScheduler::newTaskScheduled
boost::condition_variable newTaskScheduled
Definition: scheduler.h:75
CScheduler::getQueueInfo
size_t getQueueInfo(boost::chrono::system_clock::time_point &first, boost::chrono::system_clock::time_point &last) const
Definition: scheduler.cpp:99
CScheduler::serviceQueue
void serviceQueue()
Definition: scheduler.cpp:21
random.h
CScheduler::nThreadsServicingQueue
int nThreadsServicingQueue
Definition: scheduler.h:77
CScheduler::taskQueue
std::multimap< boost::chrono::system_clock::time_point, Function > taskQueue
Definition: scheduler.h:74
CScheduler::stopWhenEmpty
bool stopWhenEmpty
Definition: scheduler.h:79
reverse_lock
An RAII-style reverse lock.
Definition: reverselock.h:13
CScheduler::newTaskMutex
boost::mutex newTaskMutex
Definition: scheduler.h:76
CScheduler::Function
boost::function< void(void)> Function
Definition: scheduler.h:43
CScheduler::schedule
void schedule(Function f, boost::chrono::system_clock::time_point t)
Definition: scheduler.cpp:78
CScheduler::scheduleEvery
void scheduleEvery(Function f, int64_t deltaSeconds)
Definition: scheduler.cpp:95
CScheduler::stop
void stop(bool drain=false)
Definition: scheduler.cpp:67
RandAddSeedSleep
void RandAddSeedSleep()
Add a little bit of randomness to the output of GetStrongRangBytes.
Definition: random.cpp:282
reverselock.h