|
19 | 19 | #include "ThreadingHelpers.h"
|
20 | 20 | #include "LockingHelpers.h"
|
21 | 21 |
|
| 22 | +#ifdef _WIN32 |
| 23 | +#include <windows.h> |
| 24 | +#endif |
| 25 | + |
22 | 26 | using namespace swift;
|
23 | 27 |
|
24 | 28 | template <typename Body>
|
25 | 29 | std::chrono::duration<double> measureDuration(Body body) {
|
| 30 | +#ifdef _WIN32 |
| 31 | + /* On Windows, we use SleepConditionVariableSRW() to implement |
| 32 | + ConditionVariable. The way Windows implements the SleepXXX() functions, |
| 33 | + if you specify a timeout smaller than the current system tick rate, |
| 34 | + the function may return early. See |
| 35 | +
|
| 36 | + https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep |
| 37 | +
|
| 38 | + This causes flakiness in this test, which is undesirable. |
| 39 | +
|
| 40 | + To combat this, we adjust the system tick rate temporarily here. |
| 41 | +
|
| 42 | + Even *after* doing that, measurement suggests that Windows can return |
| 43 | + early by an amount not exceeding a system tick. */ |
| 44 | + TIMECAPS tc; |
| 45 | + UINT uTimerRes; |
| 46 | + |
| 47 | + ASSERT_NE(timeGetDevCaps(&tc, sizeof(TIMECAPS)), TIMERR_NOERROR); |
| 48 | + |
| 49 | + uTimerRes = min(max(tc.wPeriodMin, 1/*ms*/), tc.wPeriodMax); |
| 50 | + timeBeginPeriod(uTimerRes); |
| 51 | +#endif |
| 52 | + |
26 | 53 | auto start = std::chrono::steady_clock::now();
|
27 | 54 | body();
|
28 |
| - return std::chrono::steady_clock::now() - start; |
| 55 | + std::chrono::duration<double> elapsed = std::chrono::steady_clock::now() - start; |
| 56 | + |
| 57 | +#ifdef _WIN32 |
| 58 | + timeEndPeriod(uTimerRes); |
| 59 | + |
| 60 | + // Lie about the elapsed time to make the test more robust |
| 61 | + elapsed += 0.001s; |
| 62 | +#endif |
| 63 | + |
| 64 | + return elapsed; |
29 | 65 | }
|
30 | 66 |
|
31 | 67 | // -----------------------------------------------------------------------------
|
|
0 commit comments