66#define BITCOIN_CHECKQUEUE_H
77
88#include < sync.h>
9+ #include < tinyformat.h>
10+ #include < util/threadnames.h>
911
1012#include < algorithm>
1113#include < vector>
@@ -62,8 +64,11 @@ class CCheckQueue
6264 // ! The maximum number of elements to be processed in one batch
6365 const unsigned int nBatchSize;
6466
67+ std::vector<std::thread> m_worker_threads;
68+ bool m_request_stop{false };
69+
6570 /* * Internal function that does bulk of the verification work. */
66- bool Loop (bool fMaster = false )
71+ bool Loop (bool fMaster )
6772 {
6873 boost::condition_variable& cond = fMaster ? condMaster : condWorker;
6974 std::vector<T> vChecks;
@@ -85,7 +90,7 @@ class CCheckQueue
8590 nTotal++;
8691 }
8792 // logically, the do loop starts here
88- while (queue.empty ()) {
93+ while (queue.empty () && !m_request_stop ) {
8994 if (fMaster && nTodo == 0 ) {
9095 nTotal--;
9196 bool fRet = fAllOk ;
@@ -98,6 +103,10 @@ class CCheckQueue
98103 cond.wait (lock); // wait
99104 nIdle--;
100105 }
106+ if (m_request_stop) {
107+ return false ;
108+ }
109+
101110 // Decide how many work units to process now.
102111 // * Do not try to do everything at once, but aim for increasingly smaller batches so
103112 // all workers finish approximately simultaneously.
@@ -132,16 +141,34 @@ class CCheckQueue
132141 {
133142 }
134143
144+ // ! Create a pool of new worker threads.
145+ void StartWorkerThreads (const int threads_num)
146+ {
147+ {
148+ boost::unique_lock<boost::mutex> lock (mutex);
149+ nIdle = 0 ;
150+ nTotal = 0 ;
151+ fAllOk = true ;
152+ }
153+ assert (m_worker_threads.empty ());
154+ for (int n = 0 ; n < threads_num; ++n) {
155+ m_worker_threads.emplace_back ([this , n]() {
156+ util::ThreadRename (strprintf (" scriptch.%i" , n));
157+ Loop (false /* worker thread */ );
158+ });
159+ }
160+ }
161+
135162 // ! Worker thread
136163 void Thread ()
137164 {
138- Loop ();
165+ Loop (false /* worker thread */ );
139166 }
140167
141168 // ! Wait until execution finishes, and return whether all evaluations were successful.
142169 bool Wait ()
143170 {
144- return Loop (true );
171+ return Loop (true /* master thread */ );
145172 }
146173
147174 // ! Add a batch of checks to the queue
@@ -159,8 +186,25 @@ class CCheckQueue
159186 condWorker.notify_all ();
160187 }
161188
189+ // ! Stop all of the worker threads.
190+ void StopWorkerThreads ()
191+ {
192+ {
193+ boost::unique_lock<boost::mutex> lock (mutex);
194+ m_request_stop = true ;
195+ }
196+ condWorker.notify_all ();
197+ for (std::thread& t : m_worker_threads) {
198+ t.join ();
199+ }
200+ m_worker_threads.clear ();
201+ boost::unique_lock<boost::mutex> lock (mutex);
202+ m_request_stop = false ;
203+ }
204+
162205 ~CCheckQueue ()
163206 {
207+ assert (m_worker_threads.empty ());
164208 }
165209
166210};
0 commit comments