summaryrefslogtreecommitdiff
path: root/toxcore/mono_time.c
diff options
context:
space:
mode:
authoriphydf <iphydf@users.noreply.github.com>2018-08-26 20:34:26 +0000
committeriphydf <iphydf@users.noreply.github.com>2018-09-03 20:03:47 +0000
commit6872c14e1a02445d945623ee6e85230c5d7ecbce (patch)
tree30d90b93445976e56b96946b6e87b764eddd48a8 /toxcore/mono_time.c
parentd296490a742b226fc17a71cf96ab73fc16719b20 (diff)
Avoid use of global mutable state in mono_time on win32.
This uses a trick to get read-write access to `this` from a `const` member function, similar to C++ `mutable`, but uglier.
Diffstat (limited to 'toxcore/mono_time.c')
-rw-r--r--toxcore/mono_time.c97
1 files changed, 48 insertions, 49 deletions
diff --git a/toxcore/mono_time.c b/toxcore/mono_time.c
index aa272749..6e4bc067 100644
--- a/toxcore/mono_time.c
+++ b/toxcore/mono_time.c
@@ -28,12 +28,52 @@
28struct Mono_Time { 28struct Mono_Time {
29 uint64_t time; 29 uint64_t time;
30 uint64_t base_time; 30 uint64_t base_time;
31#ifdef OS_WIN32
32 uint64_t last_clock_mono;
33 uint64_t add_clock_mono;
34#endif
31 35
32 mono_time_current_time_cb *current_time_callback; 36 mono_time_current_time_cb *current_time_callback;
33 void *user_data; 37 void *user_data;
34}; 38};
35 39
36static mono_time_current_time_cb current_time_monotonic_default; 40static uint64_t current_time_monotonic_default(Mono_Time *mono_time, void *user_data)
41{
42 uint64_t time;
43#ifdef OS_WIN32
44 uint64_t old_add_clock_mono = mono_time->add_clock_mono;
45 time = (uint64_t)GetTickCount() + mono_time->add_clock_mono;
46
47 /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race
48 * conditions when multiple threads call this function at once */
49 if (time + 0x10000 < mono_time->last_clock_mono) {
50 uint32_t add = ~0;
51 /* use old_add_clock_mono rather than simply incrementing add_clock_mono, to handle the case that many threads
52 * simultaneously detect an overflow */
53 mono_time->add_clock_mono = old_add_clock_mono + add;
54 time += add;
55 }
56
57 mono_time->last_clock_mono = time;
58#else
59 struct timespec clock_mono;
60#if defined(__APPLE__)
61 clock_serv_t muhclock;
62 mach_timespec_t machtime;
63
64 host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock);
65 clock_get_time(muhclock, &machtime);
66 mach_port_deallocate(mach_task_self(), muhclock);
67
68 clock_mono.tv_sec = machtime.tv_sec;
69 clock_mono.tv_nsec = machtime.tv_nsec;
70#else
71 clock_gettime(CLOCK_MONOTONIC, &clock_mono);
72#endif
73 time = 1000ULL * clock_mono.tv_sec + (clock_mono.tv_nsec / 1000000ULL);
74#endif
75 return time;
76}
37 77
38Mono_Time *mono_time_new(void) 78Mono_Time *mono_time_new(void)
39{ 79{
@@ -46,6 +86,11 @@ Mono_Time *mono_time_new(void)
46 mono_time->current_time_callback = current_time_monotonic_default; 86 mono_time->current_time_callback = current_time_monotonic_default;
47 mono_time->user_data = nullptr; 87 mono_time->user_data = nullptr;
48 88
89#ifdef OS_WIN32
90 mono_time->last_clock_mono = 0;
91 mono_time->add_clock_mono = 0;
92#endif
93
49 mono_time->time = 0; 94 mono_time->time = 0;
50 mono_time->base_time = (uint64_t)time(nullptr) - (current_time_monotonic(mono_time) / 1000ULL); 95 mono_time->base_time = (uint64_t)time(nullptr) - (current_time_monotonic(mono_time) / 1000ULL);
51 96
@@ -87,53 +132,7 @@ void mono_time_set_current_time_callback(Mono_Time *mono_time,
87} 132}
88 133
89/* return current monotonic time in milliseconds (ms). */ 134/* return current monotonic time in milliseconds (ms). */
90uint64_t current_time_monotonic(const Mono_Time *mono_time) 135uint64_t current_time_monotonic(Mono_Time *mono_time)
91{ 136{
92 return mono_time->current_time_callback(mono_time->user_data); 137 return mono_time->current_time_callback(mono_time, mono_time->user_data);
93}
94
95//!TOKSTYLE-
96// No global mutable state in Tokstyle.
97#ifdef OS_WIN32
98static uint64_t last_clock_mono;
99static uint64_t add_clock_mono;
100#endif
101//!TOKSTYLE+
102
103static uint64_t current_time_monotonic_default(void *user_data)
104{
105 uint64_t time;
106#ifdef OS_WIN32
107 uint64_t old_add_clock_mono = add_clock_mono;
108 time = (uint64_t)GetTickCount() + add_clock_mono;
109
110 /* Check if time has decreased because of 32 bit wrap from GetTickCount(), while avoiding false positives from race
111 * conditions when multiple threads call this function at once */
112 if (time + 0x10000 < last_clock_mono) {
113 uint32_t add = ~0;
114 /* use old_add_clock_mono rather than simply incrementing add_clock_mono, to handle the case that many threads
115 * simultaneously detect an overflow */
116 add_clock_mono = old_add_clock_mono + add;
117 time += add;
118 }
119
120 last_clock_mono = time;
121#else
122 struct timespec clock_mono;
123#if defined(__APPLE__)
124 clock_serv_t muhclock;
125 mach_timespec_t machtime;
126
127 host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock);
128 clock_get_time(muhclock, &machtime);
129 mach_port_deallocate(mach_task_self(), muhclock);
130
131 clock_mono.tv_sec = machtime.tv_sec;
132 clock_mono.tv_nsec = machtime.tv_nsec;
133#else
134 clock_gettime(CLOCK_MONOTONIC, &clock_mono);
135#endif
136 time = 1000ULL * clock_mono.tv_sec + (clock_mono.tv_nsec / 1000000ULL);
137#endif
138 return time;
139} 138}