Add support for setting a custom monotonic time function in mono_time

This commit is contained in:
zugz (tox) 2018-08-17 19:22:58 +02:00
parent acc19a202f
commit 01e2cc55cb
No known key found for this signature in database
GPG Key ID: 6F2BDA289D04F249
3 changed files with 61 additions and 2 deletions

View File

@ -28,8 +28,13 @@
struct Mono_Time {
uint64_t time;
uint64_t base_time;
mono_time_current_time_cb *current_time_callback;
void *user_data;
};
static mono_time_current_time_cb current_time_monotonic_default;
Mono_Time *mono_time_new(void)
{
Mono_Time *mono_time = (Mono_Time *)malloc(sizeof(Mono_Time));
@ -38,6 +43,9 @@ Mono_Time *mono_time_new(void)
return nullptr;
}
mono_time->current_time_callback = current_time_monotonic_default;
mono_time->user_data = nullptr;
mono_time->time = 0;
mono_time->base_time = (uint64_t)time(nullptr) - (current_time_monotonic(mono_time) / 1000ULL);
@ -66,6 +74,24 @@ bool mono_time_is_timeout(const Mono_Time *mono_time, uint64_t timestamp, uint64
return timestamp + timeout <= mono_time_get(mono_time);
}
void mono_time_set_current_time_callback(Mono_Time *mono_time,
mono_time_current_time_cb *current_time_callback, void *user_data)
{
if (current_time_callback == nullptr) {
mono_time->current_time_callback = current_time_monotonic_default;
mono_time->user_data = nullptr;
} else {
mono_time->current_time_callback = current_time_callback;
mono_time->user_data = user_data;
}
}
/* return current monotonic time in milliseconds (ms). */
uint64_t current_time_monotonic(const Mono_Time *mono_time)
{
return mono_time->current_time_callback(mono_time->user_data);
}
//!TOKSTYLE-
// No global mutable state in Tokstyle.
#ifdef OS_WIN32
@ -74,8 +100,7 @@ static uint64_t add_clock_mono;
#endif
//!TOKSTYLE+
/* return current monotonic time in milliseconds (ms). */
uint64_t current_time_monotonic(const Mono_Time *mono_time)
static uint64_t current_time_monotonic_default(void *user_data)
{
uint64_t time;
#ifdef OS_WIN32

View File

@ -52,6 +52,16 @@ bool mono_time_is_timeout(const Mono_Time *mono_time, uint64_t timestamp, uint64
/* return current monotonic time in milliseconds (ms). */
uint64_t current_time_monotonic(const Mono_Time *mono_time);
typedef uint64_t mono_time_current_time_cb(void *user_data);
/* Override implementation of current_time_monotonic() (for tests).
*
* The caller is obligated to ensure that current_time_monotonic() continues
* to increase monotonically.
*/
void mono_time_set_current_time_callback(Mono_Time *mono_time,
mono_time_current_time_cb *current_time_callback, void *user_data);
#ifdef __cplusplus
}
#endif

View File

@ -35,4 +35,28 @@ TEST(MonoTime, IsTimeout) {
mono_time_free(mono_time);
}
static uint64_t test_current_time_callback(void *user_data) { return *(uint64_t *)user_data; }
TEST(MonoTime, CustomTime) {
Mono_Time *mono_time = mono_time_new();
uint64_t test_time = current_time_monotonic(mono_time) + 42137;
mono_time_set_current_time_callback(mono_time, test_current_time_callback, &test_time);
mono_time_update(mono_time);
EXPECT_EQ(current_time_monotonic(mono_time), test_time);
uint64_t const start = mono_time_get(mono_time);
test_time += 7000;
mono_time_update(mono_time);
EXPECT_EQ(mono_time_get(mono_time) - start, 7);
EXPECT_EQ(current_time_monotonic(mono_time), test_time);
mono_time_free(mono_time);
}
} // namespace