1 /** 2 * Stopwatch module. 3 * 4 * Windows uses QueryPerformanceFrequency and QueryPerformanceCounter. 5 * Posix platforms use clock_gettime (CLOCK_MONOTONIC). 6 */ 7 module stopwatch; 8 9 version (Windows) 10 { 11 import core.sys.windows.windows; 12 private __gshared long __freq; 13 } 14 else version (Posix) 15 { 16 import core.sys.posix.time : 17 CLOCK_MONOTONIC, timespec, clock_getres, clock_gettime; 18 private enum CLOCK_TYPE = CLOCK_MONOTONIC; 19 private enum TIME_NS = 1.0e12; // ns, used with clock_gettime 20 private enum TIME_US = 1.0e9; // µs, used with clock_gettime 21 private enum TIME_MS = 1.0e6; // ms, used with clock_gettime 22 private enum BASE = TIME_US; // base time 23 private __gshared timespec __freq; 24 } 25 26 struct stopwatch_t 27 { 28 version (Windows) 29 { 30 private alias time_t = long; 31 } 32 else version (Posix) 33 { 34 private alias time_t = timespec; 35 } 36 37 private time_t time0, time1; 38 bool running; 39 40 static void setup() 41 { 42 version (Windows) 43 { 44 LARGE_INTEGER l = void; 45 QueryPerformanceFrequency(&l); 46 __freq = l.QuadPart; 47 } 48 else version (Posix) 49 { 50 clock_getres(CLOCK_TYPE, &__freq); 51 } 52 //TODO: Take time delta to call os functions 53 } 54 55 void start() 56 { 57 version (Windows) 58 { 59 LARGE_INTEGER l = void; 60 QueryPerformanceCounter(&l); 61 time0 = l.QuadPart; 62 } 63 else version (Posix) 64 { 65 clock_gettime(CLOCK_TYPE, &time0); 66 } 67 68 running = true; 69 } 70 71 void stop() 72 { 73 version (Windows) 74 { 75 LARGE_INTEGER l = void; 76 QueryPerformanceCounter(&l); 77 time1 = l.QuadPart; 78 } 79 else version (Posix) 80 { 81 clock_gettime(CLOCK_TYPE, &time1); 82 } 83 running = false; 84 } 85 86 void reset() 87 { 88 time0 = time1 = time_t.init; 89 } 90 91 float ms() 92 { 93 version (Windows) 94 { 95 return ((time1 - time0) * 1000.0f) / __freq; 96 } 97 else version (Posix) 98 { 99 return cast(float) 100 ((BASE * (time1.tv_sec - time0.tv_sec)) 101 + time1.tv_nsec - time0.tv_nsec) / 1_000_000f; 102 } 103 } 104 105 float us() 106 { 107 version (Windows) 108 { 109 return (time1 - time0) / __freq; 110 } 111 else version (Posix) 112 { 113 return cast(float) 114 ((BASE * (time1.tv_sec - time0.tv_sec)) 115 + time1.tv_nsec - time0.tv_nsec) / 1_000f; 116 } 117 } 118 }