1#ifdef _WIN32
2 #include <windows.h>
3#else
4 #include <sys/time.h>
5#endif
6
7#include "boost/bind/bind.hpp"
8#include "boost/chrono.hpp"
9#include "boost/chrono/ceil.hpp"
10#include "boost/date_time.hpp"
11#include "boost/thread/concurrent_queues/sync_priority_queue.hpp"
12#include "boost/thread/concurrent_queues/sync_timed_queue.hpp"
13#include "boost/thread/future.hpp"
14#include "boost/thread/mutex.hpp"
15#include "boost/thread/recursive_mutex.hpp"
16#include "boost/thread/shared_lock_guard.hpp"
17#include "boost/thread/shared_mutex.hpp"
18#include "boost/thread/thread.hpp"
19
20#include <iomanip>
21#ifdef TEST_CPP14_FEATURES
22#include <future>
23#include <mutex>
24#include <shared_mutex>
25#include <thread>
26#endif
27
28/******************************************************************************/
29
30/*
31 * Summary:
32 *
33 * This code tests the behavior of time-related functions in the presence of
34 * system clock changes (jumps). It requires root/Administrator privileges in
35 * order to run because it changes the system clock. NTP should also be disabled
36 * while running this code so that NTP can't change the system clock.
37 *
38 * Each function to be tested is executed five times. The amount of time the
39 * function waits before returning is measured against the amount of time the
40 * function was expected to wait. If the difference exceeds a threshold value
41 * (defined below) then the test fails.
42 *
43 * The following values are intentially:
44 * - more than 200 milliseconds
45 * - more than 200 milliseconds apart
46 * - not a multiple of 100 milliseconds
47 * - not a multiple of each other
48 * - don't sum or diff to a multiple of 100 milliseconds
49 */
50const long long s_waitMs = 580;
51const long long s_shortJumpMs = 230;
52const long long s_longJumpMs = 870; // Causes additional, unavoidable failures when BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC is disabled
53const long long s_sleepBeforeJumpMs = 110;
54
55#ifdef _WIN32
56const long long s_maxEarlyErrorMs = 10
57 + 100; // Windows is unpredictable, especially in a VM, so allow extra time if the function returns early
58const long long s_maxLateErrorMs = 110 // due to polling, functions may not return for up to 100 milliseconds after they are supposed to
59 + 100; // Windows is slow, especially in a VM, so allow extra time for the functions to return
60#else
61const long long s_maxEarlyErrorMs = 10;
62const long long s_maxLateErrorMs = 110; // Due to polling, functions may not return for up to 100 milliseconds after they are supposed to
63#endif
64
65int g_numTestsRun = 0;
66int g_numTestsPassed = 0;
67int g_numTestsFailed = 0;
68
69/******************************************************************************/
70
71// A custom clock based off the system clock but with a different epoch.
72
73namespace custom
74{
75 class custom_boost_clock
76 {
77 public:
78 typedef boost::chrono::microseconds duration; // intentionally not nanoseconds
79 typedef duration::rep rep;
80 typedef duration::period period;
81 typedef boost::chrono::time_point<custom_boost_clock> time_point;
82 static bool is_steady;
83
84 static time_point now();
85 };
86
87 bool custom_boost_clock::is_steady = false;
88
89 custom_boost_clock::time_point custom_boost_clock::now()
90 {
91 return time_point(boost::chrono::ceil<duration>(d: boost::chrono::system_clock::now().time_since_epoch()) - boost::chrono::hours(10 * 365 * 24));
92 }
93
94#ifdef TEST_CPP14_FEATURES
95 class custom_std_clock
96 {
97 public:
98 typedef std::chrono::microseconds duration; // intentionally not nanoseconds
99 typedef duration::rep rep;
100 typedef duration::period period;
101 typedef std::chrono::time_point<custom_std_clock> time_point;
102 static bool is_steady;
103
104 static time_point now();
105 };
106
107 bool custom_std_clock::is_steady = false;
108
109 custom_std_clock::time_point custom_std_clock::now()
110 {
111 return time_point(std::chrono::duration_cast<duration>(std::chrono::system_clock::now().time_since_epoch()) - std::chrono::hours(10 * 365 * 24));
112 }
113#endif
114}
115
116/******************************************************************************/
117
118template <typename MutexType = boost::mutex, typename CondType = boost::condition_variable>
119struct BoostHelper
120{
121 typedef MutexType mutex;
122 typedef CondType cond;
123
124 typedef boost::lock_guard<MutexType> lock_guard;
125 typedef boost::unique_lock<MutexType> unique_lock;
126
127 typedef boost::chrono::milliseconds milliseconds;
128 typedef boost::chrono::nanoseconds nanoseconds;
129
130 typedef boost::chrono::system_clock system_clock;
131 typedef boost::chrono::steady_clock steady_clock;
132 typedef custom::custom_boost_clock custom_clock;
133
134 typedef system_clock::time_point system_time_point;
135 typedef steady_clock::time_point steady_time_point;
136 typedef custom_clock::time_point custom_time_point;
137
138 typedef boost::cv_status cv_status;
139 typedef boost::future_status future_status;
140
141 typedef boost::packaged_task<bool> packaged_task;
142 typedef boost::future<bool> future;
143 typedef boost::shared_future<bool> shared_future;
144
145 typedef boost::thread thread;
146
147 static const milliseconds waitDur;
148
149 template <typename T>
150 static void sleep_for(T d)
151 {
152 boost::this_thread::sleep_for(d);
153 }
154
155 template <typename T>
156 static void sleep_for_no_int(T d)
157 {
158 boost::this_thread::no_interruption_point::sleep_for(d);
159 }
160
161 template <typename T>
162 static void sleep_until(T t)
163 {
164 boost::this_thread::sleep_until(t);
165 }
166
167 template <typename T>
168 static void sleep_until_no_int(T t)
169 {
170 boost::this_thread::no_interruption_point::sleep_until(t);
171 }
172
173 static system_time_point systemNow()
174 {
175 return system_clock::now();
176 }
177
178 static steady_time_point steadyNow()
179 {
180 return steady_clock::now();
181 }
182
183 static custom_time_point customNow()
184 {
185 return custom_clock::now();
186 }
187
188 template <class ToDuration, class Rep, class Period>
189 static ToDuration duration_cast(const boost::chrono::duration<Rep, Period>& d)
190 {
191 return boost::chrono::duration_cast<ToDuration>(d);
192 }
193
194 static milliseconds zero()
195 {
196 return milliseconds(0);
197 }
198};
199
200template <typename MutexType, typename CondType>
201const typename BoostHelper<MutexType, CondType>::milliseconds
202BoostHelper<MutexType, CondType>::waitDur = typename BoostHelper<MutexType, CondType>::milliseconds(s_waitMs);
203
204#ifdef TEST_CPP14_FEATURES
205template <typename MutexType = std::mutex, typename CondType = std::condition_variable>
206struct StdHelper
207{
208 typedef MutexType mutex;
209 typedef CondType cond;
210
211 typedef std::lock_guard<MutexType> lock_guard;
212 typedef std::unique_lock<MutexType> unique_lock;
213
214 typedef std::chrono::milliseconds milliseconds;
215 typedef std::chrono::nanoseconds nanoseconds;
216
217 typedef std::chrono::system_clock system_clock;
218 typedef std::chrono::steady_clock steady_clock;
219 typedef custom::custom_std_clock custom_clock;
220
221 typedef system_clock::time_point system_time_point;
222 typedef steady_clock::time_point steady_time_point;
223 typedef custom_clock::time_point custom_time_point;
224
225 typedef std::cv_status cv_status;
226 typedef std::future_status future_status;
227
228 typedef std::packaged_task<bool()> packaged_task;
229 typedef std::future<bool> future;
230 typedef std::shared_future<bool> shared_future;
231
232 typedef std::thread thread;
233
234 static const milliseconds waitDur;
235
236 template <typename T>
237 static void sleep_for(T d)
238 {
239 std::this_thread::sleep_for(d);
240 }
241
242 template <typename T>
243 static void sleep_until(T t)
244 {
245 std::this_thread::sleep_until(t);
246 }
247
248 static system_time_point systemNow()
249 {
250 return system_clock::now();
251 }
252
253 static steady_time_point steadyNow()
254 {
255 return steady_clock::now();
256 }
257
258 static custom_time_point customNow()
259 {
260 return custom_clock::now();
261 }
262
263 template <class ToDuration, class Rep, class Period>
264 static ToDuration duration_cast(const std::chrono::duration<Rep, Period>& d)
265 {
266 return std::chrono::duration_cast<ToDuration>(d);
267 }
268
269 static milliseconds zero()
270 {
271 return milliseconds(0);
272 }
273};
274
275template <typename MutexType, typename CondType>
276const typename StdHelper<MutexType, CondType>::milliseconds
277StdHelper<MutexType, CondType>::waitDur = typename StdHelper<MutexType, CondType>::milliseconds(s_waitMs);
278#endif
279
280/******************************************************************************/
281
282#ifdef _WIN32
283
284void changeSystemTime(long long changeMs)
285{
286 Sleep(s_sleepBeforeJumpMs);
287
288 SYSTEMTIME systemTime;
289 GetSystemTime(&systemTime);
290
291 FILETIME fileTime;
292 if (!SystemTimeToFileTime(&systemTime, &fileTime))
293 {
294 std::cout << "ERROR: Couldn't convert system time to file time" << std::endl;
295 }
296
297 ULARGE_INTEGER largeInt;
298 largeInt.LowPart = fileTime.dwLowDateTime;
299 largeInt.HighPart = fileTime.dwHighDateTime;
300 largeInt.QuadPart += changeMs * 10000;
301 fileTime.dwLowDateTime = largeInt.LowPart;
302 fileTime.dwHighDateTime = largeInt.HighPart;
303
304 if (!FileTimeToSystemTime(&fileTime, &systemTime))
305 {
306 std::cout << "ERROR: Couldn't convert file time to system time" << std::endl;
307 }
308
309 if (!SetSystemTime(&systemTime))
310 {
311 std::cout << "ERROR: Couldn't set system time" << std::endl;
312 }
313}
314
315#else
316
317void changeSystemTime(long long changeMs)
318{
319 struct timespec sleepTs;
320 sleepTs.tv_sec = (s_sleepBeforeJumpMs / 1000);
321 sleepTs.tv_nsec = (s_sleepBeforeJumpMs % 1000) * 1000000;
322 nanosleep(requested_time: &sleepTs, NULL);
323
324 struct timeval tv;
325 if (gettimeofday(tv: &tv, NULL) != 0)
326 {
327 std::cout << "ERROR: Couldn't get system time" << std::endl;
328 }
329
330 changeMs += tv.tv_sec * 1000;
331 changeMs += tv.tv_usec / 1000;
332 tv.tv_sec = (changeMs / 1000);
333 tv.tv_usec = (changeMs % 1000) * 1000;
334
335 if (settimeofday(tv: &tv, NULL) != 0)
336 {
337 std::cout << "ERROR: Couldn't set system time" << std::endl;
338 }
339}
340
341#endif
342
343enum RcEnum
344{
345 e_no_timeout,
346 e_timeout,
347 e_failed_bad,
348 e_failed_good,
349 e_succeeded_bad,
350 e_succeeded_good,
351 e_ready_bad,
352 e_not_ready_good,
353 e_na
354};
355
356template <typename Helper>
357void checkWaitTime(typename Helper::nanoseconds expected, typename Helper::nanoseconds actual, RcEnum rc)
358{
359 if (expected != Helper::zero() && expected < typename Helper::milliseconds(s_sleepBeforeJumpMs))
360 {
361 expected = typename Helper::milliseconds(s_sleepBeforeJumpMs);
362 }
363
364 typename Helper::milliseconds expectedMs = Helper::template duration_cast<typename Helper::milliseconds>(expected);
365 typename Helper::milliseconds actualMs = Helper::template duration_cast<typename Helper::milliseconds>(actual);
366
367 std::cout << "Expected: " << std::setw(4) << expectedMs.count() << " ms"
368 << ", Actual: " << std::setw(4) << actualMs.count() << " ms"
369 << ", Returned: ";
370 switch (rc)
371 {
372 case e_no_timeout : std::cout << "no_timeout, "; break;
373 case e_timeout : std::cout << "timeout, "; break;
374 case e_failed_bad : std::cout << "failed, "; break;
375 case e_failed_good : std::cout << "failed, "; break;
376 case e_succeeded_bad : std::cout << "succeeded, "; break;
377 case e_succeeded_good : std::cout << "succeeded, "; break;
378 case e_ready_bad : std::cout << "ready, "; break;
379 case e_not_ready_good : std::cout << "not_ready, "; break;
380 default : std::cout << "N/A, "; break;
381 }
382
383 if (expectedMs == Helper::zero())
384 {
385 std::cout << "FAILED: SKIPPED (test would lock up if run)";
386 g_numTestsFailed++;
387 }
388 else if (actual < expected - typename Helper::milliseconds(s_maxEarlyErrorMs))
389 {
390 std::cout << "FAILED: TOO SHORT";
391 if (rc == e_timeout) // bad
392 {
393 std::cout << ", RETURNED TIMEOUT";
394 }
395 else if (rc == e_failed_bad)
396 {
397 std::cout << ", RETURNED FAILED";
398 }
399 else if (rc == e_succeeded_bad)
400 {
401 std::cout << ", RETURNED SUCCEEDED";
402 }
403 else if (rc == e_ready_bad)
404 {
405 std::cout << ", RETURNED READY";
406 }
407 g_numTestsFailed++;
408 }
409 else if (actual > expected + typename Helper::milliseconds(s_maxLateErrorMs))
410 {
411 std::cout << "FAILED: TOO LONG";
412 if (rc == e_no_timeout) // bad
413 {
414 std::cout << ", RETURNED NO_TIMEOUT";
415 }
416 else if (rc == e_failed_bad)
417 {
418 std::cout << ", RETURNED FAILED";
419 }
420 else if (rc == e_succeeded_bad)
421 {
422 std::cout << ", RETURNED SUCCEEDED";
423 }
424 else if (rc == e_ready_bad)
425 {
426 std::cout << ", RETURNED READY";
427 }
428 g_numTestsFailed++;
429 }
430 else if (rc == e_no_timeout) // bad
431 {
432 std::cout << "FAILED: RETURNED NO_TIMEOUT";
433 g_numTestsFailed++;
434 }
435 else if (rc == e_failed_bad)
436 {
437 std::cout << "FAILED: RETURNED FAILED";
438 g_numTestsFailed++;
439 }
440 else if (rc == e_succeeded_bad)
441 {
442 std::cout << "FAILED: RETURNED SUCCEEDED";
443 g_numTestsFailed++;
444 }
445 else if (rc == e_ready_bad)
446 {
447 std::cout << "FAILED: RETURNED READY";
448 g_numTestsFailed++;
449 }
450 else
451 {
452 std::cout << "Passed";
453 g_numTestsPassed++;
454 }
455 std::cout << std::endl;
456
457 g_numTestsRun++;
458}
459
460void sleepForLongTime()
461{
462#ifdef _WIN32
463 Sleep(10000);
464#else
465 struct timespec ts = {.tv_sec: 5, .tv_nsec: 0};
466 nanosleep(requested_time: &ts, NULL);
467#endif
468}
469
470bool returnFalse()
471{
472 return false;
473}
474
475/******************************************************************************/
476
477// Run the test in the context provided, which may be the current thread or a separate thread.
478template <typename Helper, typename Context, typename Function>
479void runTestInContext(Context context, Function func, const std::string name)
480{
481 std::cout << name << ":" << std::endl;
482
483 {
484 std::cout << " While system clock remains stable: ";
485 context(func, 0);
486 }
487
488 {
489 std::cout << " While system clock jumps back (short): ";
490 typename Helper::thread t(boost::bind(f: changeSystemTime, a1: -s_shortJumpMs));
491 context(func, -s_shortJumpMs);
492 t.join();
493 }
494
495 {
496 std::cout << " While system clock jumps back (long): ";
497 typename Helper::thread t(boost::bind(f: changeSystemTime, a1: -s_longJumpMs));
498 context(func, -s_longJumpMs);
499 t.join();
500 }
501
502 {
503 std::cout << " While system clock jumps forward (short): ";
504 typename Helper::thread t(boost::bind(f: changeSystemTime, a1: s_shortJumpMs));
505 context(func, s_shortJumpMs);
506 t.join();
507 }
508
509 {
510 std::cout << " While system clock jumps forward (long): ";
511 typename Helper::thread t(boost::bind(f: changeSystemTime, a1: s_longJumpMs));
512 context(func, s_longJumpMs);
513 t.join();
514 }
515}
516
517//--------------------------------------
518
519template <typename Helper, typename Function>
520void noThreadContext(Function func, const long long jumpMs)
521{
522 func(jumpMs);
523}
524
525template <typename Helper, typename Function>
526void threadContextWithNone(Function func, const long long jumpMs)
527{
528 typename Helper::thread t(boost::bind(func, jumpMs));
529 t.join();
530}
531
532template <typename Helper, typename Function>
533void threadContextWithUnique(Function func, const long long jumpMs)
534{
535 typename Helper::mutex m;
536 typename Helper::lock_guard g(m);
537 typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs));
538 t.join();
539}
540
541template <typename Helper, typename Function>
542void threadContextWithShared(Function func, const long long jumpMs)
543{
544 typename Helper::mutex m;
545 boost::shared_lock_guard<typename Helper::mutex> g(m);
546 typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs));
547 t.join();
548}
549
550template <typename Helper, typename Function>
551void threadContextWithUpgrade(Function func, const long long jumpMs)
552{
553 typename Helper::mutex m;
554 boost::upgrade_lock<typename Helper::mutex> g(m);
555 typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs));
556 t.join();
557}
558
559//--------------------------------------
560
561// Run the test in the current thread.
562template <typename Helper, typename Function>
563void runTest(Function func, const std::string name)
564{
565 runTestInContext<Helper>(noThreadContext<Helper, Function>, func, name);
566}
567
568// Run the test in a separate thread.
569template <typename Helper, typename Function>
570void runTestWithNone(Function func, const std::string name)
571{
572 runTestInContext<Helper>(threadContextWithNone<Helper, Function>, func, name);
573}
574
575// Run the test in a separate thread. Pass a locked mutex to the function under test.
576template <typename Helper, typename Function>
577void runTestWithUnique(Function func, const std::string name)
578{
579 runTestInContext<Helper>(threadContextWithUnique<Helper, Function>, func, name);
580}
581
582// Run the test in a separate thread. Pass a shared-locked mutex to the function under test.
583template <typename Helper, typename Function>
584void runTestWithShared(Function func, const std::string name)
585{
586 runTestInContext<Helper>(threadContextWithShared<Helper, Function>, func, name);
587}
588
589// Run the test in a separate thread. Pass an upgrade-locked mutex to the function under test.
590template <typename Helper, typename Function>
591void runTestWithUpgrade(Function func, const std::string name)
592{
593 runTestInContext<Helper>(threadContextWithUpgrade<Helper, Function>, func, name);
594}
595
596/******************************************************************************/
597
598// Test Sleep
599
600template <typename Helper>
601void testSleepFor(const long long jumpMs)
602{
603 typename Helper::steady_time_point before(Helper::steadyNow());
604 Helper::sleep_for(Helper::waitDur);
605 typename Helper::steady_time_point after(Helper::steadyNow());
606
607 checkWaitTime<Helper>(Helper::waitDur, after - before, e_na);
608}
609
610template <typename Helper>
611void testSleepUntilSteady(const long long jumpMs)
612{
613 typename Helper::steady_time_point before(Helper::steadyNow());
614 Helper::sleep_until(Helper::steadyNow() + Helper::waitDur);
615 typename Helper::steady_time_point after(Helper::steadyNow());
616
617 checkWaitTime<Helper>(Helper::waitDur, after - before, e_na);
618}
619
620template <typename Helper>
621void testSleepUntilSystem(const long long jumpMs)
622{
623 typename Helper::steady_time_point before(Helper::steadyNow());
624 Helper::sleep_until(Helper::systemNow() + Helper::waitDur);
625 typename Helper::steady_time_point after(Helper::steadyNow());
626
627 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na);
628}
629
630template <typename Helper>
631void testSleepUntilCustom(const long long jumpMs)
632{
633 typename Helper::steady_time_point before(Helper::steadyNow());
634 Helper::sleep_until(Helper::customNow() + Helper::waitDur);
635 typename Helper::steady_time_point after(Helper::steadyNow());
636
637 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na);
638}
639
640//--------------------------------------
641
642template <typename Helper>
643void testSleepRelative(const long long jumpMs)
644{
645#ifndef SKIP_DATETIME_FUNCTIONS
646 typename Helper::steady_time_point before(Helper::steadyNow());
647 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
648 boost::this_thread::sleep(rel_time: ptDur);
649 typename Helper::steady_time_point after(Helper::steadyNow());
650
651 checkWaitTime<Helper>(Helper::waitDur, after - before, e_na);
652#else
653 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
654#endif
655}
656
657template <typename Helper>
658void testSleepAbsolute(const long long jumpMs)
659{
660#ifndef SKIP_DATETIME_FUNCTIONS
661 typename Helper::steady_time_point before(Helper::steadyNow());
662 boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
663 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
664 boost::this_thread::sleep(abs_time: ptNow + ptDur);
665 typename Helper::steady_time_point after(Helper::steadyNow());
666
667 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na);
668#else
669 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
670#endif
671}
672
673//--------------------------------------
674
675template <typename Helper>
676void testSleepStd(const std::string& name)
677{
678 std::cout << std::endl;
679 runTestWithNone<Helper>(testSleepFor <Helper>, name + "::this_thread::sleep_for()");
680 runTestWithNone<Helper>(testSleepUntilSteady<Helper>, name + "::this_thread::sleep_until(), steady time");
681 runTestWithNone<Helper>(testSleepUntilSystem<Helper>, name + "::this_thread::sleep_until(), system time");
682 runTestWithNone<Helper>(testSleepUntilCustom<Helper>, name + "::this_thread::sleep_until(), custom time");
683}
684
685template <typename Helper>
686void testSleepBoost(const std::string& name)
687{
688 testSleepStd<Helper>(name);
689
690 // Boost-only functions
691 runTestWithNone<Helper>(testSleepRelative<Helper>, name + "::this_thread::sleep(), relative time");
692 runTestWithNone<Helper>(testSleepAbsolute<Helper>, name + "::this_thread::sleep(), absolute time");
693}
694
695template <typename Helper>
696void testSleepNoThreadStd(const std::string& name)
697{
698 std::cout << std::endl;
699 runTest<Helper>(testSleepFor <Helper>, name + "::this_thread::sleep_for(), no thread");
700 runTest<Helper>(testSleepUntilSteady<Helper>, name + "::this_thread::sleep_until(), no thread, steady time");
701 runTest<Helper>(testSleepUntilSystem<Helper>, name + "::this_thread::sleep_until(), no thread, system time");
702 runTest<Helper>(testSleepUntilCustom<Helper>, name + "::this_thread::sleep_until(), no thread, custom time");
703}
704
705template <typename Helper>
706void testSleepNoThreadBoost(const std::string& name)
707{
708 testSleepNoThreadStd<Helper>(name);
709
710 // Boost-only functions
711 runTest<Helper>(testSleepRelative<Helper>, name + "::this_thread::sleep(), no thread, relative time");
712 runTest<Helper>(testSleepAbsolute<Helper>, name + "::this_thread::sleep(), no thread, absolute time");
713}
714
715/******************************************************************************/
716
717// Test Sleep, No Interruption Point
718
719template <typename Helper>
720void testSleepForNoInt(const long long jumpMs)
721{
722 typename Helper::steady_time_point before(Helper::steadyNow());
723 Helper::sleep_for_no_int(Helper::waitDur);
724 typename Helper::steady_time_point after(Helper::steadyNow());
725
726 checkWaitTime<Helper>(Helper::waitDur, after - before, e_na);
727}
728
729template <typename Helper>
730void testSleepUntilNoIntSteady(const long long jumpMs)
731{
732 typename Helper::steady_time_point before(Helper::steadyNow());
733 Helper::sleep_until_no_int(Helper::steadyNow() + Helper::waitDur);
734 typename Helper::steady_time_point after(Helper::steadyNow());
735
736 checkWaitTime<Helper>(Helper::waitDur, after - before, e_na);
737}
738
739template <typename Helper>
740void testSleepUntilNoIntSystem(const long long jumpMs)
741{
742 typename Helper::steady_time_point before(Helper::steadyNow());
743 Helper::sleep_until_no_int(Helper::systemNow() + Helper::waitDur);
744 typename Helper::steady_time_point after(Helper::steadyNow());
745
746 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na);
747}
748
749template <typename Helper>
750void testSleepUntilNoIntCustom(const long long jumpMs)
751{
752 typename Helper::steady_time_point before(Helper::steadyNow());
753 Helper::sleep_until_no_int(Helper::customNow() + Helper::waitDur);
754 typename Helper::steady_time_point after(Helper::steadyNow());
755
756 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na);
757}
758
759//--------------------------------------
760
761#ifndef SKIP_NO_INT_SLEEP
762
763template <typename Helper>
764void testSleepNoIntRelative(const long long jumpMs)
765{
766#ifndef SKIP_DATETIME_FUNCTIONS
767 typename Helper::steady_time_point before(Helper::steadyNow());
768 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
769 boost::this_thread::no_interruption_point::sleep(rel_time: ptDur);
770 typename Helper::steady_time_point after(Helper::steadyNow());
771
772 checkWaitTime<Helper>(Helper::waitDur, after - before, e_na);
773#else
774 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
775#endif
776}
777
778template <typename Helper>
779void testSleepNoIntAbsolute(const long long jumpMs)
780{
781#ifndef SKIP_DATETIME_FUNCTIONS
782 typename Helper::steady_time_point before(Helper::steadyNow());
783 boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
784 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
785 boost::this_thread::no_interruption_point::sleep(abs_time: ptNow + ptDur);
786 typename Helper::steady_time_point after(Helper::steadyNow());
787
788 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na);
789#else
790 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
791#endif
792}
793
794#endif
795
796//--------------------------------------
797
798// Only Boost supports no_interruption_point
799
800template <typename Helper>
801void testSleepNoIntBoost(const std::string& name)
802{
803 std::cout << std::endl;
804 runTestWithNone<Helper>(testSleepForNoInt <Helper>, name + "::this_thread::no_interruption_point::sleep_for()");
805 runTestWithNone<Helper>(testSleepUntilNoIntSteady<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), steady time");
806 runTestWithNone<Helper>(testSleepUntilNoIntSystem<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), system time");
807 runTestWithNone<Helper>(testSleepUntilNoIntCustom<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), custom time");
808
809#ifndef SKIP_NO_INT_SLEEP
810 runTestWithNone<Helper>(testSleepNoIntRelative<Helper>, name + "::this_thread::no_interruption_point::sleep(), relative time");
811 runTestWithNone<Helper>(testSleepNoIntAbsolute<Helper>, name + "::this_thread::no_interruption_point::sleep(), absolute time");
812#endif
813}
814
815template <typename Helper>
816void testSleepNoThreadNoIntBoost(const std::string& name)
817{
818 std::cout << std::endl;
819 runTest<Helper>(testSleepForNoInt <Helper>, name + "::this_thread::no_interruption_point::sleep_for(), no thread");
820 runTest<Helper>(testSleepUntilNoIntSteady<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, steady time");
821 runTest<Helper>(testSleepUntilNoIntSystem<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, system time");
822 runTest<Helper>(testSleepUntilNoIntCustom<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, custom time");
823
824#ifndef SKIP_NO_INT_SLEEP
825 runTest<Helper>(testSleepNoIntRelative<Helper>, name + "::this_thread::no_interruption_point::sleep(), no thread, relative time");
826 runTest<Helper>(testSleepNoIntAbsolute<Helper>, name + "::this_thread::no_interruption_point::sleep(), no thread, absolute time");
827#endif
828}
829
830/******************************************************************************/
831
832// Test Try Join
833
834template <typename Helper>
835void testTryJoinFor(const long long jumpMs)
836{
837 typename Helper::steady_time_point before(Helper::steadyNow());
838 typename Helper::thread t3(sleepForLongTime);
839 bool succeeded = t3.try_join_for(Helper::waitDur);
840 typename Helper::steady_time_point after(Helper::steadyNow());
841
842 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
843}
844
845template <typename Helper>
846void testTryJoinUntilSteady(const long long jumpMs)
847{
848 typename Helper::steady_time_point before(Helper::steadyNow());
849 typename Helper::thread t3(sleepForLongTime);
850 bool succeeded = t3.try_join_until(Helper::steadyNow() + Helper::waitDur);
851 typename Helper::steady_time_point after(Helper::steadyNow());
852
853 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
854}
855
856template <typename Helper>
857void testTryJoinUntilSystem(const long long jumpMs)
858{
859 typename Helper::steady_time_point before(Helper::steadyNow());
860 typename Helper::thread t3(sleepForLongTime);
861 bool succeeded = t3.try_join_until(Helper::systemNow() + Helper::waitDur);
862 typename Helper::steady_time_point after(Helper::steadyNow());
863
864 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
865}
866
867template <typename Helper>
868void testTryJoinUntilCustom(const long long jumpMs)
869{
870 typename Helper::steady_time_point before(Helper::steadyNow());
871 typename Helper::thread t3(sleepForLongTime);
872 bool succeeded = t3.try_join_until(Helper::customNow() + Helper::waitDur);
873 typename Helper::steady_time_point after(Helper::steadyNow());
874
875 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
876}
877
878//--------------------------------------
879
880template <typename Helper>
881void testTimedJoinRelative(const long long jumpMs)
882{
883#ifndef SKIP_DATETIME_FUNCTIONS
884 typename Helper::steady_time_point before(Helper::steadyNow());
885 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
886 typename Helper::thread t3(sleepForLongTime);
887 bool succeeded = t3.timed_join(ptDur);
888 typename Helper::steady_time_point after(Helper::steadyNow());
889
890 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
891#else
892 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
893#endif
894}
895
896template <typename Helper>
897void testTimedJoinAbsolute(const long long jumpMs)
898{
899#ifndef SKIP_DATETIME_FUNCTIONS
900 typename Helper::steady_time_point before(Helper::steadyNow());
901 boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
902 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
903 typename Helper::thread t3(sleepForLongTime);
904 bool succeeded = t3.timed_join(ptNow + ptDur);
905 typename Helper::steady_time_point after(Helper::steadyNow());
906
907 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
908#else
909 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
910#endif
911}
912
913//--------------------------------------
914
915// Only Boost supports timed try_join functions
916
917template <typename Helper>
918void testJoinBoost(const std::string& name)
919{
920 std::cout << std::endl;
921 runTestWithNone<Helper>(testTryJoinFor <Helper>, name + "::thread::try_join_for()");
922 runTestWithNone<Helper>(testTryJoinUntilSteady<Helper>, name + "::thread::try_join_until(), steady time");
923 runTestWithNone<Helper>(testTryJoinUntilSystem<Helper>, name + "::thread::try_join_until(), system time");
924 runTestWithNone<Helper>(testTryJoinUntilCustom<Helper>, name + "::thread::try_join_until(), custom time");
925 runTestWithNone<Helper>(testTimedJoinRelative <Helper>, name + "::thread::timed_join(), relative time");
926 runTestWithNone<Helper>(testTimedJoinAbsolute <Helper>, name + "::thread::timed_join(), absolute time");
927}
928
929/******************************************************************************/
930
931// Test Condition Variable Wait
932
933template <typename Helper>
934void testCondVarWaitFor(const long long jumpMs)
935{
936 typename Helper::cond cv;
937 typename Helper::mutex m;
938 typename Helper::unique_lock g(m);
939
940 typename Helper::steady_time_point before(Helper::steadyNow());
941 bool noTimeout = (cv.wait_for(g, Helper::waitDur) == Helper::cv_status::no_timeout);
942 typename Helper::steady_time_point after(Helper::steadyNow());
943
944 checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
945}
946
947template <typename Helper>
948void testCondVarWaitUntilSteady(const long long jumpMs)
949{
950 typename Helper::cond cv;
951 typename Helper::mutex m;
952 typename Helper::unique_lock g(m);
953
954 typename Helper::steady_time_point before(Helper::steadyNow());
955 bool noTimeout = (cv.wait_until(g, Helper::steadyNow() + Helper::waitDur) == Helper::cv_status::no_timeout);
956 typename Helper::steady_time_point after(Helper::steadyNow());
957
958 checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
959}
960
961template <typename Helper>
962void testCondVarWaitUntilSystem(const long long jumpMs)
963{
964 typename Helper::cond cv;
965 typename Helper::mutex m;
966 typename Helper::unique_lock g(m);
967
968 typename Helper::steady_time_point before(Helper::steadyNow());
969 bool noTimeout = (cv.wait_until(g, Helper::systemNow() + Helper::waitDur) == Helper::cv_status::no_timeout);
970 typename Helper::steady_time_point after(Helper::steadyNow());
971
972 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
973}
974
975template <typename Helper>
976void testCondVarWaitUntilCustom(const long long jumpMs)
977{
978 typename Helper::cond cv;
979 typename Helper::mutex m;
980 typename Helper::unique_lock g(m);
981
982 typename Helper::steady_time_point before(Helper::steadyNow());
983 bool noTimeout = (cv.wait_until(g, Helper::customNow() + Helper::waitDur) == Helper::cv_status::no_timeout);
984 typename Helper::steady_time_point after(Helper::steadyNow());
985
986 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
987}
988
989//--------------------------------------
990
991template <typename Helper>
992void testCondVarTimedWaitRelative(const long long jumpMs)
993{
994#ifndef SKIP_DATETIME_FUNCTIONS
995 typename Helper::cond cv;
996 typename Helper::mutex m;
997 typename Helper::unique_lock g(m);
998
999 typename Helper::steady_time_point before(Helper::steadyNow());
1000 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1001 bool noTimeout = cv.timed_wait(g, ptDur);
1002 typename Helper::steady_time_point after(Helper::steadyNow());
1003
1004 checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
1005#else
1006 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1007#endif
1008}
1009
1010template <typename Helper>
1011void testCondVarTimedWaitAbsolute(const long long jumpMs)
1012{
1013#ifndef SKIP_DATETIME_FUNCTIONS
1014 typename Helper::cond cv;
1015 typename Helper::mutex m;
1016 typename Helper::unique_lock g(m);
1017
1018 typename Helper::steady_time_point before(Helper::steadyNow());
1019 boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
1020 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1021 bool noTimeout = cv.timed_wait(g, ptNow + ptDur);
1022 typename Helper::steady_time_point after(Helper::steadyNow());
1023
1024 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
1025#else
1026 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1027#endif
1028}
1029
1030//--------------------------------------
1031
1032template <typename Helper>
1033void testCondVarStd(const std::string& name)
1034{
1035 std::cout << std::endl;
1036 runTestWithNone<Helper>(testCondVarWaitFor <Helper>, name + "::wait_for()");
1037 runTestWithNone<Helper>(testCondVarWaitUntilSteady<Helper>, name + "::wait_until(), steady time");
1038 runTestWithNone<Helper>(testCondVarWaitUntilSystem<Helper>, name + "::wait_until(), system time");
1039 runTestWithNone<Helper>(testCondVarWaitUntilCustom<Helper>, name + "::wait_until(), custom time");
1040}
1041
1042template <typename Helper>
1043void testCondVarBoost(const std::string& name)
1044{
1045 testCondVarStd<Helper>(name);
1046
1047 // Boost-only functions
1048 runTestWithNone<Helper>(testCondVarTimedWaitRelative<Helper>, name + "::timed_wait(), relative time");
1049 runTestWithNone<Helper>(testCondVarTimedWaitAbsolute<Helper>, name + "::timed_wait(), absolute time");
1050}
1051
1052/******************************************************************************/
1053
1054// Test Condition Variable Wait with Predicate
1055
1056template <typename Helper>
1057void testCondVarWaitForPred(const long long jumpMs)
1058{
1059 typename Helper::cond cv;
1060 typename Helper::mutex m;
1061 typename Helper::unique_lock g(m);
1062
1063 typename Helper::steady_time_point before(Helper::steadyNow());
1064 bool noTimeout = cv.wait_for(g, Helper::waitDur, returnFalse);
1065 typename Helper::steady_time_point after(Helper::steadyNow());
1066
1067 checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
1068}
1069
1070template <typename Helper>
1071void testCondVarWaitUntilPredSteady(const long long jumpMs)
1072{
1073 typename Helper::cond cv;
1074 typename Helper::mutex m;
1075 typename Helper::unique_lock g(m);
1076
1077 typename Helper::steady_time_point before(Helper::steadyNow());
1078 bool noTimeout = cv.wait_until(g, Helper::steadyNow() + Helper::waitDur, returnFalse);
1079 typename Helper::steady_time_point after(Helper::steadyNow());
1080
1081 checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
1082}
1083
1084template <typename Helper>
1085void testCondVarWaitUntilPredSystem(const long long jumpMs)
1086{
1087 typename Helper::cond cv;
1088 typename Helper::mutex m;
1089 typename Helper::unique_lock g(m);
1090
1091 typename Helper::steady_time_point before(Helper::steadyNow());
1092 bool noTimeout = cv.wait_until(g, Helper::systemNow() + Helper::waitDur, returnFalse);
1093 typename Helper::steady_time_point after(Helper::steadyNow());
1094
1095 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
1096}
1097
1098template <typename Helper>
1099void testCondVarWaitUntilPredCustom(const long long jumpMs)
1100{
1101 typename Helper::cond cv;
1102 typename Helper::mutex m;
1103 typename Helper::unique_lock g(m);
1104
1105 typename Helper::steady_time_point before(Helper::steadyNow());
1106 bool noTimeout = cv.wait_until(g, Helper::customNow() + Helper::waitDur, returnFalse);
1107 typename Helper::steady_time_point after(Helper::steadyNow());
1108
1109 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
1110}
1111
1112//--------------------------------------
1113
1114template <typename Helper>
1115void testCondVarTimedWaitPredRelative(const long long jumpMs)
1116{
1117#ifndef SKIP_DATETIME_FUNCTIONS
1118 typename Helper::cond cv;
1119 typename Helper::mutex m;
1120 typename Helper::unique_lock g(m);
1121
1122 typename Helper::steady_time_point before(Helper::steadyNow());
1123 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1124 bool noTimeout = cv.timed_wait(g, ptDur, returnFalse);
1125 typename Helper::steady_time_point after(Helper::steadyNow());
1126
1127 checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
1128#else
1129 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1130#endif
1131}
1132
1133template <typename Helper>
1134void testCondVarTimedWaitPredAbsolute(const long long jumpMs)
1135{
1136#ifndef SKIP_DATETIME_FUNCTIONS
1137 typename Helper::cond cv;
1138 typename Helper::mutex m;
1139 typename Helper::unique_lock g(m);
1140
1141 typename Helper::steady_time_point before(Helper::steadyNow());
1142 boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
1143 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1144 bool noTimeout = cv.timed_wait(g, ptNow + ptDur, returnFalse);
1145 typename Helper::steady_time_point after(Helper::steadyNow());
1146
1147 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
1148#else
1149 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1150#endif
1151}
1152
1153//--------------------------------------
1154
1155template <typename Helper>
1156void testCondVarPredStd(const std::string& name)
1157{
1158 std::cout << std::endl;
1159 runTestWithNone<Helper>(testCondVarWaitForPred <Helper>, name + "::wait_for(), with predicate");
1160 runTestWithNone<Helper>(testCondVarWaitUntilPredSteady<Helper>, name + "::wait_until(), with predicate, steady time");
1161 runTestWithNone<Helper>(testCondVarWaitUntilPredSystem<Helper>, name + "::wait_until(), with predicate, system time");
1162 runTestWithNone<Helper>(testCondVarWaitUntilPredCustom<Helper>, name + "::wait_until(), with predicate, custom time");
1163}
1164
1165template <typename Helper>
1166void testCondVarPredBoost(const std::string& name)
1167{
1168 testCondVarPredStd<Helper>(name);
1169
1170 // Boost-only functions
1171 runTestWithNone<Helper>(testCondVarTimedWaitPredRelative<Helper>, name + "::timed_wait(), with predicate, relative time");
1172 runTestWithNone<Helper>(testCondVarTimedWaitPredAbsolute<Helper>, name + "::timed_wait(), with predicate, absolute time");
1173}
1174
1175/******************************************************************************/
1176
1177// Test Try Lock
1178
1179template <typename Helper>
1180void testTryLockFor(typename Helper::mutex& m, const long long jumpMs)
1181{
1182 typename Helper::steady_time_point before(Helper::steadyNow());
1183 bool succeeded = m.try_lock_for(Helper::waitDur);
1184 typename Helper::steady_time_point after(Helper::steadyNow());
1185
1186 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1187}
1188
1189template <typename Helper>
1190void testTryLockUntilSteady(typename Helper::mutex& m, const long long jumpMs)
1191{
1192 typename Helper::steady_time_point before(Helper::steadyNow());
1193 bool succeeded = m.try_lock_until(Helper::steadyNow() + Helper::waitDur);
1194 typename Helper::steady_time_point after(Helper::steadyNow());
1195
1196 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1197}
1198
1199template <typename Helper>
1200void testTryLockUntilSystem(typename Helper::mutex& m, const long long jumpMs)
1201{
1202 typename Helper::steady_time_point before(Helper::steadyNow());
1203 bool succeeded = m.try_lock_until(Helper::systemNow() + Helper::waitDur);
1204 typename Helper::steady_time_point after(Helper::steadyNow());
1205
1206 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1207}
1208
1209template <typename Helper>
1210void testTryLockUntilCustom(typename Helper::mutex& m, const long long jumpMs)
1211{
1212 typename Helper::steady_time_point before(Helper::steadyNow());
1213 bool succeeded = m.try_lock_until(Helper::customNow() + Helper::waitDur);
1214 typename Helper::steady_time_point after(Helper::steadyNow());
1215
1216 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1217}
1218
1219//--------------------------------------
1220
1221template <typename Helper>
1222void testTimedLockRelative(typename Helper::mutex& m, const long long jumpMs)
1223{
1224#ifndef SKIP_DATETIME_FUNCTIONS
1225 typename Helper::steady_time_point before(Helper::steadyNow());
1226 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1227 bool succeeded = m.timed_lock(ptDur);
1228 typename Helper::steady_time_point after(Helper::steadyNow());
1229
1230 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1231#else
1232 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1233#endif
1234}
1235
1236template <typename Helper>
1237void testTimedLockAbsolute(typename Helper::mutex& m, const long long jumpMs)
1238{
1239#ifndef SKIP_DATETIME_FUNCTIONS
1240 typename Helper::steady_time_point before(Helper::steadyNow());
1241 boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
1242 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1243 bool succeeded = m.timed_lock(ptNow + ptDur);
1244 typename Helper::steady_time_point after(Helper::steadyNow());
1245
1246 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1247#else
1248 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1249#endif
1250}
1251
1252//--------------------------------------
1253
1254template <typename Helper>
1255void testMutexStd(const std::string& name)
1256{
1257 std::cout << std::endl;
1258 runTestWithUnique<Helper>(testTryLockFor <Helper>, name + "::try_lock_for()");
1259 runTestWithUnique<Helper>(testTryLockUntilSteady<Helper>, name + "::try_lock_until(), steady time");
1260 runTestWithUnique<Helper>(testTryLockUntilSystem<Helper>, name + "::try_lock_until(), system time");
1261 runTestWithUnique<Helper>(testTryLockUntilCustom<Helper>, name + "::try_lock_until(), custom time");
1262}
1263
1264template <typename Helper>
1265void testMutexBoost(const std::string& name)
1266{
1267 testMutexStd<Helper>(name);
1268
1269 // Boost-only functions
1270 runTestWithUnique<Helper>(testTimedLockRelative<Helper>, name + "::timed_lock(), relative time");
1271 runTestWithUnique<Helper>(testTimedLockAbsolute<Helper>, name + "::timed_lock(), absolute time");
1272}
1273
1274/******************************************************************************/
1275
1276// Test Try Lock Shared
1277
1278template <typename Helper>
1279void testTryLockSharedFor(typename Helper::mutex& m, const long long jumpMs)
1280{
1281 typename Helper::steady_time_point before(Helper::steadyNow());
1282 bool succeeded = m.try_lock_shared_for(Helper::waitDur);
1283 typename Helper::steady_time_point after(Helper::steadyNow());
1284
1285 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1286}
1287
1288template <typename Helper>
1289void testTryLockSharedUntilSteady(typename Helper::mutex& m, const long long jumpMs)
1290{
1291 typename Helper::steady_time_point before(Helper::steadyNow());
1292 bool succeeded = m.try_lock_shared_until(Helper::steadyNow() + Helper::waitDur);
1293 typename Helper::steady_time_point after(Helper::steadyNow());
1294
1295 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1296}
1297
1298template <typename Helper>
1299void testTryLockSharedUntilSystem(typename Helper::mutex& m, const long long jumpMs)
1300{
1301 typename Helper::steady_time_point before(Helper::steadyNow());
1302 bool succeeded = m.try_lock_shared_until(Helper::systemNow() + Helper::waitDur);
1303 typename Helper::steady_time_point after(Helper::steadyNow());
1304
1305 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1306}
1307
1308template <typename Helper>
1309void testTryLockSharedUntilCustom(typename Helper::mutex& m, const long long jumpMs)
1310{
1311 typename Helper::steady_time_point before(Helper::steadyNow());
1312 bool succeeded = m.try_lock_shared_until(Helper::customNow() + Helper::waitDur);
1313 typename Helper::steady_time_point after(Helper::steadyNow());
1314
1315 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1316}
1317
1318//--------------------------------------
1319
1320template <typename Helper>
1321void testTimedLockSharedRelative(typename Helper::mutex& m, const long long jumpMs)
1322{
1323#ifndef SKIP_DATETIME_FUNCTIONS
1324 typename Helper::steady_time_point before(Helper::steadyNow());
1325 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1326 bool succeeded = m.timed_lock_shared(ptDur);
1327 typename Helper::steady_time_point after(Helper::steadyNow());
1328
1329 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1330#else
1331 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1332#endif
1333}
1334
1335template <typename Helper>
1336void testTimedLockSharedAbsolute(typename Helper::mutex& m, const long long jumpMs)
1337{
1338#ifndef SKIP_DATETIME_FUNCTIONS
1339 typename Helper::steady_time_point before(Helper::steadyNow());
1340 boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
1341 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1342 bool succeeded = m.timed_lock_shared(ptNow + ptDur);
1343 typename Helper::steady_time_point after(Helper::steadyNow());
1344
1345 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1346#else
1347 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1348#endif
1349}
1350
1351//--------------------------------------
1352
1353template <typename Helper>
1354void testMutexSharedStd(const std::string& name)
1355{
1356 std::cout << std::endl;
1357 runTestWithUnique<Helper>(testTryLockSharedFor <Helper>, name + "::try_lock_shared_for()");
1358 runTestWithUnique<Helper>(testTryLockSharedUntilSteady<Helper>, name + "::try_lock_shared_until(), steady time");
1359 runTestWithUnique<Helper>(testTryLockSharedUntilSystem<Helper>, name + "::try_lock_shared_until(), system time");
1360 runTestWithUnique<Helper>(testTryLockSharedUntilCustom<Helper>, name + "::try_lock_shared_until(), custom time");
1361}
1362
1363template <typename Helper>
1364void testMutexSharedBoost(const std::string& name)
1365{
1366 testMutexSharedStd<Helper>(name);
1367
1368 // Boost-only functions
1369 runTestWithUnique<Helper>(testTimedLockSharedRelative<Helper>, name + "::timed_lock_shared(), relative time");
1370 runTestWithUnique<Helper>(testTimedLockSharedAbsolute<Helper>, name + "::timed_lock_shared(), absolute time");
1371}
1372
1373/******************************************************************************/
1374
1375// Test Try Lock Upgrade
1376
1377#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
1378
1379template <typename Helper>
1380void testTryLockUpgradeFor(typename Helper::mutex& m, const long long jumpMs)
1381{
1382 typename Helper::steady_time_point before(Helper::steadyNow());
1383 bool succeeded = m.try_lock_upgrade_for(Helper::waitDur);
1384 typename Helper::steady_time_point after(Helper::steadyNow());
1385
1386 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1387}
1388
1389template <typename Helper>
1390void testTryLockUpgradeUntilSteady(typename Helper::mutex& m, const long long jumpMs)
1391{
1392 typename Helper::steady_time_point before(Helper::steadyNow());
1393 bool succeeded = m.try_lock_upgrade_until(Helper::steadyNow() + Helper::waitDur);
1394 typename Helper::steady_time_point after(Helper::steadyNow());
1395
1396 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1397}
1398
1399template <typename Helper>
1400void testTryLockUpgradeUntilSystem(typename Helper::mutex& m, const long long jumpMs)
1401{
1402 typename Helper::steady_time_point before(Helper::steadyNow());
1403 bool succeeded = m.try_lock_upgrade_until(Helper::systemNow() + Helper::waitDur);
1404 typename Helper::steady_time_point after(Helper::steadyNow());
1405
1406 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1407}
1408
1409template <typename Helper>
1410void testTryLockUpgradeUntilCustom(typename Helper::mutex& m, const long long jumpMs)
1411{
1412 typename Helper::steady_time_point before(Helper::steadyNow());
1413 bool succeeded = m.try_lock_upgrade_until(Helper::customNow() + Helper::waitDur);
1414 typename Helper::steady_time_point after(Helper::steadyNow());
1415
1416 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1417}
1418
1419//--------------------------------------
1420
1421template <typename Helper>
1422void testTimedLockUpgradeRelative(typename Helper::mutex& m, const long long jumpMs)
1423{
1424#ifndef SKIP_DATETIME_FUNCTIONS
1425 typename Helper::steady_time_point before(Helper::steadyNow());
1426 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1427 bool succeeded = m.timed_lock_upgrade(ptDur);
1428 typename Helper::steady_time_point after(Helper::steadyNow());
1429
1430 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1431#else
1432 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1433#endif
1434}
1435
1436template <typename Helper>
1437void testTimedLockUpgradeAbsolute(typename Helper::mutex& m, const long long jumpMs)
1438{
1439#ifndef SKIP_DATETIME_FUNCTIONS
1440 typename Helper::steady_time_point before(Helper::steadyNow());
1441 boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
1442 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1443 bool succeeded = m.timed_lock_upgrade(ptNow + ptDur);
1444 typename Helper::steady_time_point after(Helper::steadyNow());
1445
1446 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1447#else
1448 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1449#endif
1450}
1451
1452//--------------------------------------
1453
1454template <typename Helper>
1455void testTryUnlockSharedAndLockFor(typename Helper::mutex& m, const long long jumpMs)
1456{
1457 boost::shared_lock_guard<typename Helper::mutex> g(m);
1458
1459 typename Helper::steady_time_point before(Helper::steadyNow());
1460 bool succeeded = m.try_unlock_shared_and_lock_for(Helper::waitDur);
1461 typename Helper::steady_time_point after(Helper::steadyNow());
1462
1463 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1464}
1465
1466template <typename Helper>
1467void testTryUnlockSharedAndLockUntilSteady(typename Helper::mutex& m, const long long jumpMs)
1468{
1469 boost::shared_lock_guard<typename Helper::mutex> g(m);
1470
1471 typename Helper::steady_time_point before(Helper::steadyNow());
1472 bool succeeded = m.try_unlock_shared_and_lock_until(Helper::steadyNow() + Helper::waitDur);
1473 typename Helper::steady_time_point after(Helper::steadyNow());
1474
1475 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1476}
1477
1478template <typename Helper>
1479void testTryUnlockSharedAndLockUntilSystem(typename Helper::mutex& m, const long long jumpMs)
1480{
1481 boost::shared_lock_guard<typename Helper::mutex> g(m);
1482
1483 typename Helper::steady_time_point before(Helper::steadyNow());
1484 bool succeeded = m.try_unlock_shared_and_lock_until(Helper::systemNow() + Helper::waitDur);
1485 typename Helper::steady_time_point after(Helper::steadyNow());
1486
1487 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1488}
1489
1490template <typename Helper>
1491void testTryUnlockSharedAndLockUntilCustom(typename Helper::mutex& m, const long long jumpMs)
1492{
1493 boost::shared_lock_guard<typename Helper::mutex> g(m);
1494
1495 typename Helper::steady_time_point before(Helper::steadyNow());
1496 bool succeeded = m.try_unlock_shared_and_lock_until(Helper::customNow() + Helper::waitDur);
1497 typename Helper::steady_time_point after(Helper::steadyNow());
1498
1499 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1500}
1501
1502//--------------------------------------
1503
1504template <typename Helper>
1505void testTryUnlockUpgradeAndLockFor(typename Helper::mutex& m, const long long jumpMs)
1506{
1507 boost::upgrade_lock<typename Helper::mutex> g(m);
1508
1509 typename Helper::steady_time_point before(Helper::steadyNow());
1510 bool succeeded = m.try_unlock_upgrade_and_lock_for(Helper::waitDur);
1511 typename Helper::steady_time_point after(Helper::steadyNow());
1512
1513 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1514}
1515
1516template <typename Helper>
1517void testTryUnlockUpgradeAndLockUntilSteady(typename Helper::mutex& m, const long long jumpMs)
1518{
1519 boost::upgrade_lock<typename Helper::mutex> g(m);
1520
1521 typename Helper::steady_time_point before(Helper::steadyNow());
1522 bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::steadyNow() + Helper::waitDur);
1523 typename Helper::steady_time_point after(Helper::steadyNow());
1524
1525 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1526}
1527
1528template <typename Helper>
1529void testTryUnlockUpgradeAndLockUntilSystem(typename Helper::mutex& m, const long long jumpMs)
1530{
1531 boost::upgrade_lock<typename Helper::mutex> g(m);
1532
1533 typename Helper::steady_time_point before(Helper::steadyNow());
1534 bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::systemNow() + Helper::waitDur);
1535 typename Helper::steady_time_point after(Helper::steadyNow());
1536
1537 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1538}
1539
1540template <typename Helper>
1541void testTryUnlockUpgradeAndLockUntilCustom(typename Helper::mutex& m, const long long jumpMs)
1542{
1543 boost::upgrade_lock<typename Helper::mutex> g(m);
1544
1545 typename Helper::steady_time_point before(Helper::steadyNow());
1546 bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::customNow() + Helper::waitDur);
1547 typename Helper::steady_time_point after(Helper::steadyNow());
1548
1549 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1550}
1551
1552//--------------------------------------
1553
1554template <typename Helper>
1555void testTryUnlockSharedAndLockUpgradeFor(typename Helper::mutex& m, const long long jumpMs)
1556{
1557 boost::shared_lock_guard<typename Helper::mutex> g(m);
1558
1559 typename Helper::steady_time_point before(Helper::steadyNow());
1560 bool succeeded = m.try_unlock_shared_and_lock_upgrade_for(Helper::waitDur);
1561 typename Helper::steady_time_point after(Helper::steadyNow());
1562
1563 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1564}
1565
1566template <typename Helper>
1567void testTryUnlockSharedAndLockUpgradeUntilSteady(typename Helper::mutex& m, const long long jumpMs)
1568{
1569 boost::shared_lock_guard<typename Helper::mutex> g(m);
1570
1571 typename Helper::steady_time_point before(Helper::steadyNow());
1572 bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::steadyNow() + Helper::waitDur);
1573 typename Helper::steady_time_point after(Helper::steadyNow());
1574
1575 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good);
1576}
1577
1578template <typename Helper>
1579void testTryUnlockSharedAndLockUpgradeUntilSystem(typename Helper::mutex& m, const long long jumpMs)
1580{
1581 boost::shared_lock_guard<typename Helper::mutex> g(m);
1582
1583 typename Helper::steady_time_point before(Helper::steadyNow());
1584 bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::systemNow() + Helper::waitDur);
1585 typename Helper::steady_time_point after(Helper::steadyNow());
1586
1587 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1588}
1589
1590template <typename Helper>
1591void testTryUnlockSharedAndLockUpgradeUntilCustom(typename Helper::mutex& m, const long long jumpMs)
1592{
1593 boost::shared_lock_guard<typename Helper::mutex> g(m);
1594
1595 typename Helper::steady_time_point before(Helper::steadyNow());
1596 bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::customNow() + Helper::waitDur);
1597 typename Helper::steady_time_point after(Helper::steadyNow());
1598
1599 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good);
1600}
1601
1602#endif
1603
1604//--------------------------------------
1605
1606// Only Boost supports upgrade mutexes
1607
1608template <typename Helper>
1609void testMutexUpgradeBoost(const std::string& name)
1610{
1611#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
1612 std::cout << std::endl;
1613 runTestWithUnique<Helper>(testTryLockUpgradeFor <Helper>, name + "::try_lock_upgrade_for()");
1614 runTestWithUnique<Helper>(testTryLockUpgradeUntilSteady<Helper>, name + "::try_lock_upgrade_until(), steady time");
1615 runTestWithUnique<Helper>(testTryLockUpgradeUntilSystem<Helper>, name + "::try_lock_upgrade_until(), system time");
1616 runTestWithUnique<Helper>(testTryLockUpgradeUntilCustom<Helper>, name + "::try_lock_upgrade_until(), custom time");
1617 runTestWithUnique<Helper>(testTimedLockUpgradeRelative <Helper>, name + "::timed_lock_upgrade(), relative time");
1618 runTestWithUnique<Helper>(testTimedLockUpgradeAbsolute <Helper>, name + "::timed_lock_upgrade(), absolute time");
1619
1620 std::cout << std::endl;
1621 runTestWithShared<Helper>(testTryUnlockSharedAndLockFor <Helper>, name + "::try_unlock_shared_and_lock_for()");
1622 runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilSteady<Helper>, name + "::try_unlock_shared_and_lock_until(), steady time");
1623 runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilSystem<Helper>, name + "::try_unlock_shared_and_lock_until(), system time");
1624 runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilCustom<Helper>, name + "::try_unlock_shared_and_lock_until(), custom time");
1625
1626 std::cout << std::endl;
1627 runTestWithShared<Helper>(testTryUnlockUpgradeAndLockFor <Helper>, name + "::try_unlock_upgrade_and_lock_for()");
1628 runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilSteady<Helper>, name + "::try_unlock_upgrade_and_lock_until(), steady time");
1629 runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilSystem<Helper>, name + "::try_unlock_upgrade_and_lock_until(), system time");
1630 runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilCustom<Helper>, name + "::try_unlock_upgrade_and_lock_until(), custom time");
1631
1632 std::cout << std::endl;
1633 runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockFor <Helper>, name + "::try_unlock_shared_and_lock_upgrade_for()");
1634 runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilSteady<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), steady time");
1635 runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilSystem<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), system time");
1636 runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilCustom<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), custom time");
1637#endif
1638}
1639
1640/******************************************************************************/
1641
1642// Test Future Wait
1643
1644template <typename Helper>
1645void testFutureWaitFor(const long long jumpMs)
1646{
1647 typename Helper::packaged_task pt(returnFalse);
1648 typename Helper::future f = pt.get_future();
1649
1650 typename Helper::steady_time_point before(Helper::steadyNow());
1651 bool timeout = (f.wait_for(Helper::waitDur) == Helper::future_status::timeout);
1652 typename Helper::steady_time_point after(Helper::steadyNow());
1653
1654 checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
1655}
1656
1657template <typename Helper>
1658void testFutureWaitUntilSteady(const long long jumpMs)
1659{
1660 typename Helper::packaged_task pt(returnFalse);
1661 typename Helper::future f = pt.get_future();
1662
1663 typename Helper::steady_time_point before(Helper::steadyNow());
1664 bool timeout = (f.wait_until(Helper::steadyNow() + Helper::waitDur) == Helper::future_status::timeout);
1665 typename Helper::steady_time_point after(Helper::steadyNow());
1666
1667 checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
1668}
1669
1670template <typename Helper>
1671void testFutureWaitUntilSystem(const long long jumpMs)
1672{
1673 typename Helper::packaged_task pt(returnFalse);
1674 typename Helper::future f = pt.get_future();
1675
1676 typename Helper::steady_time_point before(Helper::steadyNow());
1677 bool timeout = (f.wait_until(Helper::systemNow() + Helper::waitDur) == Helper::future_status::timeout);
1678 typename Helper::steady_time_point after(Helper::steadyNow());
1679
1680 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
1681}
1682
1683template <typename Helper>
1684void testFutureWaitUntilCustom(const long long jumpMs)
1685{
1686 typename Helper::packaged_task pt(returnFalse);
1687 typename Helper::future f = pt.get_future();
1688
1689 typename Helper::steady_time_point before(Helper::steadyNow());
1690 bool timeout = (f.wait_until(Helper::customNow() + Helper::waitDur) == Helper::future_status::timeout);
1691 typename Helper::steady_time_point after(Helper::steadyNow());
1692
1693 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
1694}
1695
1696//--------------------------------------
1697
1698template <typename Helper>
1699void testFutureTimedWaitRelative(const long long jumpMs)
1700{
1701#ifndef SKIP_DATETIME_FUNCTIONS
1702 typename Helper::packaged_task pt(returnFalse);
1703 typename Helper::future f = pt.get_future();
1704
1705 typename Helper::steady_time_point before(Helper::steadyNow());
1706 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1707 bool noTimeout = f.timed_wait(ptDur);
1708 typename Helper::steady_time_point after(Helper::steadyNow());
1709
1710 checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
1711#else
1712 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1713#endif
1714}
1715
1716template <typename Helper>
1717void testFutureTimedWaitAbsolute(const long long jumpMs)
1718{
1719#ifndef SKIP_DATETIME_FUNCTIONS
1720 typename Helper::packaged_task pt(returnFalse);
1721 typename Helper::future f = pt.get_future();
1722
1723 typename Helper::steady_time_point before(Helper::steadyNow());
1724 boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
1725 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1726 bool noTimeout = f.timed_wait_until(ptNow + ptDur);
1727 typename Helper::steady_time_point after(Helper::steadyNow());
1728
1729 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
1730#else
1731 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1732#endif
1733}
1734
1735//--------------------------------------
1736
1737template <typename Helper>
1738void testFutureStd(const std::string& name)
1739{
1740 std::cout << std::endl;
1741 runTestWithNone<Helper>(testFutureWaitFor <Helper>, name + "::wait_for()");
1742 runTestWithNone<Helper>(testFutureWaitUntilSteady<Helper>, name + "::wait_until(), steady time");
1743 runTestWithNone<Helper>(testFutureWaitUntilSystem<Helper>, name + "::wait_until(), system time");
1744 runTestWithNone<Helper>(testFutureWaitUntilCustom<Helper>, name + "::wait_until(), custom time");
1745}
1746
1747template <typename Helper>
1748void testFutureBoost(const std::string& name)
1749{
1750 testFutureStd<Helper>(name);
1751
1752 // Boost-only functions
1753 runTestWithNone<Helper>(testFutureTimedWaitRelative<Helper>, name + "::timed_wait(), relative time");
1754 runTestWithNone<Helper>(testFutureTimedWaitAbsolute<Helper>, name + "::timed_wait_until(), absolute time");
1755}
1756
1757/******************************************************************************/
1758
1759// Test Shared Future Wait
1760
1761template <typename Helper>
1762void testSharedFutureWaitFor(const long long jumpMs)
1763{
1764 typename Helper::packaged_task pt(returnFalse);
1765 typename Helper::future f = pt.get_future();
1766 typename Helper::shared_future sf = boost::move(f);
1767
1768 typename Helper::steady_time_point before(Helper::steadyNow());
1769 bool timeout = (sf.wait_for(Helper::waitDur) == Helper::future_status::timeout);
1770 typename Helper::steady_time_point after(Helper::steadyNow());
1771
1772 checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
1773}
1774
1775template <typename Helper>
1776void testSharedFutureWaitUntilSteady(const long long jumpMs)
1777{
1778 typename Helper::packaged_task pt(returnFalse);
1779 typename Helper::future f = pt.get_future();
1780 typename Helper::shared_future sf = boost::move(f);
1781
1782 typename Helper::steady_time_point before(Helper::steadyNow());
1783 bool timeout = (sf.wait_until(Helper::steadyNow() + Helper::waitDur) == Helper::future_status::timeout);
1784 typename Helper::steady_time_point after(Helper::steadyNow());
1785
1786 checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
1787}
1788
1789template <typename Helper>
1790void testSharedFutureWaitUntilSystem(const long long jumpMs)
1791{
1792 typename Helper::packaged_task pt(returnFalse);
1793 typename Helper::future f = pt.get_future();
1794 typename Helper::shared_future sf = boost::move(f);
1795
1796 typename Helper::steady_time_point before(Helper::steadyNow());
1797 bool timeout = (sf.wait_until(Helper::systemNow() + Helper::waitDur) == Helper::future_status::timeout);
1798 typename Helper::steady_time_point after(Helper::steadyNow());
1799
1800 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
1801}
1802
1803template <typename Helper>
1804void testSharedFutureWaitUntilCustom(const long long jumpMs)
1805{
1806 typename Helper::packaged_task pt(returnFalse);
1807 typename Helper::future f = pt.get_future();
1808 typename Helper::shared_future sf = boost::move(f);
1809
1810 typename Helper::steady_time_point before(Helper::steadyNow());
1811 bool timeout = (sf.wait_until(Helper::customNow() + Helper::waitDur) == Helper::future_status::timeout);
1812 typename Helper::steady_time_point after(Helper::steadyNow());
1813
1814 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
1815}
1816
1817//--------------------------------------
1818
1819template <typename Helper>
1820void testSharedFutureTimedWaitRelative(const long long jumpMs)
1821{
1822#ifndef SKIP_DATETIME_FUNCTIONS
1823 typename Helper::packaged_task pt(returnFalse);
1824 typename Helper::future f = pt.get_future();
1825 typename Helper::shared_future sf = boost::move(f);
1826
1827 typename Helper::steady_time_point before(Helper::steadyNow());
1828 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1829 bool noTimeout = sf.timed_wait(ptDur);
1830 typename Helper::steady_time_point after(Helper::steadyNow());
1831
1832 checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout);
1833#else
1834 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1835#endif
1836}
1837
1838template <typename Helper>
1839void testSharedFutureTimedWaitAbsolute(const long long jumpMs)
1840{
1841#ifndef SKIP_DATETIME_FUNCTIONS
1842 typename Helper::packaged_task pt(returnFalse);
1843 typename Helper::future f = pt.get_future();
1844 typename Helper::shared_future sf = boost::move(f);
1845
1846 typename Helper::steady_time_point before(Helper::steadyNow());
1847 boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time());
1848 boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast<boost::chrono::milliseconds>(Helper::waitDur).count());
1849 bool noTimeout = sf.timed_wait_until(ptNow + ptDur);
1850 typename Helper::steady_time_point after(Helper::steadyNow());
1851
1852 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout);
1853#else
1854 checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na);
1855#endif
1856}
1857
1858//--------------------------------------
1859
1860template <typename Helper>
1861void testSharedFutureStd(const std::string& name)
1862{
1863 std::cout << std::endl;
1864 runTestWithNone<Helper>(testSharedFutureWaitFor <Helper>, name + "::wait_for()");
1865 runTestWithNone<Helper>(testSharedFutureWaitUntilSteady<Helper>, name + "::wait_until(), steady time");
1866 runTestWithNone<Helper>(testSharedFutureWaitUntilSystem<Helper>, name + "::wait_until(), system time");
1867 runTestWithNone<Helper>(testSharedFutureWaitUntilCustom<Helper>, name + "::wait_until(), custom time");
1868}
1869
1870template <typename Helper>
1871void testSharedFutureBoost(const std::string& name)
1872{
1873 testSharedFutureStd<Helper>(name);
1874
1875 // Boost-only functions
1876 runTestWithNone<Helper>(testSharedFutureTimedWaitRelative<Helper>, name + "::timed_wait(), relative time");
1877 runTestWithNone<Helper>(testSharedFutureTimedWaitAbsolute<Helper>, name + "::timed_wait_until(), absolute time");
1878}
1879
1880/******************************************************************************/
1881
1882// Test Sync Priority Queue
1883
1884template <typename Helper>
1885void testSyncPriorityQueuePullFor(const long long jumpMs)
1886{
1887 boost::sync_priority_queue<int> q;
1888 int i;
1889
1890 typename Helper::steady_time_point before(Helper::steadyNow());
1891 bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout);
1892 typename Helper::steady_time_point after(Helper::steadyNow());
1893
1894 checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
1895}
1896
1897template <typename Helper>
1898void testSyncPriorityQueuePullUntilSteady(const long long jumpMs)
1899{
1900 boost::sync_priority_queue<int> q;
1901 int i;
1902
1903 typename Helper::steady_time_point before(Helper::steadyNow());
1904 bool timeout = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::timeout);
1905 typename Helper::steady_time_point after(Helper::steadyNow());
1906
1907 checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
1908}
1909
1910template <typename Helper>
1911void testSyncPriorityQueuePullUntilSystem(const long long jumpMs)
1912{
1913 boost::sync_priority_queue<int> q;
1914 int i;
1915
1916 typename Helper::steady_time_point before(Helper::steadyNow());
1917 bool timeout = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::timeout);
1918 typename Helper::steady_time_point after(Helper::steadyNow());
1919
1920 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
1921}
1922
1923template <typename Helper>
1924void testSyncPriorityQueuePullUntilCustom(const long long jumpMs)
1925{
1926 boost::sync_priority_queue<int> q;
1927 int i;
1928
1929 typename Helper::steady_time_point before(Helper::steadyNow());
1930 bool timeout = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::timeout);
1931 typename Helper::steady_time_point after(Helper::steadyNow());
1932
1933 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
1934}
1935
1936//--------------------------------------
1937
1938// Only Boost supports sync_priority_queue
1939
1940template <typename Helper>
1941void testSyncPriorityQueueBoost(const std::string& name)
1942{
1943 std::cout << std::endl;
1944 runTestWithNone<Helper>(testSyncPriorityQueuePullFor <Helper>, name + "::pull_for()");
1945 runTestWithNone<Helper>(testSyncPriorityQueuePullUntilSteady<Helper>, name + "::pull_until(), steady time");
1946 runTestWithNone<Helper>(testSyncPriorityQueuePullUntilSystem<Helper>, name + "::pull_until(), system time");
1947 runTestWithNone<Helper>(testSyncPriorityQueuePullUntilCustom<Helper>, name + "::pull_until(), custom time");
1948}
1949
1950/******************************************************************************/
1951
1952// Test Sync Timed Queue
1953
1954template <typename Helper>
1955void testSyncTimedQueuePullForEmptySteady(const long long jumpMs)
1956{
1957 boost::sync_timed_queue<int, typename Helper::steady_clock> q;
1958 int i;
1959
1960 typename Helper::steady_time_point before(Helper::steadyNow());
1961 bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout);
1962 typename Helper::steady_time_point after(Helper::steadyNow());
1963
1964 checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
1965}
1966
1967template <typename Helper>
1968void testSyncTimedQueuePullForEmptySystem(const long long jumpMs)
1969{
1970 boost::sync_timed_queue<int, typename Helper::system_clock> q;
1971 int i;
1972
1973 typename Helper::steady_time_point before(Helper::steadyNow());
1974 bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout);
1975 typename Helper::steady_time_point after(Helper::steadyNow());
1976
1977 checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
1978}
1979
1980template <typename Helper>
1981void testSyncTimedQueuePullForEmptyCustom(const long long jumpMs)
1982{
1983 boost::sync_timed_queue<int, typename Helper::custom_clock> q;
1984 int i;
1985
1986 typename Helper::steady_time_point before(Helper::steadyNow());
1987 bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout);
1988 typename Helper::steady_time_point after(Helper::steadyNow());
1989
1990 checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
1991}
1992
1993template <typename Helper>
1994void testSyncTimedQueuePullUntilEmptySteady(const long long jumpMs)
1995{
1996 boost::sync_timed_queue<int, typename Helper::steady_clock> q;
1997 int i;
1998
1999 typename Helper::steady_time_point before(Helper::steadyNow());
2000 bool timeout = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::timeout);
2001 typename Helper::steady_time_point after(Helper::steadyNow());
2002
2003 checkWaitTime<Helper>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout);
2004}
2005
2006template <typename Helper>
2007void testSyncTimedQueuePullUntilEmptySystem(const long long jumpMs)
2008{
2009 boost::sync_timed_queue<int, typename Helper::system_clock> q;
2010 int i;
2011
2012 typename Helper::steady_time_point before(Helper::steadyNow());
2013 bool timeout = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::timeout);
2014 typename Helper::steady_time_point after(Helper::steadyNow());
2015
2016 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
2017}
2018
2019template <typename Helper>
2020void testSyncTimedQueuePullUntilEmptyCustom(const long long jumpMs)
2021{
2022 boost::sync_timed_queue<int, typename Helper::custom_clock> q;
2023 int i;
2024
2025 typename Helper::steady_time_point before(Helper::steadyNow());
2026 bool timeout = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::timeout);
2027 typename Helper::steady_time_point after(Helper::steadyNow());
2028
2029 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout);
2030}
2031
2032//--------------------------------------
2033
2034template <typename Helper>
2035void testSyncTimedQueuePullForNotReadySteady(const long long jumpMs)
2036{
2037 boost::sync_timed_queue<int, typename Helper::steady_clock> q;
2038 q.push(0, typename Helper::milliseconds(10000)); // a long time
2039 int i;
2040
2041 typename Helper::steady_time_point before(Helper::steadyNow());
2042 bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready);
2043 typename Helper::steady_time_point after(Helper::steadyNow());
2044
2045 checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad);
2046}
2047
2048template <typename Helper>
2049void testSyncTimedQueuePullForNotReadySystem(const long long jumpMs)
2050{
2051 boost::sync_timed_queue<int, typename Helper::system_clock> q;
2052 q.push(0, typename Helper::milliseconds(10000)); // a long time
2053 int i;
2054
2055 typename Helper::steady_time_point before(Helper::steadyNow());
2056 bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready);
2057 typename Helper::steady_time_point after(Helper::steadyNow());
2058
2059 checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad);
2060}
2061
2062template <typename Helper>
2063void testSyncTimedQueuePullForNotReadyCustom(const long long jumpMs)
2064{
2065 boost::sync_timed_queue<int, typename Helper::custom_clock> q;
2066 q.push(0, typename Helper::milliseconds(10000)); // a long time
2067 int i;
2068
2069 typename Helper::steady_time_point before(Helper::steadyNow());
2070 bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready);
2071 typename Helper::steady_time_point after(Helper::steadyNow());
2072
2073 checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad);
2074}
2075
2076template <typename Helper>
2077void testSyncTimedQueuePullUntilNotReadySteady(const long long jumpMs)
2078{
2079 boost::sync_timed_queue<int, typename Helper::steady_clock> q;
2080 q.push(0, typename Helper::milliseconds(10000)); // a long time
2081 int i;
2082
2083 typename Helper::steady_time_point before(Helper::steadyNow());
2084 bool notReady = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready);
2085 typename Helper::steady_time_point after(Helper::steadyNow());
2086
2087 checkWaitTime<Helper>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad);
2088}
2089
2090template <typename Helper>
2091void testSyncTimedQueuePullUntilNotReadySystem(const long long jumpMs)
2092{
2093 boost::sync_timed_queue<int, typename Helper::system_clock> q;
2094 q.push(0, typename Helper::milliseconds(10000)); // a long time
2095 int i;
2096
2097 typename Helper::steady_time_point before(Helper::steadyNow());
2098 bool notReady = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready);
2099 typename Helper::steady_time_point after(Helper::steadyNow());
2100
2101 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, notReady ? e_not_ready_good : e_ready_bad);
2102}
2103
2104template <typename Helper>
2105void testSyncTimedQueuePullUntilNotReadyCustom(const long long jumpMs)
2106{
2107 boost::sync_timed_queue<int, typename Helper::custom_clock> q;
2108 q.push(0, typename Helper::milliseconds(10000)); // a long time
2109 int i;
2110
2111 typename Helper::steady_time_point before(Helper::steadyNow());
2112 bool notReady = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready);
2113 typename Helper::steady_time_point after(Helper::steadyNow());
2114
2115 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, notReady ? e_not_ready_good : e_ready_bad);
2116}
2117
2118//--------------------------------------
2119
2120template <typename Helper>
2121void testSyncTimedQueuePullForSucceedsSteady(const long long jumpMs)
2122{
2123 boost::sync_timed_queue<int, typename Helper::steady_clock> q;
2124 q.push(0, Helper::waitDur);
2125 int i;
2126
2127 typename Helper::steady_time_point before(Helper::steadyNow());
2128 bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success);
2129 typename Helper::steady_time_point after(Helper::steadyNow());
2130
2131 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad);
2132}
2133
2134template <typename Helper>
2135void testSyncTimedQueuePullForSucceedsSystem(const long long jumpMs)
2136{
2137 boost::sync_timed_queue<int, typename Helper::system_clock> q;
2138 q.push(0, Helper::waitDur);
2139 int i;
2140
2141 typename Helper::steady_time_point before(Helper::steadyNow());
2142 bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success);
2143 typename Helper::steady_time_point after(Helper::steadyNow());
2144
2145 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad);
2146}
2147
2148template <typename Helper>
2149void testSyncTimedQueuePullForSucceedsCustom(const long long jumpMs)
2150{
2151 boost::sync_timed_queue<int, typename Helper::custom_clock> q;
2152 q.push(0, Helper::waitDur);
2153 int i;
2154
2155 typename Helper::steady_time_point before(Helper::steadyNow());
2156 bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success);
2157 typename Helper::steady_time_point after(Helper::steadyNow());
2158
2159 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad);
2160}
2161
2162template <typename Helper>
2163void testSyncTimedQueuePullUntilSucceedsSteady(const long long jumpMs)
2164{
2165 boost::sync_timed_queue<int, typename Helper::steady_clock> q;
2166 q.push(0, Helper::steadyNow() + Helper::waitDur);
2167 int i;
2168
2169 typename Helper::steady_time_point before(Helper::steadyNow());
2170 bool succeeded = (q.pull_until(Helper::steadyNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success);
2171 typename Helper::steady_time_point after(Helper::steadyNow());
2172
2173 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad);
2174}
2175
2176template <typename Helper>
2177void testSyncTimedQueuePullUntilSucceedsSystem(const long long jumpMs)
2178{
2179 boost::sync_timed_queue<int, typename Helper::system_clock> q;
2180 q.push(0, Helper::systemNow() + Helper::waitDur);
2181 int i;
2182
2183 typename Helper::steady_time_point before(Helper::steadyNow());
2184 bool succeeded = (q.pull_until(Helper::systemNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success);
2185 typename Helper::steady_time_point after(Helper::steadyNow());
2186
2187 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad);
2188}
2189
2190template <typename Helper>
2191void testSyncTimedQueuePullUntilSucceedsCustom(const long long jumpMs)
2192{
2193 boost::sync_timed_queue<int, typename Helper::custom_clock> q;
2194 q.push(0, Helper::customNow() + Helper::waitDur);
2195 int i;
2196
2197 typename Helper::steady_time_point before(Helper::steadyNow());
2198 bool succeeded = (q.pull_until(Helper::customNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success);
2199 typename Helper::steady_time_point after(Helper::steadyNow());
2200
2201 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad);
2202}
2203
2204//--------------------------------------
2205
2206template <typename Helper>
2207void testSyncTimedQueueWaitPullSucceedsSteady(const long long jumpMs)
2208{
2209 boost::sync_timed_queue<int, typename Helper::steady_clock> q;
2210 q.push(0, Helper::steadyNow() + Helper::waitDur);
2211 int i;
2212
2213 typename Helper::steady_time_point before(Helper::steadyNow());
2214 bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success);
2215 typename Helper::steady_time_point after(Helper::steadyNow());
2216
2217 checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad);
2218}
2219
2220template <typename Helper>
2221void testSyncTimedQueueWaitPullSucceedsSystem(const long long jumpMs)
2222{
2223 boost::sync_timed_queue<int, typename Helper::system_clock> q;
2224 q.push(0, Helper::systemNow() + Helper::waitDur);
2225 int i;
2226
2227 typename Helper::steady_time_point before(Helper::steadyNow());
2228 bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success);
2229 typename Helper::steady_time_point after(Helper::steadyNow());
2230
2231 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad);
2232}
2233
2234template <typename Helper>
2235void testSyncTimedQueueWaitPullSucceedsCustom(const long long jumpMs)
2236{
2237 boost::sync_timed_queue<int, typename Helper::custom_clock> q;
2238 q.push(0, Helper::customNow() + Helper::waitDur);
2239 int i;
2240
2241 typename Helper::steady_time_point before(Helper::steadyNow());
2242 bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success);
2243 typename Helper::steady_time_point after(Helper::steadyNow());
2244
2245 checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad);
2246}
2247
2248//--------------------------------------
2249
2250// Only Boost supports sync_timed_queue
2251
2252template <typename Helper>
2253void testSyncTimedQueueBoost(const std::string& name)
2254{
2255 std::cout << std::endl;
2256 runTestWithNone<Helper>(testSyncTimedQueuePullForEmptySteady <Helper>, name + "::pull_for(), empty, steady time");
2257 runTestWithNone<Helper>(testSyncTimedQueuePullForEmptySystem <Helper>, name + "::pull_for(), empty, system time");
2258 runTestWithNone<Helper>(testSyncTimedQueuePullForEmptyCustom <Helper>, name + "::pull_for(), empty, custom time");
2259 runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptySteady<Helper>, name + "::pull_until(), empty, steady time");
2260 runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptySystem<Helper>, name + "::pull_until(), empty, system time");
2261 runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptyCustom<Helper>, name + "::pull_until(), empty, custom time");
2262
2263 std::cout << std::endl;
2264 runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadySteady <Helper>, name + "::pull_for(), not ready, steady time");
2265 runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadySystem <Helper>, name + "::pull_for(), not ready, system time");
2266 runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadyCustom <Helper>, name + "::pull_for(), not ready, custom time");
2267 runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadySteady<Helper>, name + "::pull_until(), not ready, steady time");
2268 runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadySystem<Helper>, name + "::pull_until(), not ready, system time");
2269 runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadyCustom<Helper>, name + "::pull_until(), not ready, custom time");
2270
2271 std::cout << std::endl;
2272 runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsSteady <Helper>, name + "::pull_for(), succeeds, steady time");
2273 runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsSystem <Helper>, name + "::pull_for(), succeeds, system time");
2274 runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsCustom <Helper>, name + "::pull_for(), succeeds, custom time");
2275 runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsSteady<Helper>, name + "::pull_until(), succeeds, steady time");
2276 runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsSystem<Helper>, name + "::pull_until(), succeeds, system time");
2277 runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsCustom<Helper>, name + "::pull_until(), succeeds, custom time");
2278
2279 std::cout << std::endl;
2280 runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsSteady<Helper>, name + "::wait_pull(), succeeds, steady time");
2281 runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsSystem<Helper>, name + "::wait_pull(), succeeds, system time");
2282 runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsCustom<Helper>, name + "::wait_pull(), succeeds, custom time");
2283}
2284
2285/******************************************************************************/
2286
2287int main()
2288{
2289 std::cout << std::endl;
2290 std::cout << "INFO: This test requires root/Administrator privileges in order to change the system clock." << std::endl;
2291 std::cout << "INFO: Disable NTP while running this test to prevent NTP from changing the system clock." << std::endl;
2292 std::cout << std::endl;
2293
2294 std::cout << "BOOST_HAS_PTHREAD_DELAY_NP: ";
2295#ifdef BOOST_HAS_PTHREAD_DELAY_NP
2296 std::cout << "YES" << std::endl;
2297#else
2298 std::cout << "NO" << std::endl;
2299#endif
2300
2301 std::cout << "BOOST_HAS_NANOSLEEP: ";
2302#ifdef BOOST_HAS_NANOSLEEP
2303 std::cout << "YES" << std::endl;
2304#else
2305 std::cout << "NO" << std::endl;
2306#endif
2307
2308 std::cout << "BOOST_THREAD_SLEEP_FOR_IS_STEADY: ";
2309#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY
2310 std::cout << "YES" << std::endl;
2311#else
2312 std::cout << "NO" << std::endl;
2313#endif
2314
2315 std::cout << "CLOCK_MONOTONIC: ";
2316#ifdef CLOCK_MONOTONIC
2317 std::cout << "YES" << std::endl;
2318#else
2319 std::cout << "NO" << std::endl;
2320#endif
2321
2322 std::cout << "BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN: ";
2323#ifdef BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN
2324 std::cout << "YES" << std::endl;
2325#else
2326 std::cout << "NO" << std::endl;
2327#endif
2328
2329 std::cout << "BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS: ";
2330#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
2331 std::cout << "YES" << std::endl;
2332#else
2333 std::cout << "NO" << std::endl;
2334#endif
2335
2336 std::cout << "BOOST_THREAD_V2_SHARED_MUTEX: ";
2337#ifdef BOOST_THREAD_V2_SHARED_MUTEX
2338 std::cout << "YES" << std::endl;
2339#else
2340 std::cout << "NO" << std::endl;
2341#endif
2342
2343 std::cout << "BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC: ";
2344#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
2345 std::cout << "YES" << std::endl;
2346#else
2347 std::cout << "NO" << std::endl;
2348#endif
2349
2350 std::cout << std::endl;
2351 std::cout << "Wait Time: " << s_waitMs << " ms" << std::endl;
2352 std::cout << "Short Jump Time: " << s_shortJumpMs << " ms" << std::endl;
2353 std::cout << "Long Jump Time: " << s_longJumpMs << " ms" << std::endl;
2354 std::cout << "Sleep Before Jump Time: " << s_sleepBeforeJumpMs << " ms" << std::endl;
2355 std::cout << "Max Early Error: " << s_maxEarlyErrorMs << " ms" << std::endl;
2356 std::cout << "Max Late Error: " << s_maxLateErrorMs << " ms" << std::endl;
2357
2358 testSleepBoost <BoostHelper< > >(name: "boost");
2359 testSleepNoIntBoost <BoostHelper< > >(name: "boost");
2360 testSleepNoThreadBoost <BoostHelper< > >(name: "boost");
2361 testSleepNoThreadNoIntBoost<BoostHelper< > >(name: "boost");
2362 testJoinBoost <BoostHelper< > >(name: "boost");
2363 testCondVarBoost <BoostHelper<boost::mutex, boost::condition_variable > >(name: "boost::condition_variable");
2364 testCondVarPredBoost <BoostHelper<boost::mutex, boost::condition_variable > >(name: "boost::condition_variable");
2365 testCondVarBoost <BoostHelper<boost::mutex, boost::condition_variable_any> >(name: "boost::condition_variable_any");
2366 testCondVarPredBoost <BoostHelper<boost::mutex, boost::condition_variable_any> >(name: "boost::condition_variable_any");
2367 testMutexBoost <BoostHelper<boost::timed_mutex > >(name: "boost::timed_mutex");
2368 testMutexBoost <BoostHelper<boost::recursive_timed_mutex > >(name: "boost::recursive_timed_mutex");
2369 testMutexBoost <BoostHelper<boost::shared_mutex > >(name: "boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex
2370 testMutexSharedBoost <BoostHelper<boost::shared_mutex > >(name: "boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex
2371 testMutexUpgradeBoost <BoostHelper<boost::shared_mutex > >(name: "boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex
2372 testFutureBoost <BoostHelper< > >(name: "boost::future");
2373 testSharedFutureBoost <BoostHelper< > >(name: "boost::shared_future");
2374 testSyncPriorityQueueBoost <BoostHelper< > >(name: "boost::sync_priority_queue");
2375 testSyncTimedQueueBoost <BoostHelper< > >(name: "boost::sync_timed_queue");
2376
2377#ifdef TEST_CPP14_FEATURES
2378 testSleepStd <StdHelper< > >("std");
2379 testSleepNoThreadStd<StdHelper< > >("std");
2380 testCondVarStd <StdHelper<std::mutex, std::condition_variable > >("std::condition_variable");
2381 testCondVarPredStd <StdHelper<std::mutex, std::condition_variable > >("std::condition_variable");
2382 testCondVarStd <StdHelper<std::mutex, std::condition_variable_any> >("std::condition_variable_any");
2383 testCondVarPredStd <StdHelper<std::mutex, std::condition_variable_any> >("std::condition_variable_any");
2384 testMutexStd <StdHelper<std::timed_mutex > >("std::timed_mutex");
2385 testMutexStd <StdHelper<std::recursive_timed_mutex > >("std::recursive_timed_mutex");
2386 testMutexStd <StdHelper<std::shared_timed_mutex > >("std::shared_timed_mutex");
2387 testMutexSharedStd <StdHelper<std::shared_timed_mutex > >("std::shared_timed_mutex");
2388 testFutureStd <StdHelper< > >("std::future");
2389 testSharedFutureStd <StdHelper< > >("std::shared_future");
2390#endif
2391
2392 std::cout << std::endl;
2393 std::cout << "Number of Tests Run: " << g_numTestsRun << std::endl;
2394 std::cout << "Number of Tests Passed: " << g_numTestsPassed << std::endl;
2395 std::cout << "Number of Tests Failed: " << g_numTestsFailed << std::endl;
2396
2397 return 0;
2398}
2399

source code of boost/libs/thread/test/test_time_jumps.cpp