32 #define TEST_NAME "util/threading"
46 Barrier() : Barrier(2) {}
48 explicit Barrier(
const size_t count)
49 : threshold_(
count), count_(
count), generation_(0) {}
52 std::unique_lock<std::mutex> lock(mutex_);
53 auto current_generation = generation_;
57 condition_.notify_all();
59 condition_.wait(lock, [
this, current_generation] {
60 return current_generation != generation_;
67 std::condition_variable condition_;
68 const size_t threshold_;
79 class TestThread :
public Thread {
91 BOOST_CHECK(!thread.IsStarted());
92 BOOST_CHECK(!thread.IsStopped());
93 BOOST_CHECK(!thread.IsPaused());
94 BOOST_CHECK(!thread.IsRunning());
95 BOOST_CHECK(!thread.IsFinished());
99 thread.startBarrier.Wait();
100 BOOST_CHECK(thread.IsStarted());
101 BOOST_CHECK(!thread.IsStopped());
102 BOOST_CHECK(!thread.IsPaused());
103 BOOST_CHECK(thread.IsRunning());
104 BOOST_CHECK(!thread.IsFinished());
106 thread.endBarrier.Wait();
108 BOOST_CHECK(thread.IsStarted());
109 BOOST_CHECK(!thread.IsStopped());
110 BOOST_CHECK(!thread.IsPaused());
111 BOOST_CHECK(!thread.IsRunning());
112 BOOST_CHECK(thread.IsFinished());
116 class TestThread :
public Thread {
118 Barrier startBarrier;
119 Barrier pauseBarrier;
120 Barrier pausedBarrier;
121 Barrier resumedBarrier;
127 pausedBarrier.Wait();
129 resumedBarrier.Wait();
135 BOOST_CHECK(!thread.IsStarted());
136 BOOST_CHECK(!thread.IsStopped());
137 BOOST_CHECK(!thread.IsPaused());
138 BOOST_CHECK(!thread.IsRunning());
139 BOOST_CHECK(!thread.IsFinished());
143 thread.startBarrier.Wait();
144 BOOST_CHECK(thread.IsStarted());
145 BOOST_CHECK(!thread.IsStopped());
146 BOOST_CHECK(!thread.IsPaused());
147 BOOST_CHECK(thread.IsRunning());
148 BOOST_CHECK(!thread.IsFinished());
150 thread.pauseBarrier.Wait();
152 thread.pausedBarrier.Wait();
153 while (!thread.IsPaused() || thread.IsRunning()) {
154 std::this_thread::sleep_for(std::chrono::milliseconds(10));
156 BOOST_CHECK(thread.IsStarted());
157 BOOST_CHECK(!thread.IsStopped());
158 BOOST_CHECK(thread.IsPaused());
159 BOOST_CHECK(!thread.IsRunning());
160 BOOST_CHECK(!thread.IsFinished());
163 thread.resumedBarrier.Wait();
164 BOOST_CHECK(thread.IsStarted());
165 BOOST_CHECK(!thread.IsStopped());
166 BOOST_CHECK(!thread.IsPaused());
167 BOOST_CHECK(thread.IsRunning());
168 BOOST_CHECK(!thread.IsFinished());
170 thread.endBarrier.Wait();
172 BOOST_CHECK(thread.IsStarted());
173 BOOST_CHECK(!thread.IsStopped());
174 BOOST_CHECK(!thread.IsPaused());
175 BOOST_CHECK(!thread.IsRunning());
176 BOOST_CHECK(thread.IsFinished());
180 class TestThread :
public Thread {
182 Barrier startBarrier;
183 Barrier pauseBarrier;
184 Barrier pausedBarrier;
185 Barrier resumedBarrier;
187 Barrier stoppingBarrier;
188 Barrier stoppedBarrier;
194 pausedBarrier.Wait();
196 resumedBarrier.Wait();
198 stoppingBarrier.Wait();
201 stoppedBarrier.Wait();
209 BOOST_CHECK(!thread.IsStarted());
210 BOOST_CHECK(!thread.IsStopped());
211 BOOST_CHECK(!thread.IsPaused());
212 BOOST_CHECK(!thread.IsRunning());
213 BOOST_CHECK(!thread.IsFinished());
217 thread.startBarrier.Wait();
218 BOOST_CHECK(thread.IsStarted());
219 BOOST_CHECK(!thread.IsStopped());
220 BOOST_CHECK(!thread.IsPaused());
221 BOOST_CHECK(thread.IsRunning());
222 BOOST_CHECK(!thread.IsFinished());
224 thread.pauseBarrier.Wait();
226 thread.pausedBarrier.Wait();
227 while (!thread.IsPaused() || thread.IsRunning()) {
228 std::this_thread::sleep_for(std::chrono::milliseconds(10));
230 BOOST_CHECK(thread.IsStarted());
231 BOOST_CHECK(!thread.IsStopped());
232 BOOST_CHECK(thread.IsPaused());
233 BOOST_CHECK(!thread.IsRunning());
234 BOOST_CHECK(!thread.IsFinished());
237 thread.resumedBarrier.Wait();
238 BOOST_CHECK(thread.IsStarted());
239 BOOST_CHECK(!thread.IsStopped());
240 BOOST_CHECK(!thread.IsPaused());
241 BOOST_CHECK(thread.IsRunning());
242 BOOST_CHECK(!thread.IsFinished());
244 thread.stopBarrier.Wait();
246 thread.stoppingBarrier.Wait();
247 thread.stoppedBarrier.Wait();
248 BOOST_CHECK(thread.IsStarted());
249 BOOST_CHECK(thread.IsStopped());
250 BOOST_CHECK(!thread.IsPaused());
251 BOOST_CHECK(thread.IsRunning());
252 BOOST_CHECK(!thread.IsFinished());
254 thread.endBarrier.Wait();
256 BOOST_CHECK(thread.IsStarted());
257 BOOST_CHECK(thread.IsStopped());
258 BOOST_CHECK(!thread.IsPaused());
259 BOOST_CHECK(!thread.IsRunning());
260 BOOST_CHECK(thread.IsFinished());
264 class TestThread :
public Thread {
266 Barrier startBarrier;
276 BOOST_CHECK(!thread.IsStarted());
277 BOOST_CHECK(!thread.IsStopped());
278 BOOST_CHECK(!thread.IsPaused());
279 BOOST_CHECK(!thread.IsRunning());
280 BOOST_CHECK(!thread.IsFinished());
282 for (
size_t i = 0; i < 2; ++i) {
285 thread.startBarrier.Wait();
286 BOOST_CHECK(thread.IsStarted());
287 BOOST_CHECK(!thread.IsStopped());
288 BOOST_CHECK(!thread.IsPaused());
289 BOOST_CHECK(thread.IsRunning());
290 BOOST_CHECK(!thread.IsFinished());
292 thread.endBarrier.Wait();
294 BOOST_CHECK(thread.IsStarted());
295 BOOST_CHECK(!thread.IsStopped());
296 BOOST_CHECK(!thread.IsPaused());
297 BOOST_CHECK(!thread.IsRunning());
298 BOOST_CHECK(thread.IsFinished());
303 class TestThread :
public Thread {
305 Barrier startBarrier;
306 Barrier signalBarrier;
312 signalBarrier.Wait();
318 BOOST_CHECK(!thread.IsStarted());
319 BOOST_CHECK(!thread.IsStopped());
320 BOOST_CHECK(!thread.IsPaused());
321 BOOST_CHECK(!thread.IsRunning());
322 BOOST_CHECK(!thread.IsFinished());
326 thread.startBarrier.Wait();
327 BOOST_CHECK(thread.IsStarted());
328 BOOST_CHECK(!thread.IsStopped());
329 BOOST_CHECK(!thread.IsPaused());
330 BOOST_CHECK(thread.IsRunning());
331 BOOST_CHECK(!thread.IsFinished());
333 thread.signalBarrier.Wait();
334 BOOST_CHECK(thread.CheckValidSetup());
336 thread.endBarrier.Wait();
338 BOOST_CHECK(thread.IsStarted());
339 BOOST_CHECK(!thread.IsStopped());
340 BOOST_CHECK(!thread.IsPaused());
341 BOOST_CHECK(!thread.IsRunning());
342 BOOST_CHECK(thread.IsFinished());
346 class TestThread :
public Thread {
348 Barrier startBarrier;
349 Barrier signalBarrier;
354 SignalInvalidSetup();
355 signalBarrier.Wait();
361 BOOST_CHECK(!thread.IsStarted());
362 BOOST_CHECK(!thread.IsStopped());
363 BOOST_CHECK(!thread.IsPaused());
364 BOOST_CHECK(!thread.IsRunning());
365 BOOST_CHECK(!thread.IsFinished());
369 thread.startBarrier.Wait();
370 BOOST_CHECK(thread.IsStarted());
371 BOOST_CHECK(!thread.IsStopped());
372 BOOST_CHECK(!thread.IsPaused());
373 BOOST_CHECK(thread.IsRunning());
374 BOOST_CHECK(!thread.IsFinished());
376 thread.signalBarrier.Wait();
377 BOOST_CHECK(!thread.CheckValidSetup());
379 thread.endBarrier.Wait();
381 BOOST_CHECK(thread.IsStarted());
382 BOOST_CHECK(!thread.IsStopped());
383 BOOST_CHECK(!thread.IsPaused());
384 BOOST_CHECK(!thread.IsRunning());
385 BOOST_CHECK(thread.IsFinished());
389 class TestThread :
public Thread {
397 RegisterCallback(CALLBACK1);
398 RegisterCallback(CALLBACK2);
408 bool called_back1 =
false;
409 std::function<void()> CallbackFunc1 = [&called_back1]() {
413 bool called_back2 =
false;
414 std::function<void()> CallbackFunc2 = [&called_back2]() {
418 bool called_back3 =
false;
419 std::function<void()> CallbackFunc3 = [&called_back3]() {
424 thread.AddCallback(TestThread::CALLBACK1, CallbackFunc1);
427 BOOST_CHECK(called_back1);
428 BOOST_CHECK(!called_back2);
429 BOOST_CHECK(!called_back3);
431 called_back1 =
false;
432 called_back2 =
false;
433 thread.AddCallback(TestThread::CALLBACK2, CallbackFunc2);
436 BOOST_CHECK(called_back1);
437 BOOST_CHECK(called_back2);
438 BOOST_CHECK(!called_back3);
440 called_back1 =
false;
441 called_back2 =
false;
442 called_back3 =
false;
443 thread.AddCallback(TestThread::CALLBACK1, CallbackFunc3);
446 BOOST_CHECK(called_back1);
447 BOOST_CHECK(called_back2);
448 BOOST_CHECK(called_back3);
452 class TestThread :
public Thread {
454 Barrier startBarrier;
455 Barrier signalBarrier;
464 bool called_back1 =
false;
465 std::function<void()> CallbackFunc1 = [&called_back1]() {
469 bool called_back2 =
false;
470 std::function<void()> CallbackFunc2 = [&called_back2]() {
475 thread.AddCallback(TestThread::STARTED_CALLBACK, CallbackFunc1);
476 thread.AddCallback(TestThread::FINISHED_CALLBACK, CallbackFunc2);
478 thread.startBarrier.Wait();
479 BOOST_CHECK(called_back1);
480 BOOST_CHECK(!called_back2);
481 thread.endBarrier.Wait();
483 BOOST_CHECK(called_back1);
484 BOOST_CHECK(called_back2);
488 std::function<void(
void)> Func = []() {
490 for (
int i = 0; i < 100; ++i) {
496 std::vector<std::future<void>> futures;
498 for (
int i = 0; i < 100; ++i) {
499 futures.push_back(pool.
AddTask(Func));
502 for (
auto& future : futures) {
508 std::function<void(
int)> Func = [](
int num) {
509 for (
int i = 0; i < 100; ++i) {
515 std::vector<std::future<void>> futures;
517 for (
int i = 0; i < 100; ++i) {
518 futures.push_back(pool.
AddTask(Func, i));
521 for (
auto& future : futures) {
527 std::function<int(
void)> Func = []() {
return 0; };
530 std::vector<std::future<int>> futures;
532 for (
int i = 0; i < 100; ++i) {
533 futures.push_back(pool.
AddTask(Func));
536 for (
auto& future : futures) {
542 std::function<int(
int)> Func = [](
int num) {
543 for (
int i = 0; i < 100; ++i) {
550 std::vector<std::future<int>> futures;
552 for (
int i = 0; i < 100; ++i) {
553 futures.push_back(pool.
AddTask(Func, i));
556 for (
auto& future : futures) {
562 std::function<int(
int)> Func = [](
int num) {
563 for (
int i = 0; i < 100; ++i) {
570 std::vector<std::future<int>> futures;
572 for (
int i = 0; i < 100; ++i) {
573 futures.push_back(pool.
AddTask(Func, i));
578 BOOST_CHECK_THROW(pool.
AddTask(Func, 100), std::runtime_error);
584 std::vector<uint8_t> results(100, 0);
585 std::function<void(
int)> Func = [&results](
const int num) {
592 for (
size_t i = 0; i < results.size(); ++i) {
598 for (
const auto result : results) {
599 BOOST_CHECK_EQUAL(
result, 1);
604 std::vector<uint8_t> results(4, 0);
605 std::function<void(
int)> Func = [&results](
const int num) {
611 for (
size_t i = 0; i < results.size(); ++i) {
615 for (
size_t j = 0; j < results.size(); ++j) {
617 BOOST_CHECK_EQUAL(results[j], 1);
619 BOOST_CHECK_EQUAL(results[j], 0);
630 std::vector<int> results(100, -1);
631 std::function<void(
int)> Func = [&](
const int num) {
635 for (
size_t i = 0; i < results.size(); ++i) {
641 for (
const auto result : results) {
642 BOOST_CHECK_GE(
result, 0);
643 BOOST_CHECK_LE(
result, 3);
653 std::thread producer_thread([&job_queue]() {
654 for (
int i = 0; i < 10; ++i) {
655 CHECK(job_queue.
Push(i));
659 std::thread consumer_thread([&job_queue]() {
660 CHECK_LE(job_queue.
Size(), 10);
661 for (
int i = 0; i < 10; ++i) {
662 const auto job = job_queue.
Pop();
663 CHECK(job.IsValid());
664 CHECK_LT(job.Data(), 10);
668 producer_thread.join();
669 consumer_thread.join();
678 std::thread producer_thread([&job_queue]() {
679 for (
int i = 0; i < 10; ++i) {
680 CHECK(job_queue.
Push(i));
684 std::thread consumer_thread([&job_queue]() {
685 CHECK_LE(job_queue.
Size(), 2);
686 for (
int i = 0; i < 10; ++i) {
687 const auto job = job_queue.
Pop();
688 CHECK(job.IsValid());
689 CHECK_LT(job.Data(), 10);
693 producer_thread.join();
694 consumer_thread.join();
703 std::thread producer_thread1([&job_queue]() {
704 for (
int i = 0; i < 10; ++i) {
705 CHECK(job_queue.
Push(i));
709 std::thread producer_thread2([&job_queue]() {
710 for (
int i = 0; i < 10; ++i) {
711 CHECK(job_queue.
Push(i));
715 std::thread consumer_thread([&job_queue]() {
716 CHECK_LE(job_queue.
Size(), 1);
717 for (
int i = 0; i < 20; ++i) {
718 const auto job = job_queue.
Pop();
719 CHECK(job.IsValid());
720 CHECK_LT(job.Data(), 10);
724 producer_thread1.join();
725 producer_thread2.join();
726 consumer_thread.join();
735 std::thread producer_thread([&job_queue]() {
736 for (
int i = 0; i < 20; ++i) {
737 CHECK(job_queue.
Push(i));
741 std::thread consumer_thread1([&job_queue]() {
742 CHECK_LE(job_queue.
Size(), 1);
743 for (
int i = 0; i < 10; ++i) {
744 const auto job = job_queue.
Pop();
745 CHECK(job.IsValid());
746 CHECK_LT(job.Data(), 20);
750 std::thread consumer_thread2([&job_queue]() {
751 CHECK_LE(job_queue.
Size(), 1);
752 for (
int i = 0; i < 10; ++i) {
753 const auto job = job_queue.
Pop();
754 CHECK(job.IsValid());
755 CHECK_LT(job.Data(), 20);
759 producer_thread.join();
760 consumer_thread1.join();
761 consumer_thread2.join();
770 std::thread producer_thread1([&job_queue]() {
771 for (
int i = 0; i < 10; ++i) {
772 CHECK(job_queue.
Push(i));
776 std::thread producer_thread2([&job_queue]() {
777 for (
int i = 0; i < 10; ++i) {
778 CHECK(job_queue.
Push(i));
782 std::thread consumer_thread1([&job_queue]() {
783 CHECK_LE(job_queue.
Size(), 1);
784 for (
int i = 0; i < 10; ++i) {
785 const auto job = job_queue.
Pop();
786 CHECK(job.IsValid());
787 CHECK_LT(job.Data(), 10);
791 std::thread consumer_thread2([&job_queue]() {
792 CHECK_LE(job_queue.
Size(), 1);
793 for (
int i = 0; i < 10; ++i) {
794 const auto job = job_queue.
Pop();
795 CHECK(job.IsValid());
796 CHECK_LT(job.Data(), 10);
800 producer_thread1.join();
801 producer_thread2.join();
802 consumer_thread1.join();
803 consumer_thread2.join();
812 for (
int i = 0; i < 10; ++i) {
813 CHECK(job_queue.
Push(i));
816 std::thread consumer_thread([&job_queue]() {
817 CHECK_EQ(job_queue.
Size(), 10);
818 for (
int i = 0; i < 10; ++i) {
819 const auto job = job_queue.
Pop();
820 CHECK(job.IsValid());
821 CHECK_EQ(job.Data(), i);
827 BOOST_CHECK_EQUAL(job_queue.
Size(), 0);
828 BOOST_CHECK(job_queue.
Push(0));
831 consumer_thread.join();
841 std::thread producer_thread([&job_queue, &stopBarrier]() {
842 CHECK(job_queue.
Push(0));
844 CHECK(!job_queue.
Push(0));
848 BOOST_CHECK_EQUAL(job_queue.
Size(), 1);
851 producer_thread.join();
853 BOOST_CHECK(!job_queue.
Push(0));
863 BOOST_CHECK(job_queue.
Push(0));
866 std::thread consumer_thread([&job_queue, &popBarrier]() {
867 const auto job = job_queue.
Pop();
868 CHECK(job.IsValid());
869 CHECK_EQ(job.Data(), 0);
875 BOOST_CHECK_EQUAL(job_queue.
Size(), 0);
878 consumer_thread.join();
880 BOOST_CHECK(!job_queue.
Push(0));
887 BOOST_CHECK(job_queue.
Push(0));
888 BOOST_CHECK_EQUAL(job_queue.
Size(), 1);
891 BOOST_CHECK_EQUAL(job_queue.
Size(), 0);
int Run(int argc, const char *argv[])
auto AddTask(func_t &&f, args_t &&... args) -> std::future< typename std::result_of< func_t(args_t...)>::type >
int GetEffectiveNumThreads(const int num_threads)
BOOST_AUTO_TEST_CASE(TestThreadWait)