| <!-- go/cmark --> |
| |
| <!--* freshness: {owner: 'tommi' reviewed: '2026-06-17'} *--> |
| |
| # API Threading Design considerations |
| |
| The header files in this directory form the API to the WebRTC library that is |
| intended for client applications' use. |
| |
| This API is designed to be used on top of a multithreaded runtime. |
| |
| The public API functions are designed to be called from a single thread\* (the |
| "client thread"), and can do internal dispatching to the thread where activity |
| needs to happen. Those threads can be passed in by the client, typically as |
| arguments to factory constructors, or they can be created by the library if |
| factory constructors that don't take threads are used. |
| |
| Many of the functions are designed to be used in an asynchronous manner, where a |
| function is called to initiate an activity, and a callback will be called when |
| the activity is completed, or a handler function will be called on an observer |
| object when interesting events happen. |
| |
| Note: Often, even functions that look like simple functions (such as information |
| query functions) will need to jump between threads to perform their function - |
| which means that things may happen on other threads between calls; writing |
| "increment(x); increment(x)" is not a safe way to increment X by exactly two, |
| since the increment function may have jumped to another thread that already had |
| a queue of things to handle, causing large amounts of other activity to have |
| intervened between the two calls. |
| |
| (\*) The term "thread" is used here to denote any construct that guarantees |
| sequential execution - other names for such constructs are task runners and |
| sequenced task queues. |
| |
| ## Client threads and callbacks |
| |
| At the moment, the API does not give any guarantee on which thread\* the |
| callbacks and events are called on. So it's best to write all callback and event |
| handlers like this (pseudocode): |
| |
| ``` |
| void ObserverClass::Handler(event) { |
| if (!called_on_client_thread()) { |
| dispatch_to_client_thread(bind(handler(event))); |
| return; |
| } |
| // Process event, we're now on the right thread |
| } |
| ``` |
| |
| It is generally NOT safe to call WebRTC library functions from the callback; if |
| this is wanted, one should instead dispatch a task on an appropriate thread to |
| do so. |
| |
| In the future, the implementation may evolve to crash or return an error if this |
| happens. |
| |
| In the future, the implementation may change to always call the callbacks and |
| event handlers on the client thread. |
| |
| ## Implementation considerations |
| |
| The C++ classes that are part of the public API are also used to derive classes |
| that form part of the implementation. |
| |
| This should not directly concern users of the API, but may matter if one wants |
| to look at how the WebRTC library is implemented, or for legacy code that |
| directly accesses internal APIs. |
| |
| Many APIs are defined in terms of a "proxy object", which will do a blocking |
| dispatch of the function to another thread, and an "implementation object" which |
| will do the actual work, but can only be created, invoked and destroyed on its |
| "home thread". |
| |
| Usually, the classes are named "xxxInterface" (in api/), "xxxProxy" and "xxx" |
| (not in api/). WebRTC users should only need to depend on the files in api/. In |
| many cases, the "xxxProxy" and "xxx" classes are subclasses of "xxxInterface", |
| but this property is an implementation feature only, and should not be relied |
| upon. |
| |
| The threading properties of these internal APIs are NOT documented in this note, |
| and need to be understood by inspecting those classes. |