test_time_jumps.cpp 95 KB

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