1 // ©2013-2014 Cameron Desrochers 2 3 #include "systemtime.h" 4 #include <climits> 5 6 #if defined(_MSC_VER) && _MSC_VER < 1700 7 #include <intrin.h> 8 #define CompilerMemBar() _ReadWriteBarrier() 9 #else 10 #include <atomic> 11 #define CompilerMemBar() std::atomic_signal_fence(std::memory_order_seq_cst) 12 #endif 13 14 #if defined(ST_WINDOWS) 15 16 #include <windows.h> 17 18 namespace moodycamel 19 { 20 sleep(int milliseconds)21void sleep(int milliseconds) 22 { 23 ::Sleep(milliseconds); 24 } 25 getSystemTime()26SystemTime getSystemTime() 27 { 28 LARGE_INTEGER t; 29 CompilerMemBar(); 30 if (!QueryPerformanceCounter(&t)) { 31 return static_cast<SystemTime>(-1); 32 } 33 CompilerMemBar(); 34 35 return static_cast<SystemTime>(t.QuadPart); 36 } 37 getTimeDelta(SystemTime start)38double getTimeDelta(SystemTime start) 39 { 40 LARGE_INTEGER t; 41 CompilerMemBar(); 42 if (start == static_cast<SystemTime>(-1) || !QueryPerformanceCounter(&t)) { 43 return -1; 44 } 45 CompilerMemBar(); 46 47 auto now = static_cast<SystemTime>(t.QuadPart); 48 49 LARGE_INTEGER f; 50 if (!QueryPerformanceFrequency(&f)) { 51 return -1; 52 } 53 54 #if defined(__GNUC__) 55 #pragma GCC diagnostic push 56 #pragma GCC diagnostic ignored "-Wconversion" 57 #endif 58 return static_cast<double>(static_cast<__int64>(now - start)) / f.QuadPart * 1000; 59 #if defined(__GNUC__) 60 #pragma GCC diagnostic pop 61 #endif 62 } 63 64 } // end namespace moodycamel 65 66 #elif defined(ST_APPLE) 67 68 #include <mach/mach.h> 69 #include <mach/mach_time.h> 70 #include <unistd.h> 71 #include <time.h> 72 73 namespace moodycamel 74 { 75 sleep(int milliseconds)76void sleep(int milliseconds) 77 { 78 ::usleep(milliseconds * 1000); 79 } 80 getSystemTime()81SystemTime getSystemTime() 82 { 83 CompilerMemBar(); 84 std::uint64_t result = mach_absolute_time(); 85 CompilerMemBar(); 86 87 return result; 88 } 89 getTimeDelta(SystemTime start)90double getTimeDelta(SystemTime start) 91 { 92 CompilerMemBar(); 93 std::uint64_t end = mach_absolute_time(); 94 CompilerMemBar(); 95 96 mach_timebase_info_data_t tb = { 0 }; 97 mach_timebase_info(&tb); 98 double toNano = static_cast<double>(tb.numer) / tb.denom; 99 100 return static_cast<double>(end - start) * toNano * 0.000001; 101 } 102 103 } // end namespace moodycamel 104 105 #elif defined(ST_NIX) 106 107 #include <unistd.h> 108 109 namespace moodycamel 110 { 111 sleep(int milliseconds)112void sleep(int milliseconds) 113 { 114 ::usleep(milliseconds * 1000); 115 } 116 getSystemTime()117SystemTime getSystemTime() 118 { 119 timespec t; 120 CompilerMemBar(); 121 if (clock_gettime(CLOCK_MONOTONIC_RAW, &t) != 0) { 122 t.tv_sec = (time_t)-1; 123 t.tv_nsec = -1; 124 } 125 CompilerMemBar(); 126 127 return t; 128 } 129 getTimeDelta(SystemTime start)130double getTimeDelta(SystemTime start) 131 { 132 timespec t; 133 CompilerMemBar(); 134 if ((start.tv_sec == (time_t)-1 && start.tv_nsec == -1) || clock_gettime(CLOCK_MONOTONIC_RAW, &t) != 0) { 135 return -1; 136 } 137 CompilerMemBar(); 138 139 return static_cast<double>(static_cast<long>(t.tv_sec) - static_cast<long>(start.tv_sec)) * 1000 + double(t.tv_nsec - start.tv_nsec) / 1000000; 140 } 141 142 } // end namespace moodycamel 143 144 #endif 145