1 /* SPDX-License-Identifier: GPL-3.0-or-later
2  * Copyright © 2016-2020 The TokTok team.
3  * Copyright © 2014 Tox project.
4  */
5 #ifndef C_TOXCORE_TOXCORE_MONO_TIME_H
6 #define C_TOXCORE_TOXCORE_MONO_TIME_H
7 
8 #include <stdbool.h>
9 #include <stdint.h>
10 
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14 
15 #ifndef MONO_TIME_DEFINED
16 #define MONO_TIME_DEFINED
17 /**
18  * The timer portion of the toxcore event loop.
19  *
20  * We update the time exactly once per tox_iterate call. Programs built on lower
21  * level APIs such as the DHT bootstrap node must update the time manually in
22  * each iteration.
23  *
24  * Time is kept per Tox instance, not globally, even though "time" as a concept
25  * is global. This is because by definition `mono_time` represents the time at
26  * the start of an iteration, and also by definition the time when all network
27  * events for the current iteration occurred. This affects mainly two situations:
28  *
29  * 1. Two timers started in the same iteration: e.g. two timers set to expire in
30  *    10 seconds will both expire at the same time, i.e. about 10 seconds later.
31  *    If the time were global, `mono_time` would be a random number that is
32  *    either the time at the start of an iteration, or 1 second later (since the
33  *    timer resolution is 1 second). This can happen when one update happens at
34  *    e.g. 10:00:00.995 and a few milliseconds later a concurrently running
35  *    instance updates the time at 10:00:01.005, making one timer expire a
36  *    second after the other.
37  * 2. One timer based on an event: if we want to encode a behaviour of a timer
38  *    expiring e.g. 10 seconds after a network event occurred, we simply start a
39  *    timer in the event handler. If a concurrent instance updates the time
40  *    underneath us, it may instead expire 9 seconds after the event.
41  *
42  * Both these situations cause incorrect behaviour randomly. In practice,
43  * toxcore is somewhat robust against strange timer behaviour, but the
44  * implementation should at least theoretically match the specification.
45  */
46 typedef struct Mono_Time Mono_Time;
47 #endif /* MONO_TIME_DEFINED */
48 
49 Mono_Time *mono_time_new(void);
50 void mono_time_free(Mono_Time *mono_time);
51 
52 /**
53  * Update mono_time; subsequent calls to mono_time_get or mono_time_is_timeout
54  * will use the time at the call to mono_time_update.
55  */
56 void mono_time_update(Mono_Time *mono_time);
57 
58 /**
59  * Return unix time since epoch in seconds.
60  */
61 uint64_t mono_time_get(const Mono_Time *mono_time);
62 
63 /**
64  * Return true iff timestamp is at least timeout seconds in the past.
65  */
66 bool mono_time_is_timeout(const Mono_Time *mono_time, uint64_t timestamp, uint64_t timeout);
67 
68 /**
69  * Return current monotonic time in milliseconds (ms). The starting point is
70  * unspecified.
71  */
72 uint64_t current_time_monotonic(Mono_Time *mono_time);
73 
74 typedef uint64_t mono_time_current_time_cb(Mono_Time *mono_time, void *user_data);
75 
76 /* Override implementation of current_time_monotonic() (for tests).
77  *
78  * The caller is obligated to ensure that current_time_monotonic() continues
79  * to increase monotonically.
80  */
81 void mono_time_set_current_time_callback(Mono_Time *mono_time,
82         mono_time_current_time_cb *current_time_callback, void *user_data);
83 
84 #ifdef __cplusplus
85 }
86 #endif
87 
88 #endif // C_TOXCORE_TOXCORE_MONO_TIME_H
89