/
BirdLeon
/
ROBLOX2016
Обзор
Документация
Войти
/
BirdLeon
/
ROBLOX2016
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
Library/boost/libs/thread/test/test_time_jumps.cpp
2 398 строк
95 KB
PatoFlamejanteTV
full source code
19 дек 2024, 19:11
19 дек 2024, 19:11
05db15d
Код
Авторство
О чём код?
#ifdef _WIN32 #include <windows.h> #else #include <sys/time.h> #endif #include "boost/bind/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 <iomanip> #ifdef TEST_CPP14_FEATURES #include <future> #include <mutex> #include <shared_mutex> #include <thread> #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<custom_boost_clock> 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<duration>(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<custom_std_clock> 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<duration>(std::chrono::system_clock::now().time_since_epoch()) - std::chrono::hours(10 * 365 * 24)); } #endif } /******************************************************************************/ template <typename MutexType = boost::mutex, typename CondType = boost::condition_variable> struct BoostHelper { typedef MutexType mutex; typedef CondType cond; typedef boost::lock_guard<MutexType> lock_guard; typedef boost::unique_lock<MutexType> 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<bool> packaged_task; typedef boost::future<bool> future; typedef boost::shared_future<bool> shared_future; typedef boost::thread thread; static const milliseconds waitDur; template <typename T> static void sleep_for(T d) { boost::this_thread::sleep_for(d); } template <typename T> static void sleep_for_no_int(T d) { boost::this_thread::no_interruption_point::sleep_for(d); } template <typename T> static void sleep_until(T t) { boost::this_thread::sleep_until(t); } template <typename T> 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 <class ToDuration, class Rep, class Period> static ToDuration duration_cast(const boost::chrono::duration<Rep, Period>& d) { return boost::chrono::duration_cast<ToDuration>(d); } static milliseconds zero() { return milliseconds(0); } }; template <typename MutexType, typename CondType> const typename BoostHelper<MutexType, CondType>::milliseconds BoostHelper<MutexType, CondType>::waitDur = typename BoostHelper<MutexType, CondType>::milliseconds(s_waitMs); #ifdef TEST_CPP14_FEATURES template <typename MutexType = std::mutex, typename CondType = std::condition_variable> struct StdHelper { typedef MutexType mutex; typedef CondType cond; typedef std::lock_guard<MutexType> lock_guard; typedef std::unique_lock<MutexType> 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<bool()> packaged_task; typedef std::future<bool> future; typedef std::shared_future<bool> shared_future; typedef std::thread thread; static const milliseconds waitDur; template <typename T> static void sleep_for(T d) { std::this_thread::sleep_for(d); } template <typename T> 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 <class ToDuration, class Rep, class Period> static ToDuration duration_cast(const std::chrono::duration<Rep, Period>& d) { return std::chrono::duration_cast<ToDuration>(d); } static milliseconds zero() { return milliseconds(0); } }; template <typename MutexType, typename CondType> const typename StdHelper<MutexType, CondType>::milliseconds StdHelper<MutexType, CondType>::waitDur = typename StdHelper<MutexType, CondType>::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 <typename Helper> 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<typename Helper::milliseconds>(expected); typename Helper::milliseconds actualMs = Helper::template duration_cast<typename Helper::milliseconds>(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 <typename Helper, typename Context, typename Function> 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 <typename Helper, typename Function> void noThreadContext(Function func, const long long jumpMs) { func(jumpMs); } template <typename Helper, typename Function> void threadContextWithNone(Function func, const long long jumpMs) { typename Helper::thread t(boost::bind(func, jumpMs)); t.join(); } template <typename Helper, typename Function> 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 <typename Helper, typename Function> void threadContextWithShared(Function func, const long long jumpMs) { typename Helper::mutex m; boost::shared_lock_guard<typename Helper::mutex> g(m); typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs)); t.join(); } template <typename Helper, typename Function> void threadContextWithUpgrade(Function func, const long long jumpMs) { typename Helper::mutex m; boost::upgrade_lock<typename Helper::mutex> g(m); typename Helper::thread t(boost::bind(func, boost::ref(m), jumpMs)); t.join(); } //-------------------------------------- // Run the test in the current thread. template <typename Helper, typename Function> void runTest(Function func, const std::string name) { runTestInContext<Helper>(noThreadContext<Helper, Function>, func, name); } // Run the test in a separate thread. template <typename Helper, typename Function> void runTestWithNone(Function func, const std::string name) { runTestInContext<Helper>(threadContextWithNone<Helper, Function>, func, name); } // Run the test in a separate thread. Pass a locked mutex to the function under test. template <typename Helper, typename Function> void runTestWithUnique(Function func, const std::string name) { runTestInContext<Helper>(threadContextWithUnique<Helper, Function>, func, name); } // Run the test in a separate thread. Pass a shared-locked mutex to the function under test. template <typename Helper, typename Function> void runTestWithShared(Function func, const std::string name) { runTestInContext<Helper>(threadContextWithShared<Helper, Function>, func, name); } // Run the test in a separate thread. Pass an upgrade-locked mutex to the function under test. template <typename Helper, typename Function> void runTestWithUpgrade(Function func, const std::string name) { runTestInContext<Helper>(threadContextWithUpgrade<Helper, Function>, func, name); } /******************************************************************************/ // Test Sleep template <typename Helper> 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>(Helper::waitDur, after - before, e_na); } template <typename Helper> 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>(Helper::waitDur, after - before, e_na); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); } //-------------------------------------- template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); boost::this_thread::sleep(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); boost::this_thread::sleep(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template <typename Helper> void testSleepStd(const std::string& name) { std::cout << std::endl; runTestWithNone<Helper>(testSleepFor <Helper>, name + "::this_thread::sleep_for()"); runTestWithNone<Helper>(testSleepUntilSteady<Helper>, name + "::this_thread::sleep_until(), steady time"); runTestWithNone<Helper>(testSleepUntilSystem<Helper>, name + "::this_thread::sleep_until(), system time"); runTestWithNone<Helper>(testSleepUntilCustom<Helper>, name + "::this_thread::sleep_until(), custom time"); } template <typename Helper> void testSleepBoost(const std::string& name) { testSleepStd<Helper>(name); // Boost-only functions runTestWithNone<Helper>(testSleepRelative<Helper>, name + "::this_thread::sleep(), relative time"); runTestWithNone<Helper>(testSleepAbsolute<Helper>, name + "::this_thread::sleep(), absolute time"); } template <typename Helper> void testSleepNoThreadStd(const std::string& name) { std::cout << std::endl; runTest<Helper>(testSleepFor <Helper>, name + "::this_thread::sleep_for(), no thread"); runTest<Helper>(testSleepUntilSteady<Helper>, name + "::this_thread::sleep_until(), no thread, steady time"); runTest<Helper>(testSleepUntilSystem<Helper>, name + "::this_thread::sleep_until(), no thread, system time"); runTest<Helper>(testSleepUntilCustom<Helper>, name + "::this_thread::sleep_until(), no thread, custom time"); } template <typename Helper> void testSleepNoThreadBoost(const std::string& name) { testSleepNoThreadStd<Helper>(name); // Boost-only functions runTest<Helper>(testSleepRelative<Helper>, name + "::this_thread::sleep(), no thread, relative time"); runTest<Helper>(testSleepAbsolute<Helper>, name + "::this_thread::sleep(), no thread, absolute time"); } /******************************************************************************/ // Test Sleep, No Interruption Point template <typename Helper> 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>(Helper::waitDur, after - before, e_na); } template <typename Helper> 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>(Helper::waitDur, after - before, e_na); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); } //-------------------------------------- #ifndef SKIP_NO_INT_SLEEP template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); boost::this_thread::no_interruption_point::sleep(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur, after - before, e_na); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); boost::this_thread::no_interruption_point::sleep(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, e_na); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } #endif //-------------------------------------- // Only Boost supports no_interruption_point template <typename Helper> void testSleepNoIntBoost(const std::string& name) { std::cout << std::endl; runTestWithNone<Helper>(testSleepForNoInt <Helper>, name + "::this_thread::no_interruption_point::sleep_for()"); runTestWithNone<Helper>(testSleepUntilNoIntSteady<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), steady time"); runTestWithNone<Helper>(testSleepUntilNoIntSystem<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), system time"); runTestWithNone<Helper>(testSleepUntilNoIntCustom<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), custom time"); #ifndef SKIP_NO_INT_SLEEP runTestWithNone<Helper>(testSleepNoIntRelative<Helper>, name + "::this_thread::no_interruption_point::sleep(), relative time"); runTestWithNone<Helper>(testSleepNoIntAbsolute<Helper>, name + "::this_thread::no_interruption_point::sleep(), absolute time"); #endif } template <typename Helper> void testSleepNoThreadNoIntBoost(const std::string& name) { std::cout << std::endl; runTest<Helper>(testSleepForNoInt <Helper>, name + "::this_thread::no_interruption_point::sleep_for(), no thread"); runTest<Helper>(testSleepUntilNoIntSteady<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, steady time"); runTest<Helper>(testSleepUntilNoIntSystem<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, system time"); runTest<Helper>(testSleepUntilNoIntCustom<Helper>, name + "::this_thread::no_interruption_point::sleep_until(), no thread, custom time"); #ifndef SKIP_NO_INT_SLEEP runTest<Helper>(testSleepNoIntRelative<Helper>, name + "::this_thread::no_interruption_point::sleep(), no thread, relative time"); runTest<Helper>(testSleepNoIntAbsolute<Helper>, name + "::this_thread::no_interruption_point::sleep(), no thread, absolute time"); #endif } /******************************************************************************/ // Test Try Join template <typename Helper> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } //-------------------------------------- template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); typename Helper::thread t3(sleepForLongTime); bool succeeded = t3.timed_join(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } template <typename Helper> 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<boost::chrono::milliseconds>(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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- // Only Boost supports timed try_join functions template <typename Helper> void testJoinBoost(const std::string& name) { std::cout << std::endl; runTestWithNone<Helper>(testTryJoinFor <Helper>, name + "::thread::try_join_for()"); runTestWithNone<Helper>(testTryJoinUntilSteady<Helper>, name + "::thread::try_join_until(), steady time"); runTestWithNone<Helper>(testTryJoinUntilSystem<Helper>, name + "::thread::try_join_until(), system time"); runTestWithNone<Helper>(testTryJoinUntilCustom<Helper>, name + "::thread::try_join_until(), custom time"); runTestWithNone<Helper>(testTimedJoinRelative <Helper>, name + "::thread::timed_join(), relative time"); runTestWithNone<Helper>(testTimedJoinAbsolute <Helper>, name + "::thread::timed_join(), absolute time"); } /******************************************************************************/ // Test Condition Variable Wait template <typename Helper> 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>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); } template <typename Helper> 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>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); } //-------------------------------------- template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool noTimeout = cv.timed_wait(g, ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool noTimeout = cv.timed_wait(g, ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template <typename Helper> void testCondVarStd(const std::string& name) { std::cout << std::endl; runTestWithNone<Helper>(testCondVarWaitFor <Helper>, name + "::wait_for()"); runTestWithNone<Helper>(testCondVarWaitUntilSteady<Helper>, name + "::wait_until(), steady time"); runTestWithNone<Helper>(testCondVarWaitUntilSystem<Helper>, name + "::wait_until(), system time"); runTestWithNone<Helper>(testCondVarWaitUntilCustom<Helper>, name + "::wait_until(), custom time"); } template <typename Helper> void testCondVarBoost(const std::string& name) { testCondVarStd<Helper>(name); // Boost-only functions runTestWithNone<Helper>(testCondVarTimedWaitRelative<Helper>, name + "::timed_wait(), relative time"); runTestWithNone<Helper>(testCondVarTimedWaitAbsolute<Helper>, name + "::timed_wait(), absolute time"); } /******************************************************************************/ // Test Condition Variable Wait with Predicate template <typename Helper> 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>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); } template <typename Helper> 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>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); } //-------------------------------------- template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool noTimeout = cv.timed_wait(g, ptDur, returnFalse); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool noTimeout = cv.timed_wait(g, ptNow + ptDur, returnFalse); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template <typename Helper> void testCondVarPredStd(const std::string& name) { std::cout << std::endl; runTestWithNone<Helper>(testCondVarWaitForPred <Helper>, name + "::wait_for(), with predicate"); runTestWithNone<Helper>(testCondVarWaitUntilPredSteady<Helper>, name + "::wait_until(), with predicate, steady time"); runTestWithNone<Helper>(testCondVarWaitUntilPredSystem<Helper>, name + "::wait_until(), with predicate, system time"); runTestWithNone<Helper>(testCondVarWaitUntilPredCustom<Helper>, name + "::wait_until(), with predicate, custom time"); } template <typename Helper> void testCondVarPredBoost(const std::string& name) { testCondVarPredStd<Helper>(name); // Boost-only functions runTestWithNone<Helper>(testCondVarTimedWaitPredRelative<Helper>, name + "::timed_wait(), with predicate, relative time"); runTestWithNone<Helper>(testCondVarTimedWaitPredAbsolute<Helper>, name + "::timed_wait(), with predicate, absolute time"); } /******************************************************************************/ // Test Try Lock template <typename Helper> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } //-------------------------------------- template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool succeeded = m.timed_lock(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool succeeded = m.timed_lock(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template <typename Helper> void testMutexStd(const std::string& name) { std::cout << std::endl; runTestWithUnique<Helper>(testTryLockFor <Helper>, name + "::try_lock_for()"); runTestWithUnique<Helper>(testTryLockUntilSteady<Helper>, name + "::try_lock_until(), steady time"); runTestWithUnique<Helper>(testTryLockUntilSystem<Helper>, name + "::try_lock_until(), system time"); runTestWithUnique<Helper>(testTryLockUntilCustom<Helper>, name + "::try_lock_until(), custom time"); } template <typename Helper> void testMutexBoost(const std::string& name) { testMutexStd<Helper>(name); // Boost-only functions runTestWithUnique<Helper>(testTimedLockRelative<Helper>, name + "::timed_lock(), relative time"); runTestWithUnique<Helper>(testTimedLockAbsolute<Helper>, name + "::timed_lock(), absolute time"); } /******************************************************************************/ // Test Try Lock Shared template <typename Helper> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } //-------------------------------------- template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool succeeded = m.timed_lock_shared(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool succeeded = m.timed_lock_shared(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template <typename Helper> void testMutexSharedStd(const std::string& name) { std::cout << std::endl; runTestWithUnique<Helper>(testTryLockSharedFor <Helper>, name + "::try_lock_shared_for()"); runTestWithUnique<Helper>(testTryLockSharedUntilSteady<Helper>, name + "::try_lock_shared_until(), steady time"); runTestWithUnique<Helper>(testTryLockSharedUntilSystem<Helper>, name + "::try_lock_shared_until(), system time"); runTestWithUnique<Helper>(testTryLockSharedUntilCustom<Helper>, name + "::try_lock_shared_until(), custom time"); } template <typename Helper> void testMutexSharedBoost(const std::string& name) { testMutexSharedStd<Helper>(name); // Boost-only functions runTestWithUnique<Helper>(testTimedLockSharedRelative<Helper>, name + "::timed_lock_shared(), relative time"); runTestWithUnique<Helper>(testTimedLockSharedAbsolute<Helper>, name + "::timed_lock_shared(), absolute time"); } /******************************************************************************/ // Test Try Lock Upgrade #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS template <typename Helper> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } //-------------------------------------- template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool succeeded = m.timed_lock_upgrade(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool succeeded = m.timed_lock_upgrade(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template <typename Helper> void testTryUnlockSharedAndLockFor(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard<typename Helper::mutex> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> void testTryUnlockSharedAndLockUntilSteady(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard<typename Helper::mutex> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> void testTryUnlockSharedAndLockUntilSystem(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard<typename Helper::mutex> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> void testTryUnlockSharedAndLockUntilCustom(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard<typename Helper::mutex> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } //-------------------------------------- template <typename Helper> void testTryUnlockUpgradeAndLockFor(typename Helper::mutex& m, const long long jumpMs) { boost::upgrade_lock<typename Helper::mutex> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> void testTryUnlockUpgradeAndLockUntilSteady(typename Helper::mutex& m, const long long jumpMs) { boost::upgrade_lock<typename Helper::mutex> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> void testTryUnlockUpgradeAndLockUntilSystem(typename Helper::mutex& m, const long long jumpMs) { boost::upgrade_lock<typename Helper::mutex> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> void testTryUnlockUpgradeAndLockUntilCustom(typename Helper::mutex& m, const long long jumpMs) { boost::upgrade_lock<typename Helper::mutex> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } //-------------------------------------- template <typename Helper> void testTryUnlockSharedAndLockUpgradeFor(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard<typename Helper::mutex> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> void testTryUnlockSharedAndLockUpgradeUntilSteady(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard<typename Helper::mutex> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> void testTryUnlockSharedAndLockUpgradeUntilSystem(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard<typename Helper::mutex> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } template <typename Helper> void testTryUnlockSharedAndLockUpgradeUntilCustom(typename Helper::mutex& m, const long long jumpMs) { boost::shared_lock_guard<typename Helper::mutex> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_bad : e_failed_good); } #endif //-------------------------------------- // Only Boost supports upgrade mutexes template <typename Helper> void testMutexUpgradeBoost(const std::string& name) { #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS std::cout << std::endl; runTestWithUnique<Helper>(testTryLockUpgradeFor <Helper>, name + "::try_lock_upgrade_for()"); runTestWithUnique<Helper>(testTryLockUpgradeUntilSteady<Helper>, name + "::try_lock_upgrade_until(), steady time"); runTestWithUnique<Helper>(testTryLockUpgradeUntilSystem<Helper>, name + "::try_lock_upgrade_until(), system time"); runTestWithUnique<Helper>(testTryLockUpgradeUntilCustom<Helper>, name + "::try_lock_upgrade_until(), custom time"); runTestWithUnique<Helper>(testTimedLockUpgradeRelative <Helper>, name + "::timed_lock_upgrade(), relative time"); runTestWithUnique<Helper>(testTimedLockUpgradeAbsolute <Helper>, name + "::timed_lock_upgrade(), absolute time"); std::cout << std::endl; runTestWithShared<Helper>(testTryUnlockSharedAndLockFor <Helper>, name + "::try_unlock_shared_and_lock_for()"); runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilSteady<Helper>, name + "::try_unlock_shared_and_lock_until(), steady time"); runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilSystem<Helper>, name + "::try_unlock_shared_and_lock_until(), system time"); runTestWithShared<Helper>(testTryUnlockSharedAndLockUntilCustom<Helper>, name + "::try_unlock_shared_and_lock_until(), custom time"); std::cout << std::endl; runTestWithShared<Helper>(testTryUnlockUpgradeAndLockFor <Helper>, name + "::try_unlock_upgrade_and_lock_for()"); runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilSteady<Helper>, name + "::try_unlock_upgrade_and_lock_until(), steady time"); runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilSystem<Helper>, name + "::try_unlock_upgrade_and_lock_until(), system time"); runTestWithShared<Helper>(testTryUnlockUpgradeAndLockUntilCustom<Helper>, name + "::try_unlock_upgrade_and_lock_until(), custom time"); std::cout << std::endl; runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockFor <Helper>, name + "::try_unlock_shared_and_lock_upgrade_for()"); runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilSteady<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), steady time"); runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilSystem<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), system time"); runTestWithUpgrade<Helper>(testTryUnlockSharedAndLockUntilCustom<Helper>, name + "::try_unlock_shared_and_lock_upgrade_until(), custom time"); #endif } /******************************************************************************/ // Test Future Wait template <typename Helper> 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>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> 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>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } //-------------------------------------- template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool noTimeout = f.timed_wait(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool noTimeout = f.timed_wait_until(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template <typename Helper> void testFutureStd(const std::string& name) { std::cout << std::endl; runTestWithNone<Helper>(testFutureWaitFor <Helper>, name + "::wait_for()"); runTestWithNone<Helper>(testFutureWaitUntilSteady<Helper>, name + "::wait_until(), steady time"); runTestWithNone<Helper>(testFutureWaitUntilSystem<Helper>, name + "::wait_until(), system time"); runTestWithNone<Helper>(testFutureWaitUntilCustom<Helper>, name + "::wait_until(), custom time"); } template <typename Helper> void testFutureBoost(const std::string& name) { testFutureStd<Helper>(name); // Boost-only functions runTestWithNone<Helper>(testFutureTimedWaitRelative<Helper>, name + "::timed_wait(), relative time"); runTestWithNone<Helper>(testFutureTimedWaitAbsolute<Helper>, name + "::timed_wait_until(), absolute time"); } /******************************************************************************/ // Test Shared Future Wait template <typename Helper> 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>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> 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>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } //-------------------------------------- template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool noTimeout = sf.timed_wait(ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur, after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } template <typename Helper> 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<boost::chrono::milliseconds>(Helper::waitDur).count()); bool noTimeout = sf.timed_wait_until(ptNow + ptDur); typename Helper::steady_time_point after(Helper::steadyNow()); checkWaitTime<Helper>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, noTimeout ? e_no_timeout : e_timeout); #else checkWaitTime<Helper>(Helper::zero(), Helper::zero(), e_na); #endif } //-------------------------------------- template <typename Helper> void testSharedFutureStd(const std::string& name) { std::cout << std::endl; runTestWithNone<Helper>(testSharedFutureWaitFor <Helper>, name + "::wait_for()"); runTestWithNone<Helper>(testSharedFutureWaitUntilSteady<Helper>, name + "::wait_until(), steady time"); runTestWithNone<Helper>(testSharedFutureWaitUntilSystem<Helper>, name + "::wait_until(), system time"); runTestWithNone<Helper>(testSharedFutureWaitUntilCustom<Helper>, name + "::wait_until(), custom time"); } template <typename Helper> void testSharedFutureBoost(const std::string& name) { testSharedFutureStd<Helper>(name); // Boost-only functions runTestWithNone<Helper>(testSharedFutureTimedWaitRelative<Helper>, name + "::timed_wait(), relative time"); runTestWithNone<Helper>(testSharedFutureTimedWaitAbsolute<Helper>, name + "::timed_wait_until(), absolute time"); } /******************************************************************************/ // Test Sync Priority Queue template <typename Helper> void testSyncPriorityQueuePullFor(const long long jumpMs) { boost::sync_priority_queue<int> 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>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> void testSyncPriorityQueuePullUntilSteady(const long long jumpMs) { boost::sync_priority_queue<int> 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>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> void testSyncPriorityQueuePullUntilSystem(const long long jumpMs) { boost::sync_priority_queue<int> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> void testSyncPriorityQueuePullUntilCustom(const long long jumpMs) { boost::sync_priority_queue<int> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } //-------------------------------------- // Only Boost supports sync_priority_queue template <typename Helper> void testSyncPriorityQueueBoost(const std::string& name) { std::cout << std::endl; runTestWithNone<Helper>(testSyncPriorityQueuePullFor <Helper>, name + "::pull_for()"); runTestWithNone<Helper>(testSyncPriorityQueuePullUntilSteady<Helper>, name + "::pull_until(), steady time"); runTestWithNone<Helper>(testSyncPriorityQueuePullUntilSystem<Helper>, name + "::pull_until(), system time"); runTestWithNone<Helper>(testSyncPriorityQueuePullUntilCustom<Helper>, name + "::pull_until(), custom time"); } /******************************************************************************/ // Test Sync Timed Queue template <typename Helper> void testSyncTimedQueuePullForEmptySteady(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::steady_clock> 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>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> void testSyncTimedQueuePullForEmptySystem(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::system_clock> 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>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> void testSyncTimedQueuePullForEmptyCustom(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::custom_clock> 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>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> void testSyncTimedQueuePullUntilEmptySteady(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::steady_clock> 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>(Helper::waitDur, after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> void testSyncTimedQueuePullUntilEmptySystem(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::system_clock> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } template <typename Helper> void testSyncTimedQueuePullUntilEmptyCustom(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::custom_clock> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, timeout ? e_timeout : e_no_timeout); } //-------------------------------------- template <typename Helper> void testSyncTimedQueuePullForNotReadySteady(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::steady_clock> 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>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); } template <typename Helper> void testSyncTimedQueuePullForNotReadySystem(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::system_clock> 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>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); } template <typename Helper> void testSyncTimedQueuePullForNotReadyCustom(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::custom_clock> 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>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); } template <typename Helper> void testSyncTimedQueuePullUntilNotReadySteady(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::steady_clock> 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>(Helper::waitDur, after - before, notReady ? e_not_ready_good : e_ready_bad); } template <typename Helper> void testSyncTimedQueuePullUntilNotReadySystem(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::system_clock> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, notReady ? e_not_ready_good : e_ready_bad); } template <typename Helper> void testSyncTimedQueuePullUntilNotReadyCustom(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::custom_clock> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, notReady ? e_not_ready_good : e_ready_bad); } //-------------------------------------- template <typename Helper> void testSyncTimedQueuePullForSucceedsSteady(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::steady_clock> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad); } template <typename Helper> void testSyncTimedQueuePullForSucceedsSystem(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::system_clock> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); } template <typename Helper> void testSyncTimedQueuePullForSucceedsCustom(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::custom_clock> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); } template <typename Helper> void testSyncTimedQueuePullUntilSucceedsSteady(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::steady_clock> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad); } template <typename Helper> void testSyncTimedQueuePullUntilSucceedsSystem(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::system_clock> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); } template <typename Helper> void testSyncTimedQueuePullUntilSucceedsCustom(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::custom_clock> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); } //-------------------------------------- template <typename Helper> void testSyncTimedQueueWaitPullSucceedsSteady(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::steady_clock> 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>(Helper::waitDur, after - before, succeeded ? e_succeeded_good : e_failed_bad); } template <typename Helper> void testSyncTimedQueueWaitPullSucceedsSystem(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::system_clock> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); } template <typename Helper> void testSyncTimedQueueWaitPullSucceedsCustom(const long long jumpMs) { boost::sync_timed_queue<int, typename Helper::custom_clock> 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>(Helper::waitDur - typename Helper::milliseconds(jumpMs), after - before, succeeded ? e_succeeded_good : e_failed_bad); } //-------------------------------------- // Only Boost supports sync_timed_queue template <typename Helper> void testSyncTimedQueueBoost(const std::string& name) { std::cout << std::endl; runTestWithNone<Helper>(testSyncTimedQueuePullForEmptySteady <Helper>, name + "::pull_for(), empty, steady time"); runTestWithNone<Helper>(testSyncTimedQueuePullForEmptySystem <Helper>, name + "::pull_for(), empty, system time"); runTestWithNone<Helper>(testSyncTimedQueuePullForEmptyCustom <Helper>, name + "::pull_for(), empty, custom time"); runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptySteady<Helper>, name + "::pull_until(), empty, steady time"); runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptySystem<Helper>, name + "::pull_until(), empty, system time"); runTestWithNone<Helper>(testSyncTimedQueuePullUntilEmptyCustom<Helper>, name + "::pull_until(), empty, custom time"); std::cout << std::endl; runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadySteady <Helper>, name + "::pull_for(), not ready, steady time"); runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadySystem <Helper>, name + "::pull_for(), not ready, system time"); runTestWithNone<Helper>(testSyncTimedQueuePullForNotReadyCustom <Helper>, name + "::pull_for(), not ready, custom time"); runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadySteady<Helper>, name + "::pull_until(), not ready, steady time"); runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadySystem<Helper>, name + "::pull_until(), not ready, system time"); runTestWithNone<Helper>(testSyncTimedQueuePullUntilNotReadyCustom<Helper>, name + "::pull_until(), not ready, custom time"); std::cout << std::endl; runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsSteady <Helper>, name + "::pull_for(), succeeds, steady time"); runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsSystem <Helper>, name + "::pull_for(), succeeds, system time"); runTestWithNone<Helper>(testSyncTimedQueuePullForSucceedsCustom <Helper>, name + "::pull_for(), succeeds, custom time"); runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsSteady<Helper>, name + "::pull_until(), succeeds, steady time"); runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsSystem<Helper>, name + "::pull_until(), succeeds, system time"); runTestWithNone<Helper>(testSyncTimedQueuePullUntilSucceedsCustom<Helper>, name + "::pull_until(), succeeds, custom time"); std::cout << std::endl; runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsSteady<Helper>, name + "::wait_pull(), succeeds, steady time"); runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsSystem<Helper>, name + "::wait_pull(), succeeds, system time"); runTestWithNone<Helper>(testSyncTimedQueueWaitPullSucceedsCustom<Helper>, 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 <BoostHelper< > >("boost"); testSleepNoIntBoost <BoostHelper< > >("boost"); testSleepNoThreadBoost <BoostHelper< > >("boost"); testSleepNoThreadNoIntBoost<BoostHelper< > >("boost"); testJoinBoost <BoostHelper< > >("boost"); testCondVarBoost <BoostHelper<boost::mutex, boost::condition_variable > >("boost::condition_variable"); testCondVarPredBoost <BoostHelper<boost::mutex, boost::condition_variable > >("boost::condition_variable"); testCondVarBoost <BoostHelper<boost::mutex, boost::condition_variable_any> >("boost::condition_variable_any"); testCondVarPredBoost <BoostHelper<boost::mutex, boost::condition_variable_any> >("boost::condition_variable_any"); testMutexBoost <BoostHelper<boost::timed_mutex > >("boost::timed_mutex"); testMutexBoost <BoostHelper<boost::recursive_timed_mutex > >("boost::recursive_timed_mutex"); testMutexBoost <BoostHelper<boost::shared_mutex > >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex testMutexSharedBoost <BoostHelper<boost::shared_mutex > >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex testMutexUpgradeBoost <BoostHelper<boost::shared_mutex > >("boost::shared_mutex"); // upgrade_mutex is a typedef of shared_mutex, so no need to test upgrade_mutex testFutureBoost <BoostHelper< > >("boost::future"); testSharedFutureBoost <BoostHelper< > >("boost::shared_future"); testSyncPriorityQueueBoost <BoostHelper< > >("boost::sync_priority_queue"); testSyncTimedQueueBoost <BoostHelper< > >("boost::sync_timed_queue"); #ifdef TEST_CPP14_FEATURES testSleepStd <StdHelper< > >("std"); testSleepNoThreadStd<StdHelper< > >("std"); testCondVarStd <StdHelper<std::mutex, std::condition_variable > >("std::condition_variable"); testCondVarPredStd <StdHelper<std::mutex, std::condition_variable > >("std::condition_variable"); testCondVarStd <StdHelper<std::mutex, std::condition_variable_any> >("std::condition_variable_any"); testCondVarPredStd <StdHelper<std::mutex, std::condition_variable_any> >("std::condition_variable_any"); testMutexStd <StdHelper<std::timed_mutex > >("std::timed_mutex"); testMutexStd <StdHelper<std::recursive_timed_mutex > >("std::recursive_timed_mutex"); testMutexStd <StdHelper<std::shared_timed_mutex > >("std::shared_timed_mutex"); testMutexSharedStd <StdHelper<std::shared_timed_mutex > >("std::shared_timed_mutex"); testFutureStd <StdHelper< > >("std::future"); testSharedFutureStd <StdHelper< > >("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; }