|
@@ -213,6 +213,44 @@ time_add :: proc(t: Time, d: Duration) -> Time {
|
|
return Time{t._nsec + i64(d)}
|
|
return Time{t._nsec + i64(d)}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Accurate sleep borrowed from: https://blat-blatnik.github.io/computerBear/making-accurate-sleep-function/
|
|
|
|
+//
|
|
|
|
+// Accuracy seems to be pretty good out of the box on Linux, to within around 4µs worst case.
|
|
|
|
+// On Windows it depends but is comparable with regular sleep in the worst case.
|
|
|
|
+// To get the same kind of accuracy as on Linux, have your program call `win32.time_begin_period(1)` to
|
|
|
|
+// tell Windows to use a more accurate timer for your process.
|
|
|
|
+accurate_sleep :: proc(d: Duration) {
|
|
|
|
+ to_sleep, estimate, mean, m2, count: Duration
|
|
|
|
+
|
|
|
|
+ to_sleep = d
|
|
|
|
+ estimate = 5 * Millisecond
|
|
|
|
+ mean = 5 * Millisecond
|
|
|
|
+ count = 1
|
|
|
|
+
|
|
|
|
+ for to_sleep > estimate {
|
|
|
|
+ start := tick_now()
|
|
|
|
+ sleep(1 * Millisecond)
|
|
|
|
+
|
|
|
|
+ observed := tick_since(start)
|
|
|
|
+ to_sleep -= observed
|
|
|
|
+
|
|
|
|
+ count += 1
|
|
|
|
+
|
|
|
|
+ delta := observed - mean
|
|
|
|
+ mean += delta / count
|
|
|
|
+ m2 += delta * (observed - mean)
|
|
|
|
+ stddev := intrinsics.sqrt(f64(m2) / f64(count - 1))
|
|
|
|
+ estimate = mean + Duration(stddev)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ start := tick_now()
|
|
|
|
+ for to_sleep > tick_since(start) {
|
|
|
|
+ // prevent the spinlock from taking the thread hostage, still accurate enough
|
|
|
|
+ _yield()
|
|
|
|
+ // NOTE: it might be possible that it yields for too long, in that case it should spinlock freely for a while
|
|
|
|
+ // TODO: needs actual testing done to check if that's the case
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
ABSOLUTE_ZERO_YEAR :: i64(-292277022399) // Day is chosen so that 2001-01-01 is Monday in the calculations
|
|
ABSOLUTE_ZERO_YEAR :: i64(-292277022399) // Day is chosen so that 2001-01-01 is Monday in the calculations
|
|
ABSOLUTE_TO_INTERNAL :: i64(-9223371966579724800) // i64((ABSOLUTE_ZERO_YEAR - 1) * 365.2425 * SECONDS_PER_DAY);
|
|
ABSOLUTE_TO_INTERNAL :: i64(-9223371966579724800) // i64((ABSOLUTE_ZERO_YEAR - 1) * 365.2425 * SECONDS_PER_DAY);
|