#ifdef _WIN32 #include #else #include #endif #include "boost/bind.hpp" #include "boost/chrono.hpp" #include "boost/chrono/ceil.hpp" #include "boost/date_time.hpp" #include "boost/thread/concurrent_queues/sync_priority_queue.hpp" #include "boost/thread/concurrent_queues/sync_timed_queue.hpp" #include "boost/thread/future.hpp" #include "boost/thread/mutex.hpp" #include "boost/thread/recursive_mutex.hpp" #include "boost/thread/shared_lock_guard.hpp" #include "boost/thread/shared_mutex.hpp" #include "boost/thread/thread.hpp" #include #ifdef TEST_CPP14_FEATURES #include #include #include #include #endif /******************************************************************************/ /* * Summary: * * This code tests the behavior of time-related functions in the presence of * system clock changes (jumps). It requires root/Administrator privileges in * order to run because it changes the system clock. NTP should also be disabled * while running this code so that NTP can't change the system clock. * * Each function to be tested is executed five times. The amount of time the * function waits before returning is measured against the amount of time the * function was expected to wait. If the difference exceeds a threshold value * (defined below) then the test fails. * * The following values are intentially: * - more than 200 milliseconds * - more than 200 milliseconds apart * - not a multiple of 100 milliseconds * - not a multiple of each other * - don't sum or diff to a multiple of 100 milliseconds */ const long long s_waitMs = 580; const long long s_shortJumpMs = 230; const long long s_longJumpMs = 870; // Causes additional, unavoidable failures when BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC is disabled const long long s_sleepBeforeJumpMs = 110; #ifdef _WIN32 const long long s_maxEarlyErrorMs = 10 + 100; // Windows is unpredictable, especially in a VM, so allow extra time if the function returns early const long long s_maxLateErrorMs = 110 // due to polling, functions may not return for up to 100 milliseconds after they are supposed to + 100; // Windows is slow, especially in a VM, so allow extra time for the functions to return #else const long long s_maxEarlyErrorMs = 10; const long long s_maxLateErrorMs = 110; // Due to polling, functions may not return for up to 100 milliseconds after they are supposed to #endif int g_numTestsRun = 0; int g_numTestsPassed = 0; int g_numTestsFailed = 0; /******************************************************************************/ // A custom clock based off the system clock but with a different epoch. namespace custom { class custom_boost_clock { public: typedef boost::chrono::microseconds duration; // intentionally not nanoseconds typedef duration::rep rep; typedef duration::period period; typedef boost::chrono::time_point time_point; static bool is_steady; static time_point now(); }; bool custom_boost_clock::is_steady = false; custom_boost_clock::time_point custom_boost_clock::now() { return time_point(boost::chrono::ceil(boost::chrono::system_clock::now().time_since_epoch()) - boost::chrono::hours(10 * 365 * 24)); } #ifdef TEST_CPP14_FEATURES class custom_std_clock { public: typedef std::chrono::microseconds duration; // intentionally not nanoseconds typedef duration::rep rep; typedef duration::period period; typedef std::chrono::time_point time_point; static bool is_steady; static time_point now(); }; bool custom_std_clock::is_steady = false; custom_std_clock::time_point custom_std_clock::now() { return time_point(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) - std::chrono::hours(10 * 365 * 24)); } #endif } /******************************************************************************/ template struct BoostHelper { typedef MutexType mutex; typedef CondType cond; typedef boost::lock_guard lock_guard; typedef boost::unique_lock unique_lock; typedef boost::chrono::milliseconds milliseconds; typedef boost::chrono::nanoseconds nanoseconds; typedef boost::chrono::system_clock system_clock; typedef boost::chrono::steady_clock steady_clock; typedef custom::custom_boost_clock custom_clock; typedef system_clock::time_point system_time_point; typedef steady_clock::time_point steady_time_point; typedef custom_clock::time_point custom_time_point; typedef boost::cv_status cv_status; typedef boost::future_status future_status; typedef boost::packaged_task packaged_task; typedef boost::future future; typedef boost::shared_future shared_future; typedef boost::thread thread; static const milliseconds waitDur; template static void sleep_for(T d) { boost::this_thread::sleep_for(d); } template static void sleep_for_no_int(T d) { boost::this_thread::no_interruption_point::sleep_for(d); } template static void sleep_until(T t) { boost::this_thread::sleep_until(t); } template static void sleep_until_no_int(T t) { boost::this_thread::no_interruption_point::sleep_until(t); } static system_time_point systemNow() { return system_clock::now(); } static steady_time_point steadyNow() { return steady_clock::now(); } static custom_time_point customNow() { return custom_clock::now(); } template static ToDuration duration_cast(const boost::chrono::duration& d) { return boost::chrono::duration_cast(d); } static milliseconds zero() { return milliseconds(0); } }; template const typename BoostHelper::milliseconds BoostHelper::waitDur = typename BoostHelper::milliseconds(s_waitMs); #ifdef TEST_CPP14_FEATURES template struct StdHelper { typedef MutexType mutex; typedef CondType cond; typedef std::lock_guard lock_guard; typedef std::unique_lock unique_lock; typedef std::chrono::milliseconds milliseconds; typedef std::chrono::nanoseconds nanoseconds; typedef std::chrono::system_clock system_clock; typedef std::chrono::steady_clock steady_clock; typedef custom::custom_std_clock custom_clock; typedef system_clock::time_point system_time_point; typedef steady_clock::time_point steady_time_point; typedef custom_clock::time_point custom_time_point; typedef std::cv_status cv_status; typedef std::future_status future_status; typedef std::packaged_task packaged_task; typedef std::future future; typedef std::shared_future shared_future; typedef std::thread thread; static const milliseconds waitDur; template static void sleep_for(T d) { std::this_thread::sleep_for(d); } template static void sleep_until(T t) { std::this_thread::sleep_until(t); } static system_time_point systemNow() { return system_clock::now(); } static steady_time_point steadyNow() { return steady_clock::now(); } static custom_time_point customNow() { return custom_clock::now(); } template static ToDuration duration_cast(const std::chrono::duration& d) { return std::chrono::duration_cast(d); } static milliseconds zero() { return milliseconds(0); } }; template const typename StdHelper::milliseconds StdHelper::waitDur = typename StdHelper::milliseconds(s_waitMs); #endif /******************************************************************************/ #ifdef _WIN32 void changeSystemTime(long long changeMs) { Sleep(s_sleepBeforeJumpMs); SYSTEMTIME systemTime; GetSystemTime(&systemTime); FILETIME fileTime; if (!SystemTimeToFileTime(&systemTime, &fileTime)) { std::cout << "ERROR: Couldn't convert system time to file time" << std::endl; } ULARGE_INTEGER largeInt; largeInt.LowPart = fileTime.dwLowDateTime; largeInt.HighPart = fileTime.dwHighDateTime; largeInt.QuadPart += changeMs * 10000; fileTime.dwLowDateTime = largeInt.LowPart; fileTime.dwHighDateTime = largeInt.HighPart; if (!FileTimeToSystemTime(&fileTime, &systemTime)) { std::cout << "ERROR: Couldn't convert file time to system time" << std::endl; } if (!SetSystemTime(&systemTime)) { std::cout << "ERROR: Couldn't set system time" << std::endl; } } #else void changeSystemTime(long long changeMs) { struct timespec sleepTs; sleepTs.tv_sec = (s_sleepBeforeJumpMs / 1000); sleepTs.tv_nsec = (s_sleepBeforeJumpMs % 1000) * 1000000; nanosleep(&sleepTs, NULL); struct timeval tv; if (gettimeofday(&tv, NULL) != 0) { std::cout << "ERROR: Couldn't get system time" << std::endl; } changeMs += tv.tv_sec * 1000; changeMs += tv.tv_usec / 1000; tv.tv_sec = (changeMs / 1000); tv.tv_usec = (changeMs % 1000) * 1000; if (settimeofday(&tv, NULL) != 0) { std::cout << "ERROR: Couldn't set system time" << std::endl; } } #endif enum RcEnum { e_no_timeout, e_timeout, e_failed_bad, e_failed_good, e_succeeded_bad, e_succeeded_good, e_ready_bad, e_not_ready_good, e_na }; template void checkWaitTime(typename Helper::nanoseconds expected, typename Helper::nanoseconds actual, RcEnum rc) { if (expected != Helper::zero() && expected < typename Helper::milliseconds(s_sleepBeforeJumpMs)) { expected = typename Helper::milliseconds(s_sleepBeforeJumpMs); } typename Helper::milliseconds expectedMs = Helper::template duration_cast(expected); typename Helper::milliseconds actualMs = Helper::template duration_cast(actual); std::cout << "Expected: " << std::setw(4) << expectedMs.count() << " ms" << ", Actual: " << std::setw(4) << actualMs.count() << " ms" << ", Returned: "; switch (rc) { case e_no_timeout : std::cout << "no_timeout, "; break; case e_timeout : std::cout << "timeout, "; break; case e_failed_bad : std::cout << "failed, "; break; case e_failed_good : std::cout << "failed, "; break; case e_succeeded_bad : std::cout << "succeeded, "; break; case e_succeeded_good : std::cout << "succeeded, "; break; case e_ready_bad : std::cout << "ready, "; break; case e_not_ready_good : std::cout << "not_ready, "; break; default : std::cout << "N/A, "; break; } if (expectedMs == Helper::zero()) { std::cout << "FAILED: SKIPPED (test would lock up if run)"; g_numTestsFailed++; } else if (actual < expected - typename Helper::milliseconds(s_maxEarlyErrorMs)) { std::cout << "FAILED: TOO SHORT"; if (rc == e_timeout) // bad { std::cout << ", RETURNED TIMEOUT"; } else if (rc == e_failed_bad) { std::cout << ", RETURNED FAILED"; } else if (rc == e_succeeded_bad) { std::cout << ", RETURNED SUCCEEDED"; } else if (rc == e_ready_bad) { std::cout << ", RETURNED READY"; } g_numTestsFailed++; } else if (actual > expected + typename Helper::milliseconds(s_maxLateErrorMs)) { std::cout << "FAILED: TOO LONG"; if (rc == e_no_timeout) // bad { std::cout << ", RETURNED NO_TIMEOUT"; } else if (rc == e_failed_bad) { std::cout << ", RETURNED FAILED"; } else if (rc == e_succeeded_bad) { std::cout << ", RETURNED SUCCEEDED"; } else if (rc == e_ready_bad) { std::cout << ", RETURNED READY"; } g_numTestsFailed++; } else if (rc == e_no_timeout) // bad { std::cout << "FAILED: RETURNED NO_TIMEOUT"; g_numTestsFailed++; } else if (rc == e_failed_bad) { std::cout << "FAILED: RETURNED FAILED"; g_numTestsFailed++; } else if (rc == e_succeeded_bad) { std::cout << "FAILED: RETURNED SUCCEEDED"; g_numTestsFailed++; } else if (rc == e_ready_bad) { std::cout << "FAILED: RETURNED READY"; g_numTestsFailed++; } else { std::cout << "Passed"; g_numTestsPassed++; } std::cout << std::endl; g_numTestsRun++; } void sleepForLongTime() { #ifdef _WIN32 Sleep(10000); #else struct timespec ts = {5, 0}; nanosleep(&ts, NULL); #endif } bool returnFalse() { return false; } /******************************************************************************/ // Run the test in the context provided, which may be the current thread or a separate thread. template void runTestInContext(Context context, Function func, const std::string name) { std::cout << name << ":" << std::endl; { std::cout << " While system clock remains stable: "; context(func, 0); } { std::cout << " While system clock jumps back (short): "; typename Helper::thread t(boost::bind(changeSystemTime, -s_shortJumpMs)); context(func, -s_shortJumpMs); t.join(); } { std::cout << " While system clock jumps back (long): "; typename Helper::thread t(boost::bind(changeSystemTime, -s_longJumpMs)); context(func, -s_longJumpMs); t.join(); } { std::cout << " While system clock jumps forward (short): "; typename Helper::thread t(boost::bind(changeSystemTime, s_shortJumpMs)); context(func, s_shortJumpMs); t.join(); } { std::cout << " While system clock jumps forward (long): "; typename Helper::thread t(boost::bind(changeSystemTime, s_longJumpMs)); context(func, s_longJumpMs); t.join(); } } //-------------------------------------- template void noThreadContext(Function func, const long long jumpMs) { func(jumpMs); } template void threadContextWithNone(Function func, const long long jumpMs) { typename Helper::thread t(boost::bind(func, jumpMs)); t.join(); } template void threadContextWithUnique(Function func, const long long jumpMs) { typename Helper::mutex m; typename Helper::lock_guard g(m); typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs)); t.join(); } template void threadContextWithShared(Function func, const long long jumpMs) { typename Helper::mutex m; boost::shared_lock_guard g(m); typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs)); t.join(); } template void threadContextWithUpgrade(Function func, const long long jumpMs) { typename Helper::mutex m; boost::upgrade_lock g(m); typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs)); t.join(); } //-------------------------------------- // Run the test in the current thread. template void runTest(Function func, const std::string name) { runTestInContext(noThreadContext, func, name); } // Run the test in a separate thread. template void runTestWithNone(Function func, const std::string name) { runTestInContext(threadContextWithNone, func, name); } // Run the test in a separate thread. Pass a locked mutex to the function under test. template void runTestWithUnique(Function func, const std::string name) { runTestInContext(threadContextWithUnique, func, name); } // Run the test in a separate thread. Pass a shared-locked mutex to the function under test. template void runTestWithShared(Function func, const std::string name) { runTestInContext(threadContextWithShared, func, name); } // Run the test in a separate thread. Pass an upgrade-locked mutex to the function under test. template void runTestWithUpgrade(Function func, const std::string name) { runTestInContext(threadContextWithUpgrade, func, name); } /******************************************************************************/ // Test Sleep template void testSleepFor(const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); Helper::sleep_for(Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, e_na); } template void testSleepUntilSteady(const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); Helper::sleep_until(Helper::steadyNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, e_na); } template void testSleepUntilSystem(const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); Helper::sleep_until(Helper::systemNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); } template void testSleepUntilCustom(const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); Helper::sleep_until(Helper::customNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); } //-------------------------------------- template void testSleepRelative(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); boost::this_thread::sleep(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, e_na); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } template void testSleepAbsolute(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); boost::this_thread::sleep(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template void testSleepStd(const std::string& name) { std::cout << std::endl; runTestWithNone(testSleepFor , name + "::this_thread::sleep_for()"); runTestWithNone(testSleepUntilSteady, name + "::this_thread::sleep_until(), steady time"); runTestWithNone(testSleepUntilSystem, name + "::this_thread::sleep_until(), system time"); runTestWithNone(testSleepUntilCustom, name + "::this_thread::sleep_until(), custom time"); } template void testSleepBoost(const std::string& name) { testSleepStd(name); // Boost-only functions runTestWithNone(testSleepRelative, name + "::this_thread::sleep(), relative time"); runTestWithNone(testSleepAbsolute, name + "::this_thread::sleep(), absolute time"); } template void testSleepNoThreadStd(const std::string& name) { std::cout << std::endl; runTest(testSleepFor , name + "::this_thread::sleep_for(), no thread"); runTest(testSleepUntilSteady, name + "::this_thread::sleep_until(), no thread, steady time"); runTest(testSleepUntilSystem, name + "::this_thread::sleep_until(), no thread, system time"); runTest(testSleepUntilCustom, name + "::this_thread::sleep_until(), no thread, custom time"); } template void testSleepNoThreadBoost(const std::string& name) { testSleepNoThreadStd(name); // Boost-only functions runTest(testSleepRelative, name + "::this_thread::sleep(), no thread, relative time"); runTest(testSleepAbsolute, name + "::this_thread::sleep(), no thread, absolute time"); } /******************************************************************************/ // Test Sleep, No Interruption Point template void testSleepForNoInt(const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); Helper::sleep_for_no_int(Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, e_na); } template void testSleepUntilNoIntSteady(const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); Helper::sleep_until_no_int(Helper::steadyNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, e_na); } template void testSleepUntilNoIntSystem(const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); Helper::sleep_until_no_int(Helper::systemNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); } template void testSleepUntilNoIntCustom(const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); Helper::sleep_until_no_int(Helper::customNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); } //-------------------------------------- #ifndef SKIP_NO_INT_SLEEP template void testSleepNoIntRelative(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); boost::this_thread::no_interruption_point::sleep(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, e_na); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } template void testSleepNoIntAbsolute(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); boost::this_thread::no_interruption_point::sleep(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } #endif //-------------------------------------- // Only Boost supports no_interruption_point template void testSleepNoIntBoost(const std::string& name) { std::cout << std::endl; runTestWithNone(testSleepForNoInt , name + "::this_thread::no_interruption_point::sleep_for()"); runTestWithNone(testSleepUntilNoIntSteady, name + "::this_thread::no_interruption_point::sleep_until(), steady time"); runTestWithNone(testSleepUntilNoIntSystem, name + "::this_thread::no_interruption_point::sleep_until(), system time"); runTestWithNone(testSleepUntilNoIntCustom, name + "::this_thread::no_interruption_point::sleep_until(), custom time"); #ifndef SKIP_NO_INT_SLEEP runTestWithNone(testSleepNoIntRelative, name + "::this_thread::no_interruption_point::sleep(), relative time"); runTestWithNone(testSleepNoIntAbsolute, name + "::this_thread::no_interruption_point::sleep(), absolute time"); #endif } template void testSleepNoThreadNoIntBoost(const std::string& name) { std::cout << std::endl; runTest(testSleepForNoInt , name + "::this_thread::no_interruption_point::sleep_for(), no thread"); runTest(testSleepUntilNoIntSteady, name + "::this_thread::no_interruption_point::sleep_until(), no thread, steady time"); runTest(testSleepUntilNoIntSystem, name + "::this_thread::no_interruption_point::sleep_until(), no thread, system time"); runTest(testSleepUntilNoIntCustom, name + "::this_thread::no_interruption_point::sleep_until(), no thread, custom time"); #ifndef SKIP_NO_INT_SLEEP runTest(testSleepNoIntRelative, name + "::this_thread::no_interruption_point::sleep(), no thread, relative time"); runTest(testSleepNoIntAbsolute, name + "::this_thread::no_interruption_point::sleep(), no thread, absolute time"); #endif } /******************************************************************************/ // Test Try Join template void testTryJoinFor(const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); typename Helper::thread t3(sleepForLongTime); bool succeeded = t3.try_join_for(Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryJoinUntilSteady(const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); typename Helper::thread t3(sleepForLongTime); bool succeeded = t3.try_join_until(Helper::steadyNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryJoinUntilSystem(const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); typename Helper::thread t3(sleepForLongTime); bool succeeded = t3.try_join_until(Helper::systemNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryJoinUntilCustom(const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); typename Helper::thread t3(sleepForLongTime); bool succeeded = t3.try_join_until(Helper::customNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } //-------------------------------------- template void testTimedJoinRelative(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); typename Helper::thread t3(sleepForLongTime); bool succeeded = t3.timed_join(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } template void testTimedJoinAbsolute(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); typename Helper::thread t3(sleepForLongTime); bool succeeded = t3.timed_join(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- // Only Boost supports timed try_join functions template void testJoinBoost(const std::string& name) { std::cout << std::endl; runTestWithNone(testTryJoinFor , name + "::thread::try_join_for()"); runTestWithNone(testTryJoinUntilSteady, name + "::thread::try_join_until(), steady time"); runTestWithNone(testTryJoinUntilSystem, name + "::thread::try_join_until(), system time"); runTestWithNone(testTryJoinUntilCustom, name + "::thread::try_join_until(), custom time"); runTestWithNone(testTimedJoinRelative , name + "::thread::timed_join(), relative time"); runTestWithNone(testTimedJoinAbsolute , name + "::thread::timed_join(), absolute time"); } /******************************************************************************/ // Test Condition Variable Wait template void testCondVarWaitFor(const long long jumpMs) { typename Helper::cond cv; typename Helper::mutex m; typename Helper::unique_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool noTimeout = (cv.wait_for(g, Helper::waitDur) == Helper::cv_status::no_timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); } template void testCondVarWaitUntilSteady(const long long jumpMs) { typename Helper::cond cv; typename Helper::mutex m; typename Helper::unique_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool noTimeout = (cv.wait_until(g, Helper::steadyNow() + Helper::waitDur) == Helper::cv_status::no_timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); } template void testCondVarWaitUntilSystem(const long long jumpMs) { typename Helper::cond cv; typename Helper::mutex m; typename Helper::unique_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool noTimeout = (cv.wait_until(g, Helper::systemNow() + Helper::waitDur) == Helper::cv_status::no_timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); } template void testCondVarWaitUntilCustom(const long long jumpMs) { typename Helper::cond cv; typename Helper::mutex m; typename Helper::unique_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool noTimeout = (cv.wait_until(g, Helper::customNow() + Helper::waitDur) == Helper::cv_status::no_timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); } //-------------------------------------- template void testCondVarTimedWaitRelative(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::cond cv; typename Helper::mutex m; typename Helper::unique_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool noTimeout = cv.timed_wait(g, ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } template void testCondVarTimedWaitAbsolute(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::cond cv; typename Helper::mutex m; typename Helper::unique_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool noTimeout = cv.timed_wait(g, ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template void testCondVarStd(const std::string& name) { std::cout << std::endl; runTestWithNone(testCondVarWaitFor , name + "::wait_for()"); runTestWithNone(testCondVarWaitUntilSteady, name + "::wait_until(), steady time"); runTestWithNone(testCondVarWaitUntilSystem, name + "::wait_until(), system time"); runTestWithNone(testCondVarWaitUntilCustom, name + "::wait_until(), custom time"); } template void testCondVarBoost(const std::string& name) { testCondVarStd(name); // Boost-only functions runTestWithNone(testCondVarTimedWaitRelative, name + "::timed_wait(), relative time"); runTestWithNone(testCondVarTimedWaitAbsolute, name + "::timed_wait(), absolute time"); } /******************************************************************************/ // Test Condition Variable Wait with Predicate template void testCondVarWaitForPred(const long long jumpMs) { typename Helper::cond cv; typename Helper::mutex m; typename Helper::unique_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool noTimeout = cv.wait_for(g, Helper::waitDur, returnFalse); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); } template void testCondVarWaitUntilPredSteady(const long long jumpMs) { typename Helper::cond cv; typename Helper::mutex m; typename Helper::unique_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool noTimeout = cv.wait_until(g, Helper::steadyNow() + Helper::waitDur, returnFalse); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); } template void testCondVarWaitUntilPredSystem(const long long jumpMs) { typename Helper::cond cv; typename Helper::mutex m; typename Helper::unique_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool noTimeout = cv.wait_until(g, Helper::systemNow() + Helper::waitDur, returnFalse); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); } template void testCondVarWaitUntilPredCustom(const long long jumpMs) { typename Helper::cond cv; typename Helper::mutex m; typename Helper::unique_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool noTimeout = cv.wait_until(g, Helper::customNow() + Helper::waitDur, returnFalse); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); } //-------------------------------------- template void testCondVarTimedWaitPredRelative(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::cond cv; typename Helper::mutex m; typename Helper::unique_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool noTimeout = cv.timed_wait(g, ptDur, returnFalse); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } template void testCondVarTimedWaitPredAbsolute(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::cond cv; typename Helper::mutex m; typename Helper::unique_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool noTimeout = cv.timed_wait(g, ptNow + ptDur, returnFalse); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template void testCondVarPredStd(const std::string& name) { std::cout << std::endl; runTestWithNone(testCondVarWaitForPred , name + "::wait_for(), with predicate"); runTestWithNone(testCondVarWaitUntilPredSteady, name + "::wait_until(), with predicate, steady time"); runTestWithNone(testCondVarWaitUntilPredSystem, name + "::wait_until(), with predicate, system time"); runTestWithNone(testCondVarWaitUntilPredCustom, name + "::wait_until(), with predicate, custom time"); } template void testCondVarPredBoost(const std::string& name) { testCondVarPredStd(name); // Boost-only functions runTestWithNone(testCondVarTimedWaitPredRelative, name + "::timed_wait(), with predicate, relative time"); runTestWithNone(testCondVarTimedWaitPredAbsolute, name + "::timed_wait(), with predicate, absolute time"); } /******************************************************************************/ // Test Try Lock template void testTryLockFor(typename Helper::mutex& m, const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_lock_for(Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryLockUntilSteady(typename Helper::mutex& m, const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_lock_until(Helper::steadyNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryLockUntilSystem(typename Helper::mutex& m, const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_lock_until(Helper::systemNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryLockUntilCustom(typename Helper::mutex& m, const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_lock_until(Helper::customNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } //-------------------------------------- template void testTimedLockRelative(typename Helper::mutex& m, const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool succeeded = m.timed_lock(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } template void testTimedLockAbsolute(typename Helper::mutex& m, const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool succeeded = m.timed_lock(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template void testMutexStd(const std::string& name) { std::cout << std::endl; runTestWithUnique(testTryLockFor , name + "::try_lock_for()"); runTestWithUnique(testTryLockUntilSteady, name + "::try_lock_until(), steady time"); runTestWithUnique(testTryLockUntilSystem, name + "::try_lock_until(), system time"); runTestWithUnique(testTryLockUntilCustom, name + "::try_lock_until(), custom time"); } template void testMutexBoost(const std::string& name) { testMutexStd(name); // Boost-only functions runTestWithUnique(testTimedLockRelative, name + "::timed_lock(), relative time"); runTestWithUnique(testTimedLockAbsolute, name + "::timed_lock(), absolute time"); } /******************************************************************************/ // Test Try Lock Shared template void testTryLockSharedFor(typename Helper::mutex& m, const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_lock_shared_for(Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryLockSharedUntilSteady(typename Helper::mutex& m, const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_lock_shared_until(Helper::steadyNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryLockSharedUntilSystem(typename Helper::mutex& m, const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_lock_shared_until(Helper::systemNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryLockSharedUntilCustom(typename Helper::mutex& m, const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_lock_shared_until(Helper::customNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } //-------------------------------------- template void testTimedLockSharedRelative(typename Helper::mutex& m, const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool succeeded = m.timed_lock_shared(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } template void testTimedLockSharedAbsolute(typename Helper::mutex& m, const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool succeeded = m.timed_lock_shared(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template void testMutexSharedStd(const std::string& name) { std::cout << std::endl; runTestWithUnique(testTryLockSharedFor , name + "::try_lock_shared_for()"); runTestWithUnique(testTryLockSharedUntilSteady, name + "::try_lock_shared_until(), steady time"); runTestWithUnique(testTryLockSharedUntilSystem, name + "::try_lock_shared_until(), system time"); runTestWithUnique(testTryLockSharedUntilCustom, name + "::try_lock_shared_until(), custom time"); } template void testMutexSharedBoost(const std::string& name) { testMutexSharedStd(name); // Boost-only functions runTestWithUnique(testTimedLockSharedRelative, name + "::timed_lock_shared(), relative time"); runTestWithUnique(testTimedLockSharedAbsolute, name + "::timed_lock_shared(), absolute time"); } /******************************************************************************/ // Test Try Lock Upgrade #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS template void testTryLockUpgradeFor(typename Helper::mutex& m, const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_lock_upgrade_for(Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryLockUpgradeUntilSteady(typename Helper::mutex& m, const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_lock_upgrade_until(Helper::steadyNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryLockUpgradeUntilSystem(typename Helper::mutex& m, const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_lock_upgrade_until(Helper::systemNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryLockUpgradeUntilCustom(typename Helper::mutex& m, const long long jumpMs) { typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_lock_upgrade_until(Helper::customNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } //-------------------------------------- template void testTimedLockUpgradeRelative(typename Helper::mutex& m, const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool succeeded = m.timed_lock_upgrade(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } template void testTimedLockUpgradeAbsolute(typename Helper::mutex& m, const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool succeeded = m.timed_lock_upgrade(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template void testTryUnlockSharedAndLockFor(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_unlock_shared_and_lock_for(Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryUnlockSharedAndLockUntilSteady(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_unlock_shared_and_lock_until(Helper::steadyNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryUnlockSharedAndLockUntilSystem(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_unlock_shared_and_lock_until(Helper::systemNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryUnlockSharedAndLockUntilCustom(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_unlock_shared_and_lock_until(Helper::customNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } //-------------------------------------- template void testTryUnlockUpgradeAndLockFor(typename Helper::mutex& m, const long long jumpMs) { boost::upgrade_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_unlock_upgrade_and_lock_for(Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryUnlockUpgradeAndLockUntilSteady(typename Helper::mutex& m, const long long jumpMs) { boost::upgrade_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::steadyNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryUnlockUpgradeAndLockUntilSystem(typename Helper::mutex& m, const long long jumpMs) { boost::upgrade_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::systemNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryUnlockUpgradeAndLockUntilCustom(typename Helper::mutex& m, const long long jumpMs) { boost::upgrade_lock g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_unlock_upgrade_and_lock_until(Helper::customNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } //-------------------------------------- template void testTryUnlockSharedAndLockUpgradeFor(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_unlock_shared_and_lock_upgrade_for(Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryUnlockSharedAndLockUpgradeUntilSteady(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::steadyNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryUnlockSharedAndLockUpgradeUntilSystem(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::systemNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template void testTryUnlockSharedAndLockUpgradeUntilCustom(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard g(m); typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = m.try_unlock_shared_and_lock_upgrade_until(Helper::customNow() + Helper::waitDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } #endif //-------------------------------------- // Only Boost supports upgrade mutexes template void testMutexUpgradeBoost(const std::string& name) { #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS std::cout << std::endl; runTestWithUnique(testTryLockUpgradeFor , name + "::try_lock_upgrade_for()"); runTestWithUnique(testTryLockUpgradeUntilSteady, name + "::try_lock_upgrade_until(), steady time"); runTestWithUnique(testTryLockUpgradeUntilSystem, name + "::try_lock_upgrade_until(), system time"); runTestWithUnique(testTryLockUpgradeUntilCustom, name + "::try_lock_upgrade_until(), custom time"); runTestWithUnique(testTimedLockUpgradeRelative , name + "::timed_lock_upgrade(), relative time"); runTestWithUnique(testTimedLockUpgradeAbsolute , name + "::timed_lock_upgrade(), absolute time"); std::cout << std::endl; runTestWithShared(testTryUnlockSharedAndLockFor , name + "::try_unlock_shared_and_lock_for()"); runTestWithShared(testTryUnlockSharedAndLockUntilSteady, name + "::try_unlock_shared_and_lock_until(), steady time"); runTestWithShared(testTryUnlockSharedAndLockUntilSystem, name + "::try_unlock_shared_and_lock_until(), system time"); runTestWithShared(testTryUnlockSharedAndLockUntilCustom, name + "::try_unlock_shared_and_lock_until(), custom time"); std::cout << std::endl; runTestWithShared(testTryUnlockUpgradeAndLockFor , name + "::try_unlock_upgrade_and_lock_for()"); runTestWithShared(testTryUnlockUpgradeAndLockUntilSteady, name + "::try_unlock_upgrade_and_lock_until(), steady time"); runTestWithShared(testTryUnlockUpgradeAndLockUntilSystem, name + "::try_unlock_upgrade_and_lock_until(), system time"); runTestWithShared(testTryUnlockUpgradeAndLockUntilCustom, name + "::try_unlock_upgrade_and_lock_until(), custom time"); std::cout << std::endl; runTestWithUpgrade(testTryUnlockSharedAndLockFor , name + "::try_unlock_shared_and_lock_upgrade_for()"); runTestWithUpgrade(testTryUnlockSharedAndLockUntilSteady, name + "::try_unlock_shared_and_lock_upgrade_until(), steady time"); runTestWithUpgrade(testTryUnlockSharedAndLockUntilSystem, name + "::try_unlock_shared_and_lock_upgrade_until(), system time"); runTestWithUpgrade(testTryUnlockSharedAndLockUntilCustom, name + "::try_unlock_shared_and_lock_upgrade_until(), custom time"); #endif } /******************************************************************************/ // Test Future Wait template void testFutureWaitFor(const long long jumpMs) { typename Helper::packaged_task pt(returnFalse); typename Helper::future f = pt.get_future(); typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (f.wait_for(Helper::waitDur) == Helper::future_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template void testFutureWaitUntilSteady(const long long jumpMs) { typename Helper::packaged_task pt(returnFalse); typename Helper::future f = pt.get_future(); typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (f.wait_until(Helper::steadyNow() + Helper::waitDur) == Helper::future_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template void testFutureWaitUntilSystem(const long long jumpMs) { typename Helper::packaged_task pt(returnFalse); typename Helper::future f = pt.get_future(); typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (f.wait_until(Helper::systemNow() + Helper::waitDur) == Helper::future_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } template void testFutureWaitUntilCustom(const long long jumpMs) { typename Helper::packaged_task pt(returnFalse); typename Helper::future f = pt.get_future(); typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (f.wait_until(Helper::customNow() + Helper::waitDur) == Helper::future_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } //-------------------------------------- template void testFutureTimedWaitRelative(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::packaged_task pt(returnFalse); typename Helper::future f = pt.get_future(); typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool noTimeout = f.timed_wait(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } template void testFutureTimedWaitAbsolute(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::packaged_task pt(returnFalse); typename Helper::future f = pt.get_future(); typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool noTimeout = f.timed_wait_until(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template void testFutureStd(const std::string& name) { std::cout << std::endl; runTestWithNone(testFutureWaitFor , name + "::wait_for()"); runTestWithNone(testFutureWaitUntilSteady, name + "::wait_until(), steady time"); runTestWithNone(testFutureWaitUntilSystem, name + "::wait_until(), system time"); runTestWithNone(testFutureWaitUntilCustom, name + "::wait_until(), custom time"); } template void testFutureBoost(const std::string& name) { testFutureStd(name); // Boost-only functions runTestWithNone(testFutureTimedWaitRelative, name + "::timed_wait(), relative time"); runTestWithNone(testFutureTimedWaitAbsolute, name + "::timed_wait_until(), absolute time"); } /******************************************************************************/ // Test Shared Future Wait template void testSharedFutureWaitFor(const long long jumpMs) { typename Helper::packaged_task pt(returnFalse); typename Helper::future f = pt.get_future(); typename Helper::shared_future sf = boost::move(f); typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (sf.wait_for(Helper::waitDur) == Helper::future_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template void testSharedFutureWaitUntilSteady(const long long jumpMs) { typename Helper::packaged_task pt(returnFalse); typename Helper::future f = pt.get_future(); typename Helper::shared_future sf = boost::move(f); typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (sf.wait_until(Helper::steadyNow() + Helper::waitDur) == Helper::future_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template void testSharedFutureWaitUntilSystem(const long long jumpMs) { typename Helper::packaged_task pt(returnFalse); typename Helper::future f = pt.get_future(); typename Helper::shared_future sf = boost::move(f); typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (sf.wait_until(Helper::systemNow() + Helper::waitDur) == Helper::future_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } template void testSharedFutureWaitUntilCustom(const long long jumpMs) { typename Helper::packaged_task pt(returnFalse); typename Helper::future f = pt.get_future(); typename Helper::shared_future sf = boost::move(f); typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (sf.wait_until(Helper::customNow() + Helper::waitDur) == Helper::future_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } //-------------------------------------- template void testSharedFutureTimedWaitRelative(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::packaged_task pt(returnFalse); typename Helper::future f = pt.get_future(); typename Helper::shared_future sf = boost::move(f); typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool noTimeout = sf.timed_wait(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } template void testSharedFutureTimedWaitAbsolute(const long long jumpMs) { #ifndef SKIP_DATETIME_FUNCTIONS typename Helper::packaged_task pt(returnFalse); typename Helper::future f = pt.get_future(); typename Helper::shared_future sf = boost::move(f); typename Helper::steady_time_point before(Helper::steadyNow()); boost::posix_time::ptime ptNow(boost::posix_time::microsec_clock::universal_time()); boost::posix_time::milliseconds ptDur(boost::chrono::duration_cast(Helper::waitDur).count()); bool noTimeout = sf.timed_wait_until(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template void testSharedFutureStd(const std::string& name) { std::cout << std::endl; runTestWithNone(testSharedFutureWaitFor , name + "::wait_for()"); runTestWithNone(testSharedFutureWaitUntilSteady, name + "::wait_until(), steady time"); runTestWithNone(testSharedFutureWaitUntilSystem, name + "::wait_until(), system time"); runTestWithNone(testSharedFutureWaitUntilCustom, name + "::wait_until(), custom time"); } template void testSharedFutureBoost(const std::string& name) { testSharedFutureStd(name); // Boost-only functions runTestWithNone(testSharedFutureTimedWaitRelative, name + "::timed_wait(), relative time"); runTestWithNone(testSharedFutureTimedWaitAbsolute, name + "::timed_wait_until(), absolute time"); } /******************************************************************************/ // Test Sync Priority Queue template void testSyncPriorityQueuePullFor(const long long jumpMs) { boost::sync_priority_queue q; int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template void testSyncPriorityQueuePullUntilSteady(const long long jumpMs) { boost::sync_priority_queue q; int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template void testSyncPriorityQueuePullUntilSystem(const long long jumpMs) { boost::sync_priority_queue q; int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } template void testSyncPriorityQueuePullUntilCustom(const long long jumpMs) { boost::sync_priority_queue q; int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } //-------------------------------------- // Only Boost supports sync_priority_queue template void testSyncPriorityQueueBoost(const std::string& name) { std::cout << std::endl; runTestWithNone(testSyncPriorityQueuePullFor , name + "::pull_for()"); runTestWithNone(testSyncPriorityQueuePullUntilSteady, name + "::pull_until(), steady time"); runTestWithNone(testSyncPriorityQueuePullUntilSystem, name + "::pull_until(), system time"); runTestWithNone(testSyncPriorityQueuePullUntilCustom, name + "::pull_until(), custom time"); } /******************************************************************************/ // Test Sync Timed Queue template void testSyncTimedQueuePullForEmptySteady(const long long jumpMs) { boost::sync_timed_queue q; int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template void testSyncTimedQueuePullForEmptySystem(const long long jumpMs) { boost::sync_timed_queue q; int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template void testSyncTimedQueuePullForEmptyCustom(const long long jumpMs) { boost::sync_timed_queue q; int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template void testSyncTimedQueuePullUntilEmptySteady(const long long jumpMs) { boost::sync_timed_queue q; int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template void testSyncTimedQueuePullUntilEmptySystem(const long long jumpMs) { boost::sync_timed_queue q; int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } template void testSyncTimedQueuePullUntilEmptyCustom(const long long jumpMs) { boost::sync_timed_queue q; int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool timeout = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::timeout); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } //-------------------------------------- template void testSyncTimedQueuePullForNotReadySteady(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, typename Helper::milliseconds(10000)); // a long time int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); } template void testSyncTimedQueuePullForNotReadySystem(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, typename Helper::milliseconds(10000)); // a long time int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); } template void testSyncTimedQueuePullForNotReadyCustom(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, typename Helper::milliseconds(10000)); // a long time int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool notReady = (q.pull_for(Helper::waitDur, i) == boost::queue_op_status::not_ready); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); } template void testSyncTimedQueuePullUntilNotReadySteady(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, typename Helper::milliseconds(10000)); // a long time int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool notReady = (q.pull_until(Helper::steadyNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); } template void testSyncTimedQueuePullUntilNotReadySystem(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, typename Helper::milliseconds(10000)); // a long time int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool notReady = (q.pull_until(Helper::systemNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, notReady ? e_not_ready_good : e_ready_bad); } template void testSyncTimedQueuePullUntilNotReadyCustom(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, typename Helper::milliseconds(10000)); // a long time int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool notReady = (q.pull_until(Helper::customNow() + Helper::waitDur, i) == boost::queue_op_status::not_ready); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, notReady ? e_not_ready_good : e_ready_bad); } //-------------------------------------- template void testSyncTimedQueuePullForSucceedsSteady(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, Helper::waitDur); int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad); } template void testSyncTimedQueuePullForSucceedsSystem(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, Helper::waitDur); int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); } template void testSyncTimedQueuePullForSucceedsCustom(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, Helper::waitDur); int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = (q.pull_for(typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); } template void testSyncTimedQueuePullUntilSucceedsSteady(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, Helper::steadyNow() + Helper::waitDur); int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = (q.pull_until(Helper::steadyNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad); } template void testSyncTimedQueuePullUntilSucceedsSystem(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, Helper::systemNow() + Helper::waitDur); int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = (q.pull_until(Helper::systemNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); } template void testSyncTimedQueuePullUntilSucceedsCustom(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, Helper::customNow() + Helper::waitDur); int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = (q.pull_until(Helper::customNow() + typename Helper::milliseconds(10000), i) == boost::queue_op_status::success); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); } //-------------------------------------- template void testSyncTimedQueueWaitPullSucceedsSteady(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, Helper::steadyNow() + Helper::waitDur); int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad); } template void testSyncTimedQueueWaitPullSucceedsSystem(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, Helper::systemNow() + Helper::waitDur); int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); } template void testSyncTimedQueueWaitPullSucceedsCustom(const long long jumpMs) { boost::sync_timed_queue q; q.push(0, Helper::customNow() + Helper::waitDur); int i; typename Helper::steady_time_point before(Helper::steadyNow()); bool succeeded = (q.wait_pull(i) == boost::queue_op_status::success); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); } //-------------------------------------- // Only Boost supports sync_timed_queue template void testSyncTimedQueueBoost(const std::string& name) { std::cout << std::endl; runTestWithNone(testSyncTimedQueuePullForEmptySteady , name + "::pull_for(), empty, steady time"); runTestWithNone(testSyncTimedQueuePullForEmptySystem , name + "::pull_for(), empty, system time"); runTestWithNone(testSyncTimedQueuePullForEmptyCustom , name + "::pull_for(), empty, custom time"); runTestWithNone(testSyncTimedQueuePullUntilEmptySteady, name + "::pull_until(), empty, steady time"); runTestWithNone(testSyncTimedQueuePullUntilEmptySystem, name + "::pull_until(), empty, system time"); runTestWithNone(testSyncTimedQueuePullUntilEmptyCustom, name + "::pull_until(), empty, custom time"); std::cout << std::endl; runTestWithNone(testSyncTimedQueuePullForNotReadySteady , name + "::pull_for(), not ready, steady time"); runTestWithNone(testSyncTimedQueuePullForNotReadySystem , name + "::pull_for(), not ready, system time"); runTestWithNone(testSyncTimedQueuePullForNotReadyCustom , name + "::pull_for(), not ready, custom time"); runTestWithNone(testSyncTimedQueuePullUntilNotReadySteady, name + "::pull_until(), not ready, steady time"); runTestWithNone(testSyncTimedQueuePullUntilNotReadySystem, name + "::pull_until(), not ready, system time"); runTestWithNone(testSyncTimedQueuePullUntilNotReadyCustom, name + "::pull_until(), not ready, custom time"); std::cout << std::endl; runTestWithNone(testSyncTimedQueuePullForSucceedsSteady , name + "::pull_for(), succeeds, steady time"); runTestWithNone(testSyncTimedQueuePullForSucceedsSystem , name + "::pull_for(), succeeds, system time"); runTestWithNone(testSyncTimedQueuePullForSucceedsCustom , name + "::pull_for(), succeeds, custom time"); runTestWithNone(testSyncTimedQueuePullUntilSucceedsSteady, name + "::pull_until(), succeeds, steady time"); runTestWithNone(testSyncTimedQueuePullUntilSucceedsSystem, name + "::pull_until(), succeeds, system time"); runTestWithNone(testSyncTimedQueuePullUntilSucceedsCustom, name + "::pull_until(), succeeds, custom time"); std::cout << std::endl; runTestWithNone(testSyncTimedQueueWaitPullSucceedsSteady, name + "::wait_pull(), succeeds, steady time"); runTestWithNone(testSyncTimedQueueWaitPullSucceedsSystem, name + "::wait_pull(), succeeds, system time"); runTestWithNone(testSyncTimedQueueWaitPullSucceedsCustom, name + "::wait_pull(), succeeds, custom time"); } /******************************************************************************/ int main() { std::cout << std::endl; std::cout << "INFO: This test requires root/Administrator privileges in order to change the system clock." << std::endl; std::cout << "INFO: Disable NTP while running this test to prevent NTP from changing the system clock." << std::endl; std::cout << std::endl; std::cout << "BOOST_HAS_PTHREAD_DELAY_NP: "; #ifdef BOOST_HAS_PTHREAD_DELAY_NP std::cout << "YES" << std::endl; #else std::cout << "NO" << std::endl; #endif std::cout << "BOOST_HAS_NANOSLEEP: "; #ifdef BOOST_HAS_NANOSLEEP std::cout << "YES" << std::endl; #else std::cout << "NO" << std::endl; #endif std::cout << "BOOST_THREAD_SLEEP_FOR_IS_STEADY: "; #ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY std::cout << "YES" << std::endl; #else std::cout << "NO" << std::endl; #endif std::cout << "CLOCK_MONOTONIC: "; #ifdef CLOCK_MONOTONIC std::cout << "YES" << std::endl; #else std::cout << "NO" << std::endl; #endif std::cout << "BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN: "; #ifdef BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN std::cout << "YES" << std::endl; #else std::cout << "NO" << std::endl; #endif std::cout << "BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS: "; #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS std::cout << "YES" << std::endl; #else std::cout << "NO" << std::endl; #endif std::cout << "BOOST_THREAD_V2_SHARED_MUTEX: "; #ifdef BOOST_THREAD_V2_SHARED_MUTEX std::cout << "YES" << std::endl; #else std::cout << "NO" << std::endl; #endif std::cout << "BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC: "; #ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC std::cout << "YES" << std::endl; #else std::cout << "NO" << std::endl; #endif std::cout << std::endl; std::cout << "Wait Time: " << s_waitMs << " ms" << std::endl; std::cout << "Short Jump Time: " << s_shortJumpMs << " ms" << std::endl; std::cout << "Long Jump Time: " << s_longJumpMs << " ms" << std::endl; std::cout << "Sleep Before Jump Time: " << s_sleepBeforeJumpMs << " ms" << std::endl; std::cout << "Max Early Error: " << s_maxEarlyErrorMs << " ms" << std::endl; std::cout << "Max Late Error: " << s_maxLateErrorMs << " ms" << std::endl; testSleepBoost >("boost"); testSleepNoIntBoost >("boost"); testSleepNoThreadBoost >("boost"); testSleepNoThreadNoIntBoost >("boost"); testJoinBoost >("boost"); testCondVarBoost >("boost::condition_variable"); testCondVarPredBoost >("boost::condition_variable"); testCondVarBoost >("boost::condition_variable_any"); testCondVarPredBoost >("boost::condition_variable_any"); testMutexBoost >("boost::timed_mutex"); testMutexBoost >("boost::recursive_timed_mutex"); testMutexBoost >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex testMutexSharedBoost >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex testMutexUpgradeBoost >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex testFutureBoost >("boost::future"); testSharedFutureBoost >("boost::shared_future"); testSyncPriorityQueueBoost >("boost::sync_priority_queue"); testSyncTimedQueueBoost >("boost::sync_timed_queue"); #ifdef TEST_CPP14_FEATURES testSleepStd >("std"); testSleepNoThreadStd >("std"); testCondVarStd >("std::condition_variable"); testCondVarPredStd >("std::condition_variable"); testCondVarStd >("std::condition_variable_any"); testCondVarPredStd >("std::condition_variable_any"); testMutexStd >("std::timed_mutex"); testMutexStd >("std::recursive_timed_mutex"); testMutexStd >("std::shared_timed_mutex"); testMutexSharedStd >("std::shared_timed_mutex"); testFutureStd >("std::future"); testSharedFutureStd >("std::shared_future"); #endif std::cout << std::endl; std::cout << "Number of Tests Run: " << g_numTestsRun << std::endl; std::cout << "Number of Tests Passed: " << g_numTestsPassed << std::endl; std::cout << "Number of Tests Failed: " << g_numTestsFailed << std::endl; return 0; }