blob: fd906d03c3ace3e909389a9c8079f7e696eab7af [file] [log] [blame] [view]
Harald Alvestrand5cb983b2021-06-01 07:46:541<?% config.freshness.owner = 'hta' %?>
2<?% config.freshness.reviewed = '2021-05-31' %?>
3
4# Basic concepts and primitives
5
6## Time
7
8Internally, time is represent using the [webrtc::Timestamp][1] class. This
9represents
10time with a resolution of one microsecond, using a 64-bit integer, and provides
11converters to milliseconds or seconds as needed.
12
13All timestamps need to be measured from the system monotonic time.
14
15The epoch is not specified (because we can't always know if the system clock is
16correct), but whenever an absolute epoch is needed, the Unix time
17epoch (Jan 1, 1970 at 0:00 GMT) is used.
18
19Conversion from/to other formats (for example milliseconds, NTP times,
20timestamp strings) should happen as close to the interface requiring that
21format as possible.
22
23NOTE: There are parts of the codebase that don't use Timestamp, parts of the
24codebase that use the NTP epoch, and parts of the codebase that don't use the
25monotonic clock. They need to
26be updated.
27
28## Threads
29
30All execution happens on a TaskQueue instance. How a TaskQueue is implemented
31varies by platform, but they all have the [webrtc::TaskQueueBase][3] API.
32
33This API offers primitives for posting tasks, with or without delay.
34
35Some core parts use the [rtc::Thread][2], which is a subclass of TaskQueueBase.
36This may contain a SocketServer for processing I/O, and is used for policing
37certain calling pattern between a few core threads (the NetworkThread cannot
38do Invoke on the Worker thread, for instance).
39
40## Synchronization primitives
41
42### PostTask and thread-guarded variables
43
44The preferred method for synchronization is to post tasks between threads,
45and to let each thread take care of its own variables (lock-free programming).
46All variables in
47classes intended to be used with multiple threads should therefore be
48annotated with RTC_GUARDED_BY(thread).
49
50For classes used with only one thread, the recommended pattern is to let
51them own a webrtc::SequenceChecker (conventionally named sequence_checker_)
52and let all variables be RTC_GUARDED_BY(sequence_checker_).
53
54Member variables marked const do not need to be guarded, since they never
55change. (But note that they may point to objects that can change!)
56
57When posting tasks with callbacks, it is the duty of the caller to check
58that the object one is calling back into still exists when the callback
59is made. A helper for this task is the [webrtc::ScopedTaskSafety][5]
60flag, which can automatically drop callbacks in this situation, and
61associated classes.
62
63### Synchronization primitives to be used when needed
64
65When it is absolutely necessary to let one thread wait for another thread
66to do something, Thread::Invoke can be used. This function is DISCOURAGED,
67since it leads to performance issues, but is currently still widespread.
68
69When it is absolutely necessary to access one variable from multiple threads,
70the webrtc::Mutex can be used. Such variables MUST be marked up with
71RTC_GUARDED_BY(mutex), to allow static analysis that lessens the chance of
72deadlocks or unintended consequences.
73
74### Synchronization primitives that are being removed
75The following non-exhaustive list of synchronization primitives are
76in the (slow) process of being removed from the codebase.
77
78* sigslot. Use [webrtc::CallbackList][4] instead, or, when there's only one
79 signal consumer, a single std::function.
80
81* AsyncInvoker.
82
Harald Alvestrand0fe60bd2021-06-22 07:47:3483* RecursiveCriticalSection. Try to use [webrtc::Mutex][6] instead, and don't recurse.
84
Harald Alvestrand31b03e92021-11-02 10:54:3885## Enum-To-String functions
86If there is a need to convert an enum to a string representation, such as for
87enums exposed at the Javascript API interface, the recommended way is to write
88a function named AsString, declared "static constexpr" and returning an
89absl::string_view. The declaration should be right after the enum declaration,
90in the same scope; the implementation (which must be marked "inline") should
91be at the end of the same header file.
Harald Alvestrand5cb983b2021-06-01 07:46:5492
Harald Alvestrand31b03e92021-11-02 10:54:3893If the enum is not defined within a class, the "static" keyword is not needed.
Harald Alvestrand5cb983b2021-06-01 07:46:5494
95[1]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/units/timestamp.h;drc=b95d90b78a3491ef8e8aa0640dd521515ec881ca;l=29
96[2]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/rtc_base/thread.h;drc=1107751b6f11c35259a1c5c8a0f716e227b7e3b4;l=194
97[3]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/task_queue/task_queue_base.h;drc=1107751b6f11c35259a1c5c8a0f716e227b7e3b4;l=25
98[4]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/rtc_base/callback_list.h;drc=54b91412de3f579a2d5ccdead6e04cc2cc5ca3a1;l=162
99[5]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/rtc_base/task_utils/pending_task_safety_flag.h;drc=86ee89f73e4f4799b3ebcc0b5c65837c9601fe6d;l=117
Harald Alvestrand0fe60bd2021-06-22 07:47:34100[6]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/rtc_base/synchronization/mutex.h;drc=0d3c09a8fe5f12dfbc9f1bcd5790fda8830624ec;l=40