xref: /aosp_15_r20/external/pigweed/pw_sync/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_sync:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker=======
4*61c4878aSAndroid Build Coastguard Workerpw_sync
5*61c4878aSAndroid Build Coastguard Worker=======
6*61c4878aSAndroid Build Coastguard WorkerThe ``pw_sync`` module contains utilities for synchronizing between threads
7*61c4878aSAndroid Build Coastguard Workerand/or interrupts through signaling primitives and critical section lock
8*61c4878aSAndroid Build Coastguard Workerprimitives.
9*61c4878aSAndroid Build Coastguard Worker
10*61c4878aSAndroid Build Coastguard Worker.. Warning::
11*61c4878aSAndroid Build Coastguard Worker
12*61c4878aSAndroid Build Coastguard Worker   This module is still under construction, the API is not yet stable.
13*61c4878aSAndroid Build Coastguard Worker
14*61c4878aSAndroid Build Coastguard Worker.. Note::
15*61c4878aSAndroid Build Coastguard Worker
16*61c4878aSAndroid Build Coastguard Worker   The objects in this module do not have an Init() style public API which is
17*61c4878aSAndroid Build Coastguard Worker   common in many RTOS C APIs. Instead, they rely on being able to invoke the
18*61c4878aSAndroid Build Coastguard Worker   native initialization APIs for synchronization primitives during C++
19*61c4878aSAndroid Build Coastguard Worker   construction.
20*61c4878aSAndroid Build Coastguard Worker
21*61c4878aSAndroid Build Coastguard Worker   In order to support global statically constructed synchronization without
22*61c4878aSAndroid Build Coastguard Worker   constexpr constructors, the user and/or backend **MUST** ensure that any
23*61c4878aSAndroid Build Coastguard Worker   initialization required in your environment is done prior to the creation
24*61c4878aSAndroid Build Coastguard Worker   and/or initialization of the native synchronization primitives
25*61c4878aSAndroid Build Coastguard Worker   (e.g. kernel initialization).
26*61c4878aSAndroid Build Coastguard Worker
27*61c4878aSAndroid Build Coastguard Worker--------------------------------
28*61c4878aSAndroid Build Coastguard WorkerCritical Section Lock Primitives
29*61c4878aSAndroid Build Coastguard Worker--------------------------------
30*61c4878aSAndroid Build Coastguard WorkerThe critical section lock primitives provided by this module comply with
31*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_,
32*61c4878aSAndroid Build Coastguard Worker`Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_, and where
33*61c4878aSAndroid Build Coastguard Workerrelevant
34*61c4878aSAndroid Build Coastguard Worker`TimedLockable <https://en.cppreference.com/w/cpp/named_req/TimedLockable>`_ C++
35*61c4878aSAndroid Build Coastguard Workernamed requirements. This means that they are compatible with existing helpers in
36*61c4878aSAndroid Build Coastguard Workerthe STL's ``<mutex>`` thread support library. For example `std::lock_guard
37*61c4878aSAndroid Build Coastguard Worker<https://en.cppreference.com/w/cpp/thread/lock_guard>`_ and `std::unique_lock
38*61c4878aSAndroid Build Coastguard Worker<https://en.cppreference.com/w/cpp/thread/unique_lock>`_ can be directly used.
39*61c4878aSAndroid Build Coastguard Worker
40*61c4878aSAndroid Build Coastguard WorkerMutex
41*61c4878aSAndroid Build Coastguard Worker=====
42*61c4878aSAndroid Build Coastguard WorkerThe Mutex is a synchronization primitive that can be used to protect shared data
43*61c4878aSAndroid Build Coastguard Workerfrom being simultaneously accessed by multiple threads. It offers exclusive,
44*61c4878aSAndroid Build Coastguard Workernon-recursive ownership semantics where priority inheritance is used to solve
45*61c4878aSAndroid Build Coastguard Workerthe classic priority-inversion problem.
46*61c4878aSAndroid Build Coastguard Worker
47*61c4878aSAndroid Build Coastguard WorkerThe Mutex's API is C++11 STL
48*61c4878aSAndroid Build Coastguard Worker`std::mutex <https://en.cppreference.com/w/cpp/thread/mutex>`_ like,
49*61c4878aSAndroid Build Coastguard Workermeaning it is a
50*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_
51*61c4878aSAndroid Build Coastguard Workerand `Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_.
52*61c4878aSAndroid Build Coastguard Worker
53*61c4878aSAndroid Build Coastguard Worker.. list-table::
54*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
55*61c4878aSAndroid Build Coastguard Worker
56*61c4878aSAndroid Build Coastguard Worker   * - Supported on
57*61c4878aSAndroid Build Coastguard Worker     - Backend module
58*61c4878aSAndroid Build Coastguard Worker   * - FreeRTOS
59*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_freertos`
60*61c4878aSAndroid Build Coastguard Worker   * - ThreadX
61*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_threadx`
62*61c4878aSAndroid Build Coastguard Worker   * - embOS
63*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_embos`
64*61c4878aSAndroid Build Coastguard Worker   * - STL
65*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_stl`
66*61c4878aSAndroid Build Coastguard Worker   * - Baremetal
67*61c4878aSAndroid Build Coastguard Worker     - Planned
68*61c4878aSAndroid Build Coastguard Worker   * - Zephyr
69*61c4878aSAndroid Build Coastguard Worker     - Planned
70*61c4878aSAndroid Build Coastguard Worker   * - CMSIS-RTOS API v2 & RTX5
71*61c4878aSAndroid Build Coastguard Worker     - Planned
72*61c4878aSAndroid Build Coastguard Worker
73*61c4878aSAndroid Build Coastguard WorkerC++
74*61c4878aSAndroid Build Coastguard Worker---
75*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::Mutex
76*61c4878aSAndroid Build Coastguard Worker   :members:
77*61c4878aSAndroid Build Coastguard Worker
78*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::Mutex
79*61c4878aSAndroid Build Coastguard Worker
80*61c4878aSAndroid Build Coastguard Worker.. list-table::
81*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
82*61c4878aSAndroid Build Coastguard Worker   :widths: 70 10 10 10
83*61c4878aSAndroid Build Coastguard Worker
84*61c4878aSAndroid Build Coastguard Worker   * - Safe to use in context
85*61c4878aSAndroid Build Coastguard Worker     - Thread
86*61c4878aSAndroid Build Coastguard Worker     - Interrupt
87*61c4878aSAndroid Build Coastguard Worker     - NMI
88*61c4878aSAndroid Build Coastguard Worker   * - :cpp:class:`pw::sync::Mutex::Mutex`
89*61c4878aSAndroid Build Coastguard Worker     - ✔
90*61c4878aSAndroid Build Coastguard Worker     -
91*61c4878aSAndroid Build Coastguard Worker     -
92*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw::sync::Mutex::~Mutex`
93*61c4878aSAndroid Build Coastguard Worker     - ✔
94*61c4878aSAndroid Build Coastguard Worker     -
95*61c4878aSAndroid Build Coastguard Worker     -
96*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`lock`
97*61c4878aSAndroid Build Coastguard Worker     - ✔
98*61c4878aSAndroid Build Coastguard Worker     -
99*61c4878aSAndroid Build Coastguard Worker     -
100*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_lock`
101*61c4878aSAndroid Build Coastguard Worker     - ✔
102*61c4878aSAndroid Build Coastguard Worker     -
103*61c4878aSAndroid Build Coastguard Worker     -
104*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`unlock`
105*61c4878aSAndroid Build Coastguard Worker     - ✔
106*61c4878aSAndroid Build Coastguard Worker     -
107*61c4878aSAndroid Build Coastguard Worker     -
108*61c4878aSAndroid Build Coastguard Worker
109*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
110*61c4878aSAndroid Build Coastguard Worker
111*61c4878aSAndroid Build Coastguard Worker
112*61c4878aSAndroid Build Coastguard WorkerExamples in C++
113*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^
114*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
115*61c4878aSAndroid Build Coastguard Worker
116*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/mutex.h"
117*61c4878aSAndroid Build Coastguard Worker
118*61c4878aSAndroid Build Coastguard Worker   pw::sync::Mutex mutex;
119*61c4878aSAndroid Build Coastguard Worker
120*61c4878aSAndroid Build Coastguard Worker   void ThreadSafeCriticalSection() {
121*61c4878aSAndroid Build Coastguard Worker     mutex.lock();
122*61c4878aSAndroid Build Coastguard Worker     NotThreadSafeCriticalSection();
123*61c4878aSAndroid Build Coastguard Worker     mutex.unlock();
124*61c4878aSAndroid Build Coastguard Worker   }
125*61c4878aSAndroid Build Coastguard Worker
126*61c4878aSAndroid Build Coastguard Worker
127*61c4878aSAndroid Build Coastguard WorkerAlternatively you can use C++'s RAII helpers to ensure you always unlock.
128*61c4878aSAndroid Build Coastguard Worker
129*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
130*61c4878aSAndroid Build Coastguard Worker
131*61c4878aSAndroid Build Coastguard Worker   #include <mutex>
132*61c4878aSAndroid Build Coastguard Worker
133*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/mutex.h"
134*61c4878aSAndroid Build Coastguard Worker
135*61c4878aSAndroid Build Coastguard Worker   pw::sync::Mutex mutex;
136*61c4878aSAndroid Build Coastguard Worker
137*61c4878aSAndroid Build Coastguard Worker   void ThreadSafeCriticalSection() {
138*61c4878aSAndroid Build Coastguard Worker     std::lock_guard lock(mutex);
139*61c4878aSAndroid Build Coastguard Worker     NotThreadSafeCriticalSection();
140*61c4878aSAndroid Build Coastguard Worker   }
141*61c4878aSAndroid Build Coastguard Worker
142*61c4878aSAndroid Build Coastguard WorkerC
143*61c4878aSAndroid Build Coastguard Worker-
144*61c4878aSAndroid Build Coastguard WorkerThe Mutex must be created in C++, however it can be passed into C using the
145*61c4878aSAndroid Build Coastguard Worker``pw_sync_Mutex`` opaque struct alias.
146*61c4878aSAndroid Build Coastguard Worker
147*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_sync_Mutex_Lock
148*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_sync_Mutex_TryLock
149*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_sync_Mutex_Unlock
150*61c4878aSAndroid Build Coastguard Worker
151*61c4878aSAndroid Build Coastguard Worker.. list-table::
152*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
153*61c4878aSAndroid Build Coastguard Worker   :widths: 70 10 10 10
154*61c4878aSAndroid Build Coastguard Worker
155*61c4878aSAndroid Build Coastguard Worker   * - Safe to use in context
156*61c4878aSAndroid Build Coastguard Worker     - Thread
157*61c4878aSAndroid Build Coastguard Worker     - Interrupt
158*61c4878aSAndroid Build Coastguard Worker     - NMI
159*61c4878aSAndroid Build Coastguard Worker   * - ``void pw_sync_Mutex_Lock``
160*61c4878aSAndroid Build Coastguard Worker     - ✔
161*61c4878aSAndroid Build Coastguard Worker     -
162*61c4878aSAndroid Build Coastguard Worker     -
163*61c4878aSAndroid Build Coastguard Worker   * - ``bool pw_sync_Mutex_TryLock``
164*61c4878aSAndroid Build Coastguard Worker     - ✔
165*61c4878aSAndroid Build Coastguard Worker     -
166*61c4878aSAndroid Build Coastguard Worker     -
167*61c4878aSAndroid Build Coastguard Worker   * - ``void pw_sync_Mutex_Unlock``
168*61c4878aSAndroid Build Coastguard Worker     - ✔
169*61c4878aSAndroid Build Coastguard Worker     -
170*61c4878aSAndroid Build Coastguard Worker     -
171*61c4878aSAndroid Build Coastguard Worker
172*61c4878aSAndroid Build Coastguard WorkerExample in C
173*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^
174*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
175*61c4878aSAndroid Build Coastguard Worker
176*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/mutex.h"
177*61c4878aSAndroid Build Coastguard Worker
178*61c4878aSAndroid Build Coastguard Worker   pw::sync::Mutex mutex;
179*61c4878aSAndroid Build Coastguard Worker
180*61c4878aSAndroid Build Coastguard Worker   extern pw_sync_Mutex mutex;  // This can only be created in C++.
181*61c4878aSAndroid Build Coastguard Worker
182*61c4878aSAndroid Build Coastguard Worker   void ThreadSafeCriticalSection(void) {
183*61c4878aSAndroid Build Coastguard Worker     pw_sync_Mutex_Lock(&mutex);
184*61c4878aSAndroid Build Coastguard Worker     NotThreadSafeCriticalSection();
185*61c4878aSAndroid Build Coastguard Worker     pw_sync_Mutex_Unlock(&mutex);
186*61c4878aSAndroid Build Coastguard Worker   }
187*61c4878aSAndroid Build Coastguard Worker
188*61c4878aSAndroid Build Coastguard WorkerTimedMutex
189*61c4878aSAndroid Build Coastguard Worker==========
190*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync
191*61c4878aSAndroid Build Coastguard Worker
192*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`TimedMutex` is an extension of the Mutex which offers timeout
193*61c4878aSAndroid Build Coastguard Workerand deadline based semantics.
194*61c4878aSAndroid Build Coastguard Worker
195*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`TimedMutex`'s API is C++11 STL
196*61c4878aSAndroid Build Coastguard Worker`std::timed_mutex <https://en.cppreference.com/w/cpp/thread/timed_mutex>`_ like,
197*61c4878aSAndroid Build Coastguard Workermeaning it is a
198*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_,
199*61c4878aSAndroid Build Coastguard Worker`Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_, and
200*61c4878aSAndroid Build Coastguard Worker`TimedLockable <https://en.cppreference.com/w/cpp/named_req/TimedLockable>`_.
201*61c4878aSAndroid Build Coastguard Worker
202*61c4878aSAndroid Build Coastguard WorkerNote that the :cpp:class:`TimedMutex` is a derived :cpp:class:`Mutex` class,
203*61c4878aSAndroid Build Coastguard Workermeaning that a :cpp:class:`TimedMutex` can be used by someone who needs the
204*61c4878aSAndroid Build Coastguard Workerbasic :cpp:class:`Mutex`. This is in contrast to the C++ STL's
205*61c4878aSAndroid Build Coastguard Worker`std::timed_mutex <https://en.cppreference.com/w/cpp/thread/timed_mutex>`_.
206*61c4878aSAndroid Build Coastguard Worker
207*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
208*61c4878aSAndroid Build Coastguard Worker
209*61c4878aSAndroid Build Coastguard Worker.. list-table::
210*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
211*61c4878aSAndroid Build Coastguard Worker
212*61c4878aSAndroid Build Coastguard Worker   * - Supported on
213*61c4878aSAndroid Build Coastguard Worker     - Backend module
214*61c4878aSAndroid Build Coastguard Worker   * - FreeRTOS
215*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_freertos`
216*61c4878aSAndroid Build Coastguard Worker   * - ThreadX
217*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_threadx`
218*61c4878aSAndroid Build Coastguard Worker   * - embOS
219*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_embos`
220*61c4878aSAndroid Build Coastguard Worker   * - STL
221*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_stl`
222*61c4878aSAndroid Build Coastguard Worker   * - Zephyr
223*61c4878aSAndroid Build Coastguard Worker     - Planned
224*61c4878aSAndroid Build Coastguard Worker   * - CMSIS-RTOS API v2 & RTX5
225*61c4878aSAndroid Build Coastguard Worker     - Planned
226*61c4878aSAndroid Build Coastguard Worker
227*61c4878aSAndroid Build Coastguard WorkerC++
228*61c4878aSAndroid Build Coastguard Worker---
229*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::TimedMutex
230*61c4878aSAndroid Build Coastguard Worker   :members:
231*61c4878aSAndroid Build Coastguard Worker
232*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::TimedMutex
233*61c4878aSAndroid Build Coastguard Worker
234*61c4878aSAndroid Build Coastguard Worker.. list-table::
235*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
236*61c4878aSAndroid Build Coastguard Worker   :widths: 70 10 10 10
237*61c4878aSAndroid Build Coastguard Worker
238*61c4878aSAndroid Build Coastguard Worker   * - Safe to use in context
239*61c4878aSAndroid Build Coastguard Worker     - Thread
240*61c4878aSAndroid Build Coastguard Worker     - Interrupt
241*61c4878aSAndroid Build Coastguard Worker     - NMI
242*61c4878aSAndroid Build Coastguard Worker   * - :cpp:class:`pw::sync::TimedMutex::TimedMutex`
243*61c4878aSAndroid Build Coastguard Worker     - ✔
244*61c4878aSAndroid Build Coastguard Worker     -
245*61c4878aSAndroid Build Coastguard Worker     -
246*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw::sync::TimedMutex::~TimedMutex`
247*61c4878aSAndroid Build Coastguard Worker     - ✔
248*61c4878aSAndroid Build Coastguard Worker     -
249*61c4878aSAndroid Build Coastguard Worker     -
250*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw::sync::Mutex::lock`
251*61c4878aSAndroid Build Coastguard Worker     - ✔
252*61c4878aSAndroid Build Coastguard Worker     -
253*61c4878aSAndroid Build Coastguard Worker     -
254*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw::sync::Mutex::try_lock`
255*61c4878aSAndroid Build Coastguard Worker     - ✔
256*61c4878aSAndroid Build Coastguard Worker     -
257*61c4878aSAndroid Build Coastguard Worker     -
258*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_lock_for`
259*61c4878aSAndroid Build Coastguard Worker     - ✔
260*61c4878aSAndroid Build Coastguard Worker     -
261*61c4878aSAndroid Build Coastguard Worker     -
262*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_lock_until`
263*61c4878aSAndroid Build Coastguard Worker     - ✔
264*61c4878aSAndroid Build Coastguard Worker     -
265*61c4878aSAndroid Build Coastguard Worker     -
266*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw::sync::Mutex::unlock`
267*61c4878aSAndroid Build Coastguard Worker     - ✔
268*61c4878aSAndroid Build Coastguard Worker     -
269*61c4878aSAndroid Build Coastguard Worker     -
270*61c4878aSAndroid Build Coastguard Worker
271*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
272*61c4878aSAndroid Build Coastguard Worker
273*61c4878aSAndroid Build Coastguard Worker
274*61c4878aSAndroid Build Coastguard WorkerExamples in C++
275*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^
276*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
277*61c4878aSAndroid Build Coastguard Worker
278*61c4878aSAndroid Build Coastguard Worker   #include "pw_chrono/system_clock.h"
279*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/timed_mutex.h"
280*61c4878aSAndroid Build Coastguard Worker
281*61c4878aSAndroid Build Coastguard Worker   pw::sync::TimedMutex mutex;
282*61c4878aSAndroid Build Coastguard Worker
283*61c4878aSAndroid Build Coastguard Worker   bool ThreadSafeCriticalSectionWithTimeout(
284*61c4878aSAndroid Build Coastguard Worker       const SystemClock::duration timeout) {
285*61c4878aSAndroid Build Coastguard Worker     if (!mutex.try_lock_for(timeout)) {
286*61c4878aSAndroid Build Coastguard Worker       return false;
287*61c4878aSAndroid Build Coastguard Worker     }
288*61c4878aSAndroid Build Coastguard Worker     NotThreadSafeCriticalSection();
289*61c4878aSAndroid Build Coastguard Worker     mutex.unlock();
290*61c4878aSAndroid Build Coastguard Worker     return true;
291*61c4878aSAndroid Build Coastguard Worker   }
292*61c4878aSAndroid Build Coastguard Worker
293*61c4878aSAndroid Build Coastguard WorkerAlternatively you can use C++'s RAII helpers to ensure you always unlock.
294*61c4878aSAndroid Build Coastguard Worker
295*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
296*61c4878aSAndroid Build Coastguard Worker
297*61c4878aSAndroid Build Coastguard Worker   #include <mutex>
298*61c4878aSAndroid Build Coastguard Worker
299*61c4878aSAndroid Build Coastguard Worker   #include "pw_chrono/system_clock.h"
300*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/timed_mutex.h"
301*61c4878aSAndroid Build Coastguard Worker
302*61c4878aSAndroid Build Coastguard Worker   pw::sync::TimedMutex mutex;
303*61c4878aSAndroid Build Coastguard Worker
304*61c4878aSAndroid Build Coastguard Worker   bool ThreadSafeCriticalSectionWithTimeout(
305*61c4878aSAndroid Build Coastguard Worker       const SystemClock::duration timeout) {
306*61c4878aSAndroid Build Coastguard Worker     std::unique_lock lock(mutex, std::defer_lock);
307*61c4878aSAndroid Build Coastguard Worker     if (!lock.try_lock_for(timeout)) {
308*61c4878aSAndroid Build Coastguard Worker       return false;
309*61c4878aSAndroid Build Coastguard Worker     }
310*61c4878aSAndroid Build Coastguard Worker     NotThreadSafeCriticalSection();
311*61c4878aSAndroid Build Coastguard Worker     return true;
312*61c4878aSAndroid Build Coastguard Worker   }
313*61c4878aSAndroid Build Coastguard Worker
314*61c4878aSAndroid Build Coastguard WorkerC
315*61c4878aSAndroid Build Coastguard Worker-
316*61c4878aSAndroid Build Coastguard WorkerThe TimedMutex must be created in C++, however it can be passed into C using the
317*61c4878aSAndroid Build Coastguard Worker``pw_sync_TimedMutex`` opaque struct alias.
318*61c4878aSAndroid Build Coastguard Worker
319*61c4878aSAndroid Build Coastguard Worker.. doxygenfile:: timed_mutex.h
320*61c4878aSAndroid Build Coastguard Worker   :sections: func
321*61c4878aSAndroid Build Coastguard Worker
322*61c4878aSAndroid Build Coastguard Worker.. list-table::
323*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
324*61c4878aSAndroid Build Coastguard Worker   :widths: 70 10 10 10
325*61c4878aSAndroid Build Coastguard Worker
326*61c4878aSAndroid Build Coastguard Worker   * - Safe to use in context
327*61c4878aSAndroid Build Coastguard Worker     - Thread
328*61c4878aSAndroid Build Coastguard Worker     - Interrupt
329*61c4878aSAndroid Build Coastguard Worker     - NMI
330*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw_sync_TimedMutex_Lock`
331*61c4878aSAndroid Build Coastguard Worker     - ✔
332*61c4878aSAndroid Build Coastguard Worker     -
333*61c4878aSAndroid Build Coastguard Worker     -
334*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw_sync_TimedMutex_TryLock`
335*61c4878aSAndroid Build Coastguard Worker     - ✔
336*61c4878aSAndroid Build Coastguard Worker     -
337*61c4878aSAndroid Build Coastguard Worker     -
338*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw_sync_TimedMutex_TryLockFor`
339*61c4878aSAndroid Build Coastguard Worker     - ✔
340*61c4878aSAndroid Build Coastguard Worker     -
341*61c4878aSAndroid Build Coastguard Worker     -
342*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw_sync_TimedMutex_TryLockUntil`
343*61c4878aSAndroid Build Coastguard Worker     - ✔
344*61c4878aSAndroid Build Coastguard Worker     -
345*61c4878aSAndroid Build Coastguard Worker     -
346*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw_sync_TimedMutex_Unlock`
347*61c4878aSAndroid Build Coastguard Worker     - ✔
348*61c4878aSAndroid Build Coastguard Worker     -
349*61c4878aSAndroid Build Coastguard Worker     -
350*61c4878aSAndroid Build Coastguard Worker
351*61c4878aSAndroid Build Coastguard WorkerExample in C
352*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^
353*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
354*61c4878aSAndroid Build Coastguard Worker
355*61c4878aSAndroid Build Coastguard Worker   #include "pw_chrono/system_clock.h"
356*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/timed_mutex.h"
357*61c4878aSAndroid Build Coastguard Worker
358*61c4878aSAndroid Build Coastguard Worker   pw::sync::TimedMutex mutex;
359*61c4878aSAndroid Build Coastguard Worker
360*61c4878aSAndroid Build Coastguard Worker   extern pw_sync_TimedMutex mutex;  // This can only be created in C++.
361*61c4878aSAndroid Build Coastguard Worker
362*61c4878aSAndroid Build Coastguard Worker   bool ThreadSafeCriticalSectionWithTimeout(
363*61c4878aSAndroid Build Coastguard Worker       const pw_chrono_SystemClock_Duration timeout) {
364*61c4878aSAndroid Build Coastguard Worker     if (!pw_sync_TimedMutex_TryLockFor(&mutex, timeout)) {
365*61c4878aSAndroid Build Coastguard Worker       return false;
366*61c4878aSAndroid Build Coastguard Worker     }
367*61c4878aSAndroid Build Coastguard Worker     NotThreadSafeCriticalSection();
368*61c4878aSAndroid Build Coastguard Worker     pw_sync_TimedMutex_Unlock(&mutex);
369*61c4878aSAndroid Build Coastguard Worker     return true;
370*61c4878aSAndroid Build Coastguard Worker   }
371*61c4878aSAndroid Build Coastguard Worker
372*61c4878aSAndroid Build Coastguard WorkerRecursiveMutex
373*61c4878aSAndroid Build Coastguard Worker==============
374*61c4878aSAndroid Build Coastguard Worker``pw_sync`` provides ``pw::sync::RecursiveMutex``, a recursive mutex
375*61c4878aSAndroid Build Coastguard Workerimplementation. At this time, this facade can only be used internally by
376*61c4878aSAndroid Build Coastguard WorkerPigweed.
377*61c4878aSAndroid Build Coastguard Worker
378*61c4878aSAndroid Build Coastguard WorkerInterruptSpinLock
379*61c4878aSAndroid Build Coastguard Worker=================
380*61c4878aSAndroid Build Coastguard WorkerThe InterruptSpinLock is a synchronization primitive that can be used to protect
381*61c4878aSAndroid Build Coastguard Workershared data from being simultaneously accessed by multiple threads and/or
382*61c4878aSAndroid Build Coastguard Workerinterrupts as a targeted global lock, with the exception of Non-Maskable
383*61c4878aSAndroid Build Coastguard WorkerInterrupts (NMIs). It offers exclusive, non-recursive ownership semantics where
384*61c4878aSAndroid Build Coastguard WorkerIRQs up to a backend defined level of "NMIs" will be masked to solve
385*61c4878aSAndroid Build Coastguard Workerpriority-inversion.
386*61c4878aSAndroid Build Coastguard Worker
387*61c4878aSAndroid Build Coastguard WorkerThis InterruptSpinLock relies on built-in local interrupt masking to make it
388*61c4878aSAndroid Build Coastguard Workerinterrupt safe without requiring the caller to separately mask and unmask
389*61c4878aSAndroid Build Coastguard Workerinterrupts when using this primitive.
390*61c4878aSAndroid Build Coastguard Worker
391*61c4878aSAndroid Build Coastguard WorkerUnlike global interrupt locks, this also works safely and efficiently on SMP
392*61c4878aSAndroid Build Coastguard Workersystems. On systems which are not SMP, spinning is not required but some state
393*61c4878aSAndroid Build Coastguard Workermay still be used to detect recursion.
394*61c4878aSAndroid Build Coastguard Worker
395*61c4878aSAndroid Build Coastguard WorkerThe InterruptSpinLock is a
396*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_
397*61c4878aSAndroid Build Coastguard Workerand
398*61c4878aSAndroid Build Coastguard Worker`Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_.
399*61c4878aSAndroid Build Coastguard Worker
400*61c4878aSAndroid Build Coastguard Worker.. list-table::
401*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
402*61c4878aSAndroid Build Coastguard Worker
403*61c4878aSAndroid Build Coastguard Worker   * - Supported on
404*61c4878aSAndroid Build Coastguard Worker     - Backend module
405*61c4878aSAndroid Build Coastguard Worker   * - FreeRTOS
406*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_freertos`
407*61c4878aSAndroid Build Coastguard Worker   * - ThreadX
408*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_threadx`
409*61c4878aSAndroid Build Coastguard Worker   * - embOS
410*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_embos`
411*61c4878aSAndroid Build Coastguard Worker   * - STL
412*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_stl`
413*61c4878aSAndroid Build Coastguard Worker   * - Baremetal
414*61c4878aSAndroid Build Coastguard Worker     - Planned, not ready for use
415*61c4878aSAndroid Build Coastguard Worker   * - Zephyr
416*61c4878aSAndroid Build Coastguard Worker     - Planned
417*61c4878aSAndroid Build Coastguard Worker   * - CMSIS-RTOS API v2 & RTX5
418*61c4878aSAndroid Build Coastguard Worker     - Planned
419*61c4878aSAndroid Build Coastguard Worker
420*61c4878aSAndroid Build Coastguard WorkerC++
421*61c4878aSAndroid Build Coastguard Worker---
422*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::InterruptSpinLock
423*61c4878aSAndroid Build Coastguard Worker   :members:
424*61c4878aSAndroid Build Coastguard Worker
425*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::InterruptSpinLock
426*61c4878aSAndroid Build Coastguard Worker
427*61c4878aSAndroid Build Coastguard Worker.. list-table::
428*61c4878aSAndroid Build Coastguard Worker   :widths: 70 10 10 10
429*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
430*61c4878aSAndroid Build Coastguard Worker
431*61c4878aSAndroid Build Coastguard Worker   * - Safe to use in context
432*61c4878aSAndroid Build Coastguard Worker     - Thread
433*61c4878aSAndroid Build Coastguard Worker     - Interrupt
434*61c4878aSAndroid Build Coastguard Worker     - NMI
435*61c4878aSAndroid Build Coastguard Worker   * - :cpp:class:`pw::sync::InterruptSpinLock::InterruptSpinLock`
436*61c4878aSAndroid Build Coastguard Worker     - ✔
437*61c4878aSAndroid Build Coastguard Worker     - ✔
438*61c4878aSAndroid Build Coastguard Worker     -
439*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw::sync::InterruptSpinLock::~InterruptSpinLock`
440*61c4878aSAndroid Build Coastguard Worker     - ✔
441*61c4878aSAndroid Build Coastguard Worker     - ✔
442*61c4878aSAndroid Build Coastguard Worker     -
443*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`lock`
444*61c4878aSAndroid Build Coastguard Worker     - ✔
445*61c4878aSAndroid Build Coastguard Worker     - ✔
446*61c4878aSAndroid Build Coastguard Worker     -
447*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_lock`
448*61c4878aSAndroid Build Coastguard Worker     - ✔
449*61c4878aSAndroid Build Coastguard Worker     - ✔
450*61c4878aSAndroid Build Coastguard Worker     -
451*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`unlock`
452*61c4878aSAndroid Build Coastguard Worker     - ✔
453*61c4878aSAndroid Build Coastguard Worker     - ✔
454*61c4878aSAndroid Build Coastguard Worker     -
455*61c4878aSAndroid Build Coastguard Worker
456*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
457*61c4878aSAndroid Build Coastguard Worker
458*61c4878aSAndroid Build Coastguard WorkerExamples in C++
459*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^
460*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
461*61c4878aSAndroid Build Coastguard Worker
462*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/interrupt_spin_lock.h"
463*61c4878aSAndroid Build Coastguard Worker
464*61c4878aSAndroid Build Coastguard Worker   pw::sync::InterruptSpinLock interrupt_spin_lock;
465*61c4878aSAndroid Build Coastguard Worker
466*61c4878aSAndroid Build Coastguard Worker   void InterruptSafeCriticalSection() {
467*61c4878aSAndroid Build Coastguard Worker     interrupt_spin_lock.lock();
468*61c4878aSAndroid Build Coastguard Worker     NotThreadSafeCriticalSection();
469*61c4878aSAndroid Build Coastguard Worker     interrupt_spin_lock.unlock();
470*61c4878aSAndroid Build Coastguard Worker   }
471*61c4878aSAndroid Build Coastguard Worker
472*61c4878aSAndroid Build Coastguard Worker
473*61c4878aSAndroid Build Coastguard WorkerAlternatively you can use C++'s RAII helpers to ensure you always unlock.
474*61c4878aSAndroid Build Coastguard Worker
475*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
476*61c4878aSAndroid Build Coastguard Worker
477*61c4878aSAndroid Build Coastguard Worker   #include <mutex>
478*61c4878aSAndroid Build Coastguard Worker
479*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/interrupt_spin_lock.h"
480*61c4878aSAndroid Build Coastguard Worker
481*61c4878aSAndroid Build Coastguard Worker   pw::sync::InterruptSpinLock interrupt_spin_lock;
482*61c4878aSAndroid Build Coastguard Worker
483*61c4878aSAndroid Build Coastguard Worker   void InterruptSafeCriticalSection() {
484*61c4878aSAndroid Build Coastguard Worker     std::lock_guard lock(interrupt_spin_lock);
485*61c4878aSAndroid Build Coastguard Worker     NotThreadSafeCriticalSection();
486*61c4878aSAndroid Build Coastguard Worker   }
487*61c4878aSAndroid Build Coastguard Worker
488*61c4878aSAndroid Build Coastguard Worker
489*61c4878aSAndroid Build Coastguard WorkerC
490*61c4878aSAndroid Build Coastguard Worker-
491*61c4878aSAndroid Build Coastguard WorkerThe InterruptSpinLock must be created in C++, however it can be passed into C using the
492*61c4878aSAndroid Build Coastguard Worker``pw_sync_InterruptSpinLock`` opaque struct alias.
493*61c4878aSAndroid Build Coastguard Worker
494*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_sync_InterruptSpinLock_Lock
495*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_sync_InterruptSpinLock_TryLock
496*61c4878aSAndroid Build Coastguard Worker.. doxygenfunction:: pw_sync_InterruptSpinLock_Unlock
497*61c4878aSAndroid Build Coastguard Worker
498*61c4878aSAndroid Build Coastguard Worker.. list-table::
499*61c4878aSAndroid Build Coastguard Worker   :widths: 70 10 10 10
500*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
501*61c4878aSAndroid Build Coastguard Worker
502*61c4878aSAndroid Build Coastguard Worker   * - Safe to use in context
503*61c4878aSAndroid Build Coastguard Worker     - Thread
504*61c4878aSAndroid Build Coastguard Worker     - Interrupt
505*61c4878aSAndroid Build Coastguard Worker     - NMI
506*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw_sync_InterruptSpinLock_Lock`
507*61c4878aSAndroid Build Coastguard Worker     - ✔
508*61c4878aSAndroid Build Coastguard Worker     - ✔
509*61c4878aSAndroid Build Coastguard Worker     -
510*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw_sync_InterruptSpinLock_TryLock`
511*61c4878aSAndroid Build Coastguard Worker     - ✔
512*61c4878aSAndroid Build Coastguard Worker     - ✔
513*61c4878aSAndroid Build Coastguard Worker     -
514*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw_sync_InterruptSpinLock_Unlock`
515*61c4878aSAndroid Build Coastguard Worker     - ✔
516*61c4878aSAndroid Build Coastguard Worker     - ✔
517*61c4878aSAndroid Build Coastguard Worker     -
518*61c4878aSAndroid Build Coastguard Worker
519*61c4878aSAndroid Build Coastguard WorkerExample in C
520*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^
521*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
522*61c4878aSAndroid Build Coastguard Worker
523*61c4878aSAndroid Build Coastguard Worker   #include "pw_chrono/system_clock.h"
524*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/interrupt_spin_lock.h"
525*61c4878aSAndroid Build Coastguard Worker
526*61c4878aSAndroid Build Coastguard Worker   pw::sync::InterruptSpinLock interrupt_spin_lock;
527*61c4878aSAndroid Build Coastguard Worker
528*61c4878aSAndroid Build Coastguard Worker   extern pw_sync_InterruptSpinLock interrupt_spin_lock;  // This can only be created in C++.
529*61c4878aSAndroid Build Coastguard Worker
530*61c4878aSAndroid Build Coastguard Worker   void InterruptSafeCriticalSection(void) {
531*61c4878aSAndroid Build Coastguard Worker     pw_sync_InterruptSpinLock_Lock(&interrupt_spin_lock);
532*61c4878aSAndroid Build Coastguard Worker     NotThreadSafeCriticalSection();
533*61c4878aSAndroid Build Coastguard Worker     pw_sync_InterruptSpinLock_Unlock(&interrupt_spin_lock);
534*61c4878aSAndroid Build Coastguard Worker   }
535*61c4878aSAndroid Build Coastguard Worker
536*61c4878aSAndroid Build Coastguard WorkerThread Safety Lock Annotations
537*61c4878aSAndroid Build Coastguard Worker==============================
538*61c4878aSAndroid Build Coastguard WorkerPigweed's critical section lock primitives support Clang's thread safety
539*61c4878aSAndroid Build Coastguard Workeranalysis extension for C++. The analysis is completely static at compile-time.
540*61c4878aSAndroid Build Coastguard WorkerThis is only supported when building with Clang. The annotations are no-ops when
541*61c4878aSAndroid Build Coastguard Workerusing different compilers.
542*61c4878aSAndroid Build Coastguard Worker
543*61c4878aSAndroid Build Coastguard WorkerPigweed provides the ``pw_sync/lock_annotations.h`` header file with macro
544*61c4878aSAndroid Build Coastguard Workerdefinitions to allow developers to document the locking policies of
545*61c4878aSAndroid Build Coastguard Workermulti-threaded code. The annotations can also help program analysis tools to
546*61c4878aSAndroid Build Coastguard Workeridentify potential thread safety issues.
547*61c4878aSAndroid Build Coastguard Worker
548*61c4878aSAndroid Build Coastguard WorkerMore information on Clang's thread safety analysis system can be found
549*61c4878aSAndroid Build Coastguard Worker`here <https://clang.llvm.org/docs/ThreadSafetyAnalysis.html>`_.
550*61c4878aSAndroid Build Coastguard Worker
551*61c4878aSAndroid Build Coastguard WorkerEnabling Clang's Analysis
552*61c4878aSAndroid Build Coastguard Worker-------------------------
553*61c4878aSAndroid Build Coastguard WorkerIn order to enable the analysis, Clang requires that the ``-Wthread-safety``
554*61c4878aSAndroid Build Coastguard Workercompilation flag be used. In addition, if any STL components like
555*61c4878aSAndroid Build Coastguard Worker``std::lock_guard`` are used, the STL's built in annotations have to be manually
556*61c4878aSAndroid Build Coastguard Workerenabled, typically by setting the ``_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS``
557*61c4878aSAndroid Build Coastguard Workermacro.
558*61c4878aSAndroid Build Coastguard Worker
559*61c4878aSAndroid Build Coastguard WorkerIf using GN, the ``pw_build:clang_thread_safety_warnings`` config is provided
560*61c4878aSAndroid Build Coastguard Workerto do this for you, when added to your clang toolchain definition's default
561*61c4878aSAndroid Build Coastguard Workerconfigs.
562*61c4878aSAndroid Build Coastguard Worker
563*61c4878aSAndroid Build Coastguard WorkerWhy use lock annotations?
564*61c4878aSAndroid Build Coastguard Worker-------------------------
565*61c4878aSAndroid Build Coastguard WorkerLock annotations can help warn you about potential race conditions in your code
566*61c4878aSAndroid Build Coastguard Workerwhen using locks: you have to remember to grab lock(s) before entering a
567*61c4878aSAndroid Build Coastguard Workercritical section, yuou have to remember to unlock it when you leave, and you
568*61c4878aSAndroid Build Coastguard Workerhave to avoid deadlocks.
569*61c4878aSAndroid Build Coastguard Worker
570*61c4878aSAndroid Build Coastguard WorkerClang's lock annotations let you inform the compiler and anyone reading your
571*61c4878aSAndroid Build Coastguard Workercode which variables are guarded by which locks, which locks should or cannot be
572*61c4878aSAndroid Build Coastguard Workerheld when calling which function, which order locks should be acquired in, etc.
573*61c4878aSAndroid Build Coastguard Worker
574*61c4878aSAndroid Build Coastguard WorkerUsing Lock Annotations
575*61c4878aSAndroid Build Coastguard Worker----------------------
576*61c4878aSAndroid Build Coastguard WorkerWhen referring to locks in the arguments of the attributes, you should
577*61c4878aSAndroid Build Coastguard Workeruse variable names or more complex expressions (e.g. ``my_object->lock_``)
578*61c4878aSAndroid Build Coastguard Workerthat evaluate to a concrete lock object whenever possible. If the lock
579*61c4878aSAndroid Build Coastguard Workeryou want to refer to is not in scope, you may use a member pointer
580*61c4878aSAndroid Build Coastguard Worker(e.g. ``&MyClass::lock_``) to refer to a lock in some (unknown) object.
581*61c4878aSAndroid Build Coastguard Worker
582*61c4878aSAndroid Build Coastguard WorkerAnnotating Lock Usage
583*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^
584*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_GUARDED_BY
585*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_PT_GUARDED_BY
586*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_ACQUIRED_AFTER
587*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_ACQUIRED_BEFORE
588*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_EXCLUSIVE_LOCKS_REQUIRED
589*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_SHARED_LOCKS_REQUIRED
590*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_LOCKS_EXCLUDED
591*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_LOCK_RETURNED
592*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_LOCKABLE
593*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_SCOPED_LOCKABLE
594*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_EXCLUSIVE_LOCK_FUNCTION
595*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_SHARED_LOCK_FUNCTION
596*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_UNLOCK_FUNCTION
597*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_EXCLUSIVE_TRYLOCK_FUNCTION
598*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_SHARED_TRYLOCK_FUNCTION
599*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_ASSERT_EXCLUSIVE_LOCK
600*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_ASSERT_SHARED_LOCK
601*61c4878aSAndroid Build Coastguard Worker.. doxygendefine:: PW_NO_LOCK_SAFETY_ANALYSIS
602*61c4878aSAndroid Build Coastguard Worker
603*61c4878aSAndroid Build Coastguard WorkerAnnotating Lock Objects
604*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^^^
605*61c4878aSAndroid Build Coastguard WorkerIn order of lock usage annotation to work, the lock objects themselves need to
606*61c4878aSAndroid Build Coastguard Workerbe annotated as well. In case you are providing your own lock or psuedo-lock
607*61c4878aSAndroid Build Coastguard Workerobject, you can use the macros in this section to annotate it.
608*61c4878aSAndroid Build Coastguard Worker
609*61c4878aSAndroid Build Coastguard WorkerAs an example we've annotated a Lock and a RAII ScopedLocker object for you, see
610*61c4878aSAndroid Build Coastguard Workerthe macro documentation after for more details:
611*61c4878aSAndroid Build Coastguard Worker
612*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
613*61c4878aSAndroid Build Coastguard Worker
614*61c4878aSAndroid Build Coastguard Worker   class PW_LOCKABLE("Lock") Lock {
615*61c4878aSAndroid Build Coastguard Worker    public:
616*61c4878aSAndroid Build Coastguard Worker     void Lock() PW_EXCLUSIVE_LOCK_FUNCTION();
617*61c4878aSAndroid Build Coastguard Worker
618*61c4878aSAndroid Build Coastguard Worker     void ReaderLock() PW_SHARED_LOCK_FUNCTION();
619*61c4878aSAndroid Build Coastguard Worker
620*61c4878aSAndroid Build Coastguard Worker     void Unlock() PW_UNLOCK_FUNCTION();
621*61c4878aSAndroid Build Coastguard Worker
622*61c4878aSAndroid Build Coastguard Worker     void ReaderUnlock() PW_SHARED_TRYLOCK_FUNCTION();
623*61c4878aSAndroid Build Coastguard Worker
624*61c4878aSAndroid Build Coastguard Worker     bool TryLock() PW_EXCLUSIVE_TRYLOCK_FUNCTION(true);
625*61c4878aSAndroid Build Coastguard Worker
626*61c4878aSAndroid Build Coastguard Worker     bool ReaderTryLock() PW_SHARED_TRYLOCK_FUNCTION(true);
627*61c4878aSAndroid Build Coastguard Worker
628*61c4878aSAndroid Build Coastguard Worker     void AssertHeld() PW_ASSERT_EXCLUSIVE_LOCK();
629*61c4878aSAndroid Build Coastguard Worker
630*61c4878aSAndroid Build Coastguard Worker     void AssertReaderHeld() PW_ASSERT_SHARED_LOCK();
631*61c4878aSAndroid Build Coastguard Worker   };
632*61c4878aSAndroid Build Coastguard Worker
633*61c4878aSAndroid Build Coastguard Worker
634*61c4878aSAndroid Build Coastguard Worker   // Tag types for selecting a constructor.
635*61c4878aSAndroid Build Coastguard Worker   struct adopt_lock_t {} inline constexpr adopt_lock = {};
636*61c4878aSAndroid Build Coastguard Worker   struct defer_lock_t {} inline constexpr defer_lock = {};
637*61c4878aSAndroid Build Coastguard Worker   struct shared_lock_t {} inline constexpr shared_lock = {};
638*61c4878aSAndroid Build Coastguard Worker
639*61c4878aSAndroid Build Coastguard Worker   class PW_SCOPED_LOCKABLE ScopedLocker {
640*61c4878aSAndroid Build Coastguard Worker     // Acquire lock, implicitly acquire *this and associate it with lock.
641*61c4878aSAndroid Build Coastguard Worker     ScopedLocker(Lock *lock) PW_EXCLUSIVE_LOCK_FUNCTION(lock)
642*61c4878aSAndroid Build Coastguard Worker         : lock_(lock), locked(true) {
643*61c4878aSAndroid Build Coastguard Worker       lock->Lock();
644*61c4878aSAndroid Build Coastguard Worker     }
645*61c4878aSAndroid Build Coastguard Worker
646*61c4878aSAndroid Build Coastguard Worker     // Assume lock is held, implicitly acquire *this and associate it with lock.
647*61c4878aSAndroid Build Coastguard Worker     ScopedLocker(Lock *lock, adopt_lock_t) PW_EXCLUSIVE_LOCKS_REQUIRED(lock)
648*61c4878aSAndroid Build Coastguard Worker         : lock_(lock), locked(true) {}
649*61c4878aSAndroid Build Coastguard Worker
650*61c4878aSAndroid Build Coastguard Worker     // Acquire lock in shared mode, implicitly acquire *this and associate it
651*61c4878aSAndroid Build Coastguard Worker     // with lock.
652*61c4878aSAndroid Build Coastguard Worker     ScopedLocker(Lock *lock, shared_lock_t) PW_SHARED_LOCK_FUNCTION(lock)
653*61c4878aSAndroid Build Coastguard Worker         : lock_(lock), locked(true) {
654*61c4878aSAndroid Build Coastguard Worker       lock->ReaderLock();
655*61c4878aSAndroid Build Coastguard Worker     }
656*61c4878aSAndroid Build Coastguard Worker
657*61c4878aSAndroid Build Coastguard Worker     // Assume lock is held in shared mode, implicitly acquire *this and associate
658*61c4878aSAndroid Build Coastguard Worker     // it with lock.
659*61c4878aSAndroid Build Coastguard Worker     ScopedLocker(Lock *lock, adopt_lock_t, shared_lock_t)
660*61c4878aSAndroid Build Coastguard Worker         PW_SHARED_LOCKS_REQUIRED(lock) : lock_(lock), locked(true) {}
661*61c4878aSAndroid Build Coastguard Worker
662*61c4878aSAndroid Build Coastguard Worker     // Assume lock is not held, implicitly acquire *this and associate it with
663*61c4878aSAndroid Build Coastguard Worker     // lock.
664*61c4878aSAndroid Build Coastguard Worker     ScopedLocker(Lock *lock, defer_lock_t) PW_LOCKS_EXCLUDED(lock)
665*61c4878aSAndroid Build Coastguard Worker         : lock_(lock), locked(false) {}
666*61c4878aSAndroid Build Coastguard Worker
667*61c4878aSAndroid Build Coastguard Worker     // Release *this and all associated locks, if they are still held.
668*61c4878aSAndroid Build Coastguard Worker     // There is no warning if the scope was already unlocked before.
669*61c4878aSAndroid Build Coastguard Worker     ~ScopedLocker() PW_UNLOCK_FUNCTION() {
670*61c4878aSAndroid Build Coastguard Worker       if (locked)
671*61c4878aSAndroid Build Coastguard Worker         lock_->GenericUnlock();
672*61c4878aSAndroid Build Coastguard Worker     }
673*61c4878aSAndroid Build Coastguard Worker
674*61c4878aSAndroid Build Coastguard Worker     // Acquire all associated locks exclusively.
675*61c4878aSAndroid Build Coastguard Worker     void Lock() PW_EXCLUSIVE_LOCK_FUNCTION() {
676*61c4878aSAndroid Build Coastguard Worker       lock_->Lock();
677*61c4878aSAndroid Build Coastguard Worker       locked = true;
678*61c4878aSAndroid Build Coastguard Worker     }
679*61c4878aSAndroid Build Coastguard Worker
680*61c4878aSAndroid Build Coastguard Worker     // Try to acquire all associated locks exclusively.
681*61c4878aSAndroid Build Coastguard Worker     bool TryLock() PW_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
682*61c4878aSAndroid Build Coastguard Worker       return locked = lock_->TryLock();
683*61c4878aSAndroid Build Coastguard Worker     }
684*61c4878aSAndroid Build Coastguard Worker
685*61c4878aSAndroid Build Coastguard Worker     // Acquire all associated locks in shared mode.
686*61c4878aSAndroid Build Coastguard Worker     void ReaderLock() PW_SHARED_LOCK_FUNCTION() {
687*61c4878aSAndroid Build Coastguard Worker       lock_->ReaderLock();
688*61c4878aSAndroid Build Coastguard Worker       locked = true;
689*61c4878aSAndroid Build Coastguard Worker     }
690*61c4878aSAndroid Build Coastguard Worker
691*61c4878aSAndroid Build Coastguard Worker     // Try to acquire all associated locks in shared mode.
692*61c4878aSAndroid Build Coastguard Worker     bool ReaderTryLock() PW_SHARED_TRYLOCK_FUNCTION(true) {
693*61c4878aSAndroid Build Coastguard Worker       return locked = lock_->ReaderTryLock();
694*61c4878aSAndroid Build Coastguard Worker     }
695*61c4878aSAndroid Build Coastguard Worker
696*61c4878aSAndroid Build Coastguard Worker     // Release all associated locks. Warn on double unlock.
697*61c4878aSAndroid Build Coastguard Worker     void Unlock() PW_UNLOCK_FUNCTION() {
698*61c4878aSAndroid Build Coastguard Worker       lock_->Unlock();
699*61c4878aSAndroid Build Coastguard Worker       locked = false;
700*61c4878aSAndroid Build Coastguard Worker     }
701*61c4878aSAndroid Build Coastguard Worker
702*61c4878aSAndroid Build Coastguard Worker     // Release all associated locks. Warn on double unlock.
703*61c4878aSAndroid Build Coastguard Worker     void ReaderUnlock() PW_UNLOCK_FUNCTION() {
704*61c4878aSAndroid Build Coastguard Worker       lock_->ReaderUnlock();
705*61c4878aSAndroid Build Coastguard Worker       locked = false;
706*61c4878aSAndroid Build Coastguard Worker     }
707*61c4878aSAndroid Build Coastguard Worker
708*61c4878aSAndroid Build Coastguard Worker    private:
709*61c4878aSAndroid Build Coastguard Worker     Lock* lock_;
710*61c4878aSAndroid Build Coastguard Worker     bool locked_;
711*61c4878aSAndroid Build Coastguard Worker   };
712*61c4878aSAndroid Build Coastguard Worker
713*61c4878aSAndroid Build Coastguard Worker-----------------------------
714*61c4878aSAndroid Build Coastguard WorkerCritical Section Lock Helpers
715*61c4878aSAndroid Build Coastguard Worker-----------------------------
716*61c4878aSAndroid Build Coastguard Worker
717*61c4878aSAndroid Build Coastguard WorkerVirtual Lock Interfaces
718*61c4878aSAndroid Build Coastguard Worker=======================
719*61c4878aSAndroid Build Coastguard WorkerVirtual lock interfaces can be useful when lock selection cannot be templated.
720*61c4878aSAndroid Build Coastguard Worker
721*61c4878aSAndroid Build Coastguard WorkerWhy use virtual locks?
722*61c4878aSAndroid Build Coastguard Worker----------------------
723*61c4878aSAndroid Build Coastguard WorkerVirtual locks enable depending on locks without templating implementation code
724*61c4878aSAndroid Build Coastguard Workeron the type, while retaining flexibility with respect to the concrete lock type.
725*61c4878aSAndroid Build Coastguard WorkerPigweed tries to avoid pushing policy on to users, and virtual locks are one way
726*61c4878aSAndroid Build Coastguard Workerto accomplish that without templating everything.
727*61c4878aSAndroid Build Coastguard Worker
728*61c4878aSAndroid Build Coastguard WorkerA case when virtual locks are useful is when the concrete lock type changes at
729*61c4878aSAndroid Build Coastguard Workerrun time. For example, access to flash may be protected at run time by an
730*61c4878aSAndroid Build Coastguard Workerinternal mutex, however at crash time we may want to switch to a no-op lock. A
731*61c4878aSAndroid Build Coastguard Workervirtual lock interface could be used here to minimize the code-size cost that
732*61c4878aSAndroid Build Coastguard Workerwould occur otherwise if the flash driver were templated.
733*61c4878aSAndroid Build Coastguard Worker
734*61c4878aSAndroid Build Coastguard WorkerVirtualBasicLockable
735*61c4878aSAndroid Build Coastguard Worker--------------------
736*61c4878aSAndroid Build Coastguard WorkerThe ``VirtualBasicLockable`` interface meets the
737*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_ C++
738*61c4878aSAndroid Build Coastguard Workernamed requirement. Our critical section lock primitives offer optional virtual
739*61c4878aSAndroid Build Coastguard Workerversions, including:
740*61c4878aSAndroid Build Coastguard Worker
741*61c4878aSAndroid Build Coastguard Worker* :cpp:func:`pw::sync::VirtualMutex`
742*61c4878aSAndroid Build Coastguard Worker* :cpp:func:`pw::sync::VirtualTimedMutex`
743*61c4878aSAndroid Build Coastguard Worker* :cpp:func:`pw::sync::VirtualInterruptSpinLock`
744*61c4878aSAndroid Build Coastguard Worker
745*61c4878aSAndroid Build Coastguard Worker.. _module-pw_sync-genericbasiclockable:
746*61c4878aSAndroid Build Coastguard Worker
747*61c4878aSAndroid Build Coastguard WorkerGenericBasicLockable
748*61c4878aSAndroid Build Coastguard Worker--------------------
749*61c4878aSAndroid Build Coastguard Worker``GenericBasicLockable`` is a helper construct that can be used to declare
750*61c4878aSAndroid Build Coastguard Workervirtual versions of a critical section lock primitive that meets the
751*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_
752*61c4878aSAndroid Build Coastguard WorkerC++ named requirement. For example, given a ``Mutex`` type with ``lock()`` and
753*61c4878aSAndroid Build Coastguard Worker``unlock()`` methods, a ``VirtualMutex`` type that derives from
754*61c4878aSAndroid Build Coastguard Worker``VirtualBasicLockable`` can be declared as follows:
755*61c4878aSAndroid Build Coastguard Worker
756*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
757*61c4878aSAndroid Build Coastguard Worker
758*61c4878aSAndroid Build Coastguard Worker   class VirtualMutex : public GenericBasicLockable<Mutex> {};
759*61c4878aSAndroid Build Coastguard Worker
760*61c4878aSAndroid Build Coastguard WorkerBorrowable
761*61c4878aSAndroid Build Coastguard Worker==========
762*61c4878aSAndroid Build Coastguard Worker``Borrowable`` is a helper construct that enables callers to borrow an object
763*61c4878aSAndroid Build Coastguard Workerwhich is guarded by a lock, enabling a containerized style of external locking.
764*61c4878aSAndroid Build Coastguard Worker
765*61c4878aSAndroid Build Coastguard WorkerUsers who need access to the guarded object can ask to acquire a
766*61c4878aSAndroid Build Coastguard Worker``BorrowedPointer`` which permits access while the lock is held.
767*61c4878aSAndroid Build Coastguard Worker
768*61c4878aSAndroid Build Coastguard WorkerThis class is compatible with locks which comply with
769*61c4878aSAndroid Build Coastguard Worker`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_,
770*61c4878aSAndroid Build Coastguard Worker`Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_, and
771*61c4878aSAndroid Build Coastguard Worker`TimedLockable <https://en.cppreference.com/w/cpp/named_req/TimedLockable>`_
772*61c4878aSAndroid Build Coastguard WorkerC++ named requirements.
773*61c4878aSAndroid Build Coastguard Worker
774*61c4878aSAndroid Build Coastguard WorkerBy default the selected lock type is a ``pw::sync::VirtualBasicLockable``. If
775*61c4878aSAndroid Build Coastguard Workerthis virtual interface is used, the templated lock parameter can be skipped.
776*61c4878aSAndroid Build Coastguard Worker
777*61c4878aSAndroid Build Coastguard WorkerExternal vs Internal locking
778*61c4878aSAndroid Build Coastguard Worker----------------------------
779*61c4878aSAndroid Build Coastguard WorkerBefore we explain why Borrowable is useful, it's important to understand the
780*61c4878aSAndroid Build Coastguard Workertrade-offs when deciding on using internal and/or external locking.
781*61c4878aSAndroid Build Coastguard Worker
782*61c4878aSAndroid Build Coastguard WorkerInternal locking is when the lock is hidden from the caller entirely and is used
783*61c4878aSAndroid Build Coastguard Workerinternally to the API. For example:
784*61c4878aSAndroid Build Coastguard Worker
785*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
786*61c4878aSAndroid Build Coastguard Worker
787*61c4878aSAndroid Build Coastguard Worker   class BankAccount {
788*61c4878aSAndroid Build Coastguard Worker    public:
789*61c4878aSAndroid Build Coastguard Worker     void Deposit(int amount) {
790*61c4878aSAndroid Build Coastguard Worker       std::lock_guard lock(mutex_);
791*61c4878aSAndroid Build Coastguard Worker       balance_ += amount;
792*61c4878aSAndroid Build Coastguard Worker     }
793*61c4878aSAndroid Build Coastguard Worker
794*61c4878aSAndroid Build Coastguard Worker     void Withdraw(int amount) {
795*61c4878aSAndroid Build Coastguard Worker       std::lock_guard lock(mutex_);
796*61c4878aSAndroid Build Coastguard Worker       balance_ -= amount;
797*61c4878aSAndroid Build Coastguard Worker     }
798*61c4878aSAndroid Build Coastguard Worker
799*61c4878aSAndroid Build Coastguard Worker     void Balance() const {
800*61c4878aSAndroid Build Coastguard Worker       std::lock_guard lock(mutex_);
801*61c4878aSAndroid Build Coastguard Worker       return balance_;
802*61c4878aSAndroid Build Coastguard Worker     }
803*61c4878aSAndroid Build Coastguard Worker
804*61c4878aSAndroid Build Coastguard Worker    private:
805*61c4878aSAndroid Build Coastguard Worker     int balance_ PW_GUARDED_BY(mutex_);
806*61c4878aSAndroid Build Coastguard Worker     pw::sync::Mutex mutex_;
807*61c4878aSAndroid Build Coastguard Worker   };
808*61c4878aSAndroid Build Coastguard Worker
809*61c4878aSAndroid Build Coastguard WorkerInternal locking guarantees that any concurrent calls to its public member
810*61c4878aSAndroid Build Coastguard Workerfunctions don't corrupt an instance of that class. This is typically ensured by
811*61c4878aSAndroid Build Coastguard Workerhaving each member function acquire a lock on the object upon entry. This way,
812*61c4878aSAndroid Build Coastguard Workerfor any instance, there can only be one member function call active at any
813*61c4878aSAndroid Build Coastguard Workermoment, serializing the operations.
814*61c4878aSAndroid Build Coastguard Worker
815*61c4878aSAndroid Build Coastguard WorkerOne common issue that pops up is that member functions may have to call other
816*61c4878aSAndroid Build Coastguard Workermember functions which also require locks. This typically results in a
817*61c4878aSAndroid Build Coastguard Workerduplication of the public API into an internal mirror where the lock is already
818*61c4878aSAndroid Build Coastguard Workerheld. This along with having to modify every thread-safe public member function
819*61c4878aSAndroid Build Coastguard Workermay results in an increased code size.
820*61c4878aSAndroid Build Coastguard Worker
821*61c4878aSAndroid Build Coastguard WorkerHowever, with the per-method locking approach, it is not possible to perform a
822*61c4878aSAndroid Build Coastguard Workermulti-method thread-safe transaction. For example, what if we only wanted to
823*61c4878aSAndroid Build Coastguard Workerwithdraw money if the balance was high enough? With the current API there would
824*61c4878aSAndroid Build Coastguard Workerbe a risk that money is withdrawn after we've checked the balance.
825*61c4878aSAndroid Build Coastguard Worker
826*61c4878aSAndroid Build Coastguard WorkerThis is usually why external locking is used. This is when the lock is exposed
827*61c4878aSAndroid Build Coastguard Workerto the caller and may be used externally to the public API. External locking
828*61c4878aSAndroid Build Coastguard Workercan take may forms which may even include mixing internal and external locking.
829*61c4878aSAndroid Build Coastguard WorkerIn its most simplistic form it is an external lock used along side each
830*61c4878aSAndroid Build Coastguard Workerinstance, e.g.:
831*61c4878aSAndroid Build Coastguard Worker
832*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
833*61c4878aSAndroid Build Coastguard Worker
834*61c4878aSAndroid Build Coastguard Worker   class BankAccount {
835*61c4878aSAndroid Build Coastguard Worker    public:
836*61c4878aSAndroid Build Coastguard Worker     void Deposit(int amount) {
837*61c4878aSAndroid Build Coastguard Worker       balance_ += amount;
838*61c4878aSAndroid Build Coastguard Worker     }
839*61c4878aSAndroid Build Coastguard Worker
840*61c4878aSAndroid Build Coastguard Worker     void Withdraw(int amount) {
841*61c4878aSAndroid Build Coastguard Worker       balance_ -= amount;
842*61c4878aSAndroid Build Coastguard Worker     }
843*61c4878aSAndroid Build Coastguard Worker
844*61c4878aSAndroid Build Coastguard Worker     void Balance() const {
845*61c4878aSAndroid Build Coastguard Worker       return balance_;
846*61c4878aSAndroid Build Coastguard Worker     }
847*61c4878aSAndroid Build Coastguard Worker
848*61c4878aSAndroid Build Coastguard Worker    private:
849*61c4878aSAndroid Build Coastguard Worker     int balance_;
850*61c4878aSAndroid Build Coastguard Worker   };
851*61c4878aSAndroid Build Coastguard Worker
852*61c4878aSAndroid Build Coastguard Worker   pw::sync::Mutex bobs_account_mutex;
853*61c4878aSAndroid Build Coastguard Worker   BankAccount bobs_account PW_GUARDED_BY(bobs_account_mutex);
854*61c4878aSAndroid Build Coastguard Worker
855*61c4878aSAndroid Build Coastguard WorkerThe lock is acquired before the bank account is used for a transaction. In
856*61c4878aSAndroid Build Coastguard Workeraddition, we do not have to modify every public function and its trivial to
857*61c4878aSAndroid Build Coastguard Workercall other public member functions from a public member function. However, as
858*61c4878aSAndroid Build Coastguard Workeryou can imagine instantiating and passing around the instances and their locks
859*61c4878aSAndroid Build Coastguard Workercan become error prone.
860*61c4878aSAndroid Build Coastguard Worker
861*61c4878aSAndroid Build Coastguard WorkerThis is why ``Borrowable`` exists.
862*61c4878aSAndroid Build Coastguard Worker
863*61c4878aSAndroid Build Coastguard WorkerWhy use Borrowable?
864*61c4878aSAndroid Build Coastguard Worker-------------------
865*61c4878aSAndroid Build Coastguard Worker``Borrowable`` offers code-size efficient way to enable external locking that is
866*61c4878aSAndroid Build Coastguard Workereasy and safe to use. It is effectively a container which holds references to a
867*61c4878aSAndroid Build Coastguard Workerprotected instance and its lock which provides RAII-style access.
868*61c4878aSAndroid Build Coastguard Worker
869*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
870*61c4878aSAndroid Build Coastguard Worker
871*61c4878aSAndroid Build Coastguard Worker   pw::sync::Mutex bobs_account_mutex;
872*61c4878aSAndroid Build Coastguard Worker   BankAccount bobs_account PW_GUARDED_BY(bobs_account_mutex);
873*61c4878aSAndroid Build Coastguard Worker   pw::sync::Borrowable<BankAccount, pw::sync::Mutex> bobs_acount(
874*61c4878aSAndroid Build Coastguard Worker       bobs_account, bobs_account_mutex);
875*61c4878aSAndroid Build Coastguard Worker
876*61c4878aSAndroid Build Coastguard WorkerThis construct is useful when sharing objects or data which are transactional in
877*61c4878aSAndroid Build Coastguard Workernature where making individual operations threadsafe is insufficient. See the
878*61c4878aSAndroid Build Coastguard Workersection on internal vs external locking tradeoffs above.
879*61c4878aSAndroid Build Coastguard Worker
880*61c4878aSAndroid Build Coastguard WorkerIt can also offer a code-size and stack-usage efficient way to separate timeout
881*61c4878aSAndroid Build Coastguard Workerconstraints between the acquiring of the shared object and timeouts used for the
882*61c4878aSAndroid Build Coastguard Workershared object's API. For example, imagine you have an I2c bus which is used by
883*61c4878aSAndroid Build Coastguard Workerseveral threads and you'd like to specify an ACK timeout of 50ms. It'd be ideal
884*61c4878aSAndroid Build Coastguard Workerif the duration it takes to gain exclusive access to the I2c bus does not eat
885*61c4878aSAndroid Build Coastguard Workerinto the ACK timeout you'd like to use for the transaction. Borrowable can help
886*61c4878aSAndroid Build Coastguard Workeryou do exactly this if you provide access to the I2c bus through a
887*61c4878aSAndroid Build Coastguard Worker``Borrowable``.
888*61c4878aSAndroid Build Coastguard Worker
889*61c4878aSAndroid Build Coastguard Worker.. note::
890*61c4878aSAndroid Build Coastguard Worker
891*61c4878aSAndroid Build Coastguard Worker   ``Borrowable`` has semantics similar to a pointer and should be passed by
892*61c4878aSAndroid Build Coastguard Worker   value. Furthermore, a ``Borrowable<U>`` can be assigned to a
893*61c4878aSAndroid Build Coastguard Worker   ``Borrowable<T>`` if ``U`` is a subclass of ``T``.
894*61c4878aSAndroid Build Coastguard Worker
895*61c4878aSAndroid Build Coastguard WorkerC++
896*61c4878aSAndroid Build Coastguard Worker---
897*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::BorrowedPointer
898*61c4878aSAndroid Build Coastguard Worker   :members:
899*61c4878aSAndroid Build Coastguard Worker
900*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::Borrowable
901*61c4878aSAndroid Build Coastguard Worker   :members:
902*61c4878aSAndroid Build Coastguard Worker
903*61c4878aSAndroid Build Coastguard WorkerExample in C++
904*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^
905*61c4878aSAndroid Build Coastguard Worker
906*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
907*61c4878aSAndroid Build Coastguard Worker
908*61c4878aSAndroid Build Coastguard Worker   #include <chrono>
909*61c4878aSAndroid Build Coastguard Worker
910*61c4878aSAndroid Build Coastguard Worker   #include "pw_bytes/span.h"
911*61c4878aSAndroid Build Coastguard Worker   #include "pw_i2c/initiator.h"
912*61c4878aSAndroid Build Coastguard Worker   #include "pw_status/try.h"
913*61c4878aSAndroid Build Coastguard Worker   #include "pw_status/result.h"
914*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/borrow.h"
915*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/mutex.h"
916*61c4878aSAndroid Build Coastguard Worker
917*61c4878aSAndroid Build Coastguard Worker   class ExampleI2c : public pw::i2c::Initiator;
918*61c4878aSAndroid Build Coastguard Worker
919*61c4878aSAndroid Build Coastguard Worker   pw::sync::VirtualMutex i2c_mutex;
920*61c4878aSAndroid Build Coastguard Worker   ExampleI2c i2c;
921*61c4878aSAndroid Build Coastguard Worker   pw::sync::Borrowable<ExampleI2c> borrowable_i2c(i2c, i2c_mutex);
922*61c4878aSAndroid Build Coastguard Worker
923*61c4878aSAndroid Build Coastguard Worker   pw::Result<ConstByteSpan> ReadI2cData(ByteSpan buffer) {
924*61c4878aSAndroid Build Coastguard Worker     // Block indefinitely waiting to borrow the i2c bus.
925*61c4878aSAndroid Build Coastguard Worker     pw::sync::BorrowedPointer<ExampleI2c> borrowed_i2c =
926*61c4878aSAndroid Build Coastguard Worker         borrowable_i2c.acquire();
927*61c4878aSAndroid Build Coastguard Worker
928*61c4878aSAndroid Build Coastguard Worker     // Execute a sequence of transactions to get the needed data.
929*61c4878aSAndroid Build Coastguard Worker     PW_TRY(borrowed_i2c->WriteFor(kFirstWrite, std::chrono::milliseconds(50)));
930*61c4878aSAndroid Build Coastguard Worker     PW_TRY(borrowed_i2c->WriteReadFor(kSecondWrite, buffer,
931*61c4878aSAndroid Build Coastguard Worker                                       std::chrono::milliseconds(10)));
932*61c4878aSAndroid Build Coastguard Worker
933*61c4878aSAndroid Build Coastguard Worker     // Borrowed i2c pointer is returned when the scope exits.
934*61c4878aSAndroid Build Coastguard Worker     return buffer;
935*61c4878aSAndroid Build Coastguard Worker   }
936*61c4878aSAndroid Build Coastguard Worker
937*61c4878aSAndroid Build Coastguard WorkerInlineBorrowable
938*61c4878aSAndroid Build Coastguard Worker=================
939*61c4878aSAndroid Build Coastguard Worker``InlineBorrowable`` is a helper to simplify the common use case where an object
940*61c4878aSAndroid Build Coastguard Workeris wrapped in a ``Borrowable`` for its entire lifetime. The InlineBorrowable
941*61c4878aSAndroid Build Coastguard Workerowns the guarded object and the lock object.
942*61c4878aSAndroid Build Coastguard Worker
943*61c4878aSAndroid Build Coastguard WorkerInlineBorrowable has a separate parameter for the concrete lock type
944*61c4878aSAndroid Build Coastguard Workerthat is instantiated and a (possibly virtual) lock interface type that is
945*61c4878aSAndroid Build Coastguard Workerreferenced by users of the guarded object. The default lock is
946*61c4878aSAndroid Build Coastguard Worker``pw::sync::VirtualMutex`` and the default lock interface is
947*61c4878aSAndroid Build Coastguard Worker``pw::sync::VirtualBasicLockable``.
948*61c4878aSAndroid Build Coastguard Worker
949*61c4878aSAndroid Build Coastguard WorkerAn InlineBorrowable is a Borrowable with the same guarded object and lock
950*61c4878aSAndroid Build Coastguard Workerinterface types, and it can be passed directly to APIs that expect a Borrowable
951*61c4878aSAndroid Build Coastguard Workerreference.
952*61c4878aSAndroid Build Coastguard Worker
953*61c4878aSAndroid Build Coastguard WorkerWhy use InlineBorrowable?
954*61c4878aSAndroid Build Coastguard Worker-------------------------
955*61c4878aSAndroid Build Coastguard WorkerIt is a safer and simpler way to guard an object for its entire lifetime. The
956*61c4878aSAndroid Build Coastguard Workerunguarded object is never exposed and doesn't need to be stored in a separate
957*61c4878aSAndroid Build Coastguard Workervariable or data member. The guarded object and its lock are guaranteed to have
958*61c4878aSAndroid Build Coastguard Workerthe same lifetime, and the lock cannot be re-used for any other purpose.
959*61c4878aSAndroid Build Coastguard Worker
960*61c4878aSAndroid Build Coastguard WorkerConstructing objects in-place
961*61c4878aSAndroid Build Coastguard Worker-----------------------------
962*61c4878aSAndroid Build Coastguard WorkerThe guarded object and its lock are constructed in-place by the
963*61c4878aSAndroid Build Coastguard WorkerInlineBorrowable, and any constructor parameters required by the object or
964*61c4878aSAndroid Build Coastguard Workerits lock must be passed through the InlineBorrowable constructor. There are
965*61c4878aSAndroid Build Coastguard Workerseveral ways to do this:
966*61c4878aSAndroid Build Coastguard Worker
967*61c4878aSAndroid Build Coastguard Worker* Pass the parameters for the guarded object inline to the constructor. This is
968*61c4878aSAndroid Build Coastguard Worker  the recommended way to construct the object when the lock does not require any
969*61c4878aSAndroid Build Coastguard Worker  constructor parameters. Use the ``std::in_place`` marker to invoke the inline
970*61c4878aSAndroid Build Coastguard Worker  constructor.
971*61c4878aSAndroid Build Coastguard Worker
972*61c4878aSAndroid Build Coastguard Worker  .. code-block:: cpp
973*61c4878aSAndroid Build Coastguard Worker
974*61c4878aSAndroid Build Coastguard Worker     InlineBorrowable<Foo> foo(std::in_place, foo_arg1, foo_arg2);
975*61c4878aSAndroid Build Coastguard Worker     InlineBorrowable<std::array<int, 2>> foo_array(std::in_place, 1, 2);
976*61c4878aSAndroid Build Coastguard Worker
977*61c4878aSAndroid Build Coastguard Worker* Pass the parameters inside tuples:
978*61c4878aSAndroid Build Coastguard Worker
979*61c4878aSAndroid Build Coastguard Worker  .. code-block:: cpp
980*61c4878aSAndroid Build Coastguard Worker
981*61c4878aSAndroid Build Coastguard Worker     InlineBorrowable<Foo> foo(std::forward_as_tuple(foo_arg1, foo_arg2));
982*61c4878aSAndroid Build Coastguard Worker
983*61c4878aSAndroid Build Coastguard Worker     InlineBorrowable<Foo, MyLock> foo_lock(
984*61c4878aSAndroid Build Coastguard Worker         std::forward_as_tuple(foo_arg1, foo_arg2),
985*61c4878aSAndroid Build Coastguard Worker         std::forward_as_tuple(lock_arg1, lock_arg2));
986*61c4878aSAndroid Build Coastguard Worker
987*61c4878aSAndroid Build Coastguard Worker  .. note:: This approach only supports list initialization starting with C++20.
988*61c4878aSAndroid Build Coastguard Worker
989*61c4878aSAndroid Build Coastguard Worker* Use callables to construct the guarded object and lock object:
990*61c4878aSAndroid Build Coastguard Worker
991*61c4878aSAndroid Build Coastguard Worker  .. code-block:: cpp
992*61c4878aSAndroid Build Coastguard Worker
993*61c4878aSAndroid Build Coastguard Worker     InlineBorrowable<Foo> foo([&]{ return Foo{foo_arg1, foo_arg2}; });
994*61c4878aSAndroid Build Coastguard Worker
995*61c4878aSAndroid Build Coastguard Worker     InlineBorrowable<Foo, MyLock> foo_lock(
996*61c4878aSAndroid Build Coastguard Worker         [&]{ return Foo{foo_arg1, foo_arg2}; }
997*61c4878aSAndroid Build Coastguard Worker         [&]{ return MyLock{lock_arg1, lock_arg2}; }
998*61c4878aSAndroid Build Coastguard Worker
999*61c4878aSAndroid Build Coastguard Worker  .. note:: It is possible to construct and return objects that are not copyable
1000*61c4878aSAndroid Build Coastguard Worker    or movable, thanks to mandatory copy ellision (return value optimization).
1001*61c4878aSAndroid Build Coastguard Worker
1002*61c4878aSAndroid Build Coastguard WorkerC++
1003*61c4878aSAndroid Build Coastguard Worker---
1004*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::InlineBorrowable
1005*61c4878aSAndroid Build Coastguard Worker   :members:
1006*61c4878aSAndroid Build Coastguard Worker
1007*61c4878aSAndroid Build Coastguard WorkerExample in C++
1008*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^
1009*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
1010*61c4878aSAndroid Build Coastguard Worker
1011*61c4878aSAndroid Build Coastguard Worker   #include <utility>
1012*61c4878aSAndroid Build Coastguard Worker
1013*61c4878aSAndroid Build Coastguard Worker   #include "pw_bytes/span.h"
1014*61c4878aSAndroid Build Coastguard Worker   #include "pw_i2c/initiator.h"
1015*61c4878aSAndroid Build Coastguard Worker   #include "pw_status/result.h"
1016*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/inline_borrowable.h"
1017*61c4878aSAndroid Build Coastguard Worker
1018*61c4878aSAndroid Build Coastguard Worker   struct I2cOptions;
1019*61c4878aSAndroid Build Coastguard Worker
1020*61c4878aSAndroid Build Coastguard Worker   class ExampleI2c : public pw::i2c::Initiator {
1021*61c4878aSAndroid Build Coastguard Worker    public:
1022*61c4878aSAndroid Build Coastguard Worker     ExampleI2c(int bus_id, I2cOptions options);
1023*61c4878aSAndroid Build Coastguard Worker     // ...
1024*61c4878aSAndroid Build Coastguard Worker   };
1025*61c4878aSAndroid Build Coastguard Worker
1026*61c4878aSAndroid Build Coastguard Worker   int kBusId;
1027*61c4878aSAndroid Build Coastguard Worker   I2cOptions opts;
1028*61c4878aSAndroid Build Coastguard Worker
1029*61c4878aSAndroid Build Coastguard Worker   pw::sync::InlineBorrowable<ExampleI2c> i2c(std::in_place, kBusId, opts);
1030*61c4878aSAndroid Build Coastguard Worker
1031*61c4878aSAndroid Build Coastguard Worker   pw::Result<ConstByteSpan> ReadI2cData(
1032*61c4878aSAndroid Build Coastguard Worker     pw::sync::Borrowable<pw::i2c::Initiator> initiator,
1033*61c4878aSAndroid Build Coastguard Worker     ByteSpan buffer);
1034*61c4878aSAndroid Build Coastguard Worker
1035*61c4878aSAndroid Build Coastguard Worker   pw::Result<ConstByteSpan> ReadData(ByteSpan buffer) {
1036*61c4878aSAndroid Build Coastguard Worker     return ReadI2cData(i2c, buffer);
1037*61c4878aSAndroid Build Coastguard Worker   }
1038*61c4878aSAndroid Build Coastguard Worker
1039*61c4878aSAndroid Build Coastguard Worker--------------------
1040*61c4878aSAndroid Build Coastguard WorkerSignaling Primitives
1041*61c4878aSAndroid Build Coastguard Worker--------------------
1042*61c4878aSAndroid Build Coastguard WorkerNative signaling primitives tend to vary more compared to critial section locks
1043*61c4878aSAndroid Build Coastguard Workeracross different platforms. For example, although common signaling primtives
1044*61c4878aSAndroid Build Coastguard Workerlike semaphores are in most if not all RTOSes and even POSIX, it was not in the
1045*61c4878aSAndroid Build Coastguard WorkerSTL before C++20. Likewise many C++ developers are surprised that conditional
1046*61c4878aSAndroid Build Coastguard Workervariables tend to not be natively supported on RTOSes. Although you can usually
1047*61c4878aSAndroid Build Coastguard Workerbuild any signaling primitive based on other native signaling primitives, this
1048*61c4878aSAndroid Build Coastguard Workermay come with non-trivial added overhead in ROM, RAM, and execution efficiency.
1049*61c4878aSAndroid Build Coastguard Worker
1050*61c4878aSAndroid Build Coastguard WorkerFor this reason, Pigweed intends to provide some simpler signaling primitives
1051*61c4878aSAndroid Build Coastguard Workerwhich exist to solve a narrow programming need but can be implemented as
1052*61c4878aSAndroid Build Coastguard Workerefficiently as possible for the platform that it is used on.
1053*61c4878aSAndroid Build Coastguard Worker
1054*61c4878aSAndroid Build Coastguard WorkerThis simpler but highly portable class of signaling primitives is intended to
1055*61c4878aSAndroid Build Coastguard Workerensure that a portability efficiency tradeoff does not have to be made up front.
1056*61c4878aSAndroid Build Coastguard WorkerToday this is class of simpler signaling primitives is limited to the
1057*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::ThreadNotification` and
1058*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::TimedThreadNotification`.
1059*61c4878aSAndroid Build Coastguard Worker
1060*61c4878aSAndroid Build Coastguard WorkerThreadNotification
1061*61c4878aSAndroid Build Coastguard Worker==================
1062*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync
1063*61c4878aSAndroid Build Coastguard Worker
1064*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`ThreadNotification` is a synchronization primitive that can be used to
1065*61c4878aSAndroid Build Coastguard Workerpermit a SINGLE thread to block and consume a latching, saturating
1066*61c4878aSAndroid Build Coastguard Workernotification from multiple notifiers.
1067*61c4878aSAndroid Build Coastguard Worker
1068*61c4878aSAndroid Build Coastguard Worker.. Note::
1069*61c4878aSAndroid Build Coastguard Worker   Although only a single thread can block on a :cpp:class:`ThreadNotification`
1070*61c4878aSAndroid Build Coastguard Worker   at a time, many instances may be used by a single thread just like binary
1071*61c4878aSAndroid Build Coastguard Worker   semaphores.  This is in contrast to some native RTOS APIs, such as direct
1072*61c4878aSAndroid Build Coastguard Worker   task notifications, which re-use the same state within a thread's context.
1073*61c4878aSAndroid Build Coastguard Worker
1074*61c4878aSAndroid Build Coastguard Worker.. Warning::
1075*61c4878aSAndroid Build Coastguard Worker   This is a single consumer/waiter, multiple producer/notifier API!
1076*61c4878aSAndroid Build Coastguard Worker   The acquire APIs must only be invoked by a single consuming thread. As a
1077*61c4878aSAndroid Build Coastguard Worker   result, having multiple threads receiving notifications via the acquire API
1078*61c4878aSAndroid Build Coastguard Worker   is unsupported.
1079*61c4878aSAndroid Build Coastguard Worker
1080*61c4878aSAndroid Build Coastguard WorkerThis is effectively a subset of the :cpp:class:`BinarySemaphore` API, except
1081*61c4878aSAndroid Build Coastguard Workerthat only a single thread can be notified and block at a time.
1082*61c4878aSAndroid Build Coastguard Worker
1083*61c4878aSAndroid Build Coastguard WorkerThe single consumer aspect of the API permits the use of a smaller and/or
1084*61c4878aSAndroid Build Coastguard Workerfaster native APIs such as direct thread signaling. This should be
1085*61c4878aSAndroid Build Coastguard Workerbacked by the most efficient native primitive for a target, regardless of
1086*61c4878aSAndroid Build Coastguard Workerwhether that is a semaphore, event flag group, condition variable, or something
1087*61c4878aSAndroid Build Coastguard Workerelse.
1088*61c4878aSAndroid Build Coastguard Worker
1089*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`ThreadNotification` is initialized to being empty (latch is not
1090*61c4878aSAndroid Build Coastguard Workerset).
1091*61c4878aSAndroid Build Coastguard Worker
1092*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
1093*61c4878aSAndroid Build Coastguard Worker
1094*61c4878aSAndroid Build Coastguard WorkerGeneric BinarySemaphore-based Backend
1095*61c4878aSAndroid Build Coastguard Worker-------------------------------------
1096*61c4878aSAndroid Build Coastguard WorkerThis module provides a generic backend for
1097*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::ThreadNotification` via
1098*61c4878aSAndroid Build Coastguard Worker``pw_sync:binary_semaphore_thread_notification`` which uses a
1099*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::BinarySemaphore` as the backing primitive. See
1100*61c4878aSAndroid Build Coastguard Worker:ref:`BinarySemaphore <module-pw_sync-binary-semaphore>` for backend
1101*61c4878aSAndroid Build Coastguard Workeravailability.
1102*61c4878aSAndroid Build Coastguard Worker
1103*61c4878aSAndroid Build Coastguard WorkerOptimized Backend
1104*61c4878aSAndroid Build Coastguard Worker-----------------
1105*61c4878aSAndroid Build Coastguard Worker.. list-table::
1106*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
1107*61c4878aSAndroid Build Coastguard Worker
1108*61c4878aSAndroid Build Coastguard Worker   * - Supported on
1109*61c4878aSAndroid Build Coastguard Worker     - Optimized backend module
1110*61c4878aSAndroid Build Coastguard Worker   * - FreeRTOS
1111*61c4878aSAndroid Build Coastguard Worker     - ``pw_sync_freertos:thread_notification``
1112*61c4878aSAndroid Build Coastguard Worker   * - ThreadX
1113*61c4878aSAndroid Build Coastguard Worker     - Not possible, use ``pw_sync:binary_semaphore_thread_notification``
1114*61c4878aSAndroid Build Coastguard Worker   * - embOS
1115*61c4878aSAndroid Build Coastguard Worker     - Not needed, use ``pw_sync:binary_semaphore_thread_notification``
1116*61c4878aSAndroid Build Coastguard Worker   * - STL
1117*61c4878aSAndroid Build Coastguard Worker     - Not planned, use ``pw_sync:binary_semaphore_thread_notification``
1118*61c4878aSAndroid Build Coastguard Worker   * - Baremetal
1119*61c4878aSAndroid Build Coastguard Worker     - Planned
1120*61c4878aSAndroid Build Coastguard Worker   * - Zephyr
1121*61c4878aSAndroid Build Coastguard Worker     - Planned
1122*61c4878aSAndroid Build Coastguard Worker   * - CMSIS-RTOS API v2 & RTX5
1123*61c4878aSAndroid Build Coastguard Worker     - Planned
1124*61c4878aSAndroid Build Coastguard Worker
1125*61c4878aSAndroid Build Coastguard WorkerC++
1126*61c4878aSAndroid Build Coastguard Worker---
1127*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::ThreadNotification
1128*61c4878aSAndroid Build Coastguard Worker   :members:
1129*61c4878aSAndroid Build Coastguard Worker
1130*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::ThreadNotification
1131*61c4878aSAndroid Build Coastguard Worker
1132*61c4878aSAndroid Build Coastguard Worker.. list-table::
1133*61c4878aSAndroid Build Coastguard Worker   :widths: 70 10 10 10
1134*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
1135*61c4878aSAndroid Build Coastguard Worker
1136*61c4878aSAndroid Build Coastguard Worker   * - Safe to use in context
1137*61c4878aSAndroid Build Coastguard Worker     - Thread
1138*61c4878aSAndroid Build Coastguard Worker     - Interrupt
1139*61c4878aSAndroid Build Coastguard Worker     - NMI
1140*61c4878aSAndroid Build Coastguard Worker   * - :cpp:class:`pw::sync::ThreadNotification::ThreadNotification`
1141*61c4878aSAndroid Build Coastguard Worker     - ✔
1142*61c4878aSAndroid Build Coastguard Worker     -
1143*61c4878aSAndroid Build Coastguard Worker     -
1144*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw::sync::ThreadNotification::~ThreadNotification`
1145*61c4878aSAndroid Build Coastguard Worker     - ✔
1146*61c4878aSAndroid Build Coastguard Worker     -
1147*61c4878aSAndroid Build Coastguard Worker     -
1148*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`acquire`
1149*61c4878aSAndroid Build Coastguard Worker     - ✔
1150*61c4878aSAndroid Build Coastguard Worker     -
1151*61c4878aSAndroid Build Coastguard Worker     -
1152*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_acquire`
1153*61c4878aSAndroid Build Coastguard Worker     - ✔
1154*61c4878aSAndroid Build Coastguard Worker     -
1155*61c4878aSAndroid Build Coastguard Worker     -
1156*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`release`
1157*61c4878aSAndroid Build Coastguard Worker     - ✔
1158*61c4878aSAndroid Build Coastguard Worker     - ✔
1159*61c4878aSAndroid Build Coastguard Worker     -
1160*61c4878aSAndroid Build Coastguard Worker
1161*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
1162*61c4878aSAndroid Build Coastguard Worker
1163*61c4878aSAndroid Build Coastguard Worker
1164*61c4878aSAndroid Build Coastguard WorkerExamples in C++
1165*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^
1166*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
1167*61c4878aSAndroid Build Coastguard Worker
1168*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/thread_notification.h"
1169*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread/thread_core.h"
1170*61c4878aSAndroid Build Coastguard Worker
1171*61c4878aSAndroid Build Coastguard Worker   class FooHandler() : public pw::thread::ThreadCore {
1172*61c4878aSAndroid Build Coastguard Worker    // Public API invoked by other threads and/or interrupts.
1173*61c4878aSAndroid Build Coastguard Worker    void NewFooAvailable() {
1174*61c4878aSAndroid Build Coastguard Worker      new_foo_notification_.release();
1175*61c4878aSAndroid Build Coastguard Worker    }
1176*61c4878aSAndroid Build Coastguard Worker
1177*61c4878aSAndroid Build Coastguard Worker    private:
1178*61c4878aSAndroid Build Coastguard Worker     pw::sync::ThreadNotification new_foo_notification_;
1179*61c4878aSAndroid Build Coastguard Worker
1180*61c4878aSAndroid Build Coastguard Worker     // Thread function.
1181*61c4878aSAndroid Build Coastguard Worker     void Run() override {
1182*61c4878aSAndroid Build Coastguard Worker       while (true) {
1183*61c4878aSAndroid Build Coastguard Worker         new_foo_notification_.acquire();
1184*61c4878aSAndroid Build Coastguard Worker         HandleFoo();
1185*61c4878aSAndroid Build Coastguard Worker       }
1186*61c4878aSAndroid Build Coastguard Worker     }
1187*61c4878aSAndroid Build Coastguard Worker
1188*61c4878aSAndroid Build Coastguard Worker     void HandleFoo();
1189*61c4878aSAndroid Build Coastguard Worker   }
1190*61c4878aSAndroid Build Coastguard Worker
1191*61c4878aSAndroid Build Coastguard WorkerTimedThreadNotification
1192*61c4878aSAndroid Build Coastguard Worker=======================
1193*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`TimedThreadNotification` is an extension of the
1194*61c4878aSAndroid Build Coastguard Worker:cpp:class:`ThreadNotification` which offers timeout and deadline based
1195*61c4878aSAndroid Build Coastguard Workersemantics.
1196*61c4878aSAndroid Build Coastguard Worker
1197*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`TimedThreadNotification` is initialized to being empty (latch is
1198*61c4878aSAndroid Build Coastguard Workernot set).
1199*61c4878aSAndroid Build Coastguard Worker
1200*61c4878aSAndroid Build Coastguard Worker.. Warning::
1201*61c4878aSAndroid Build Coastguard Worker   This is a single consumer/waiter, multiple producer/notifier API!  The
1202*61c4878aSAndroid Build Coastguard Worker   acquire APIs must only be invoked by a single consuming thread. As a result,
1203*61c4878aSAndroid Build Coastguard Worker   having multiple threads receiving notifications via the acquire API is
1204*61c4878aSAndroid Build Coastguard Worker   unsupported.
1205*61c4878aSAndroid Build Coastguard Worker
1206*61c4878aSAndroid Build Coastguard WorkerGeneric BinarySemaphore-based Backend
1207*61c4878aSAndroid Build Coastguard Worker-------------------------------------
1208*61c4878aSAndroid Build Coastguard WorkerThis module provides a generic backend for
1209*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::TimedThreadNotification` via
1210*61c4878aSAndroid Build Coastguard Worker``pw_sync:binary_semaphore_timed_thread_notification`` which uses a
1211*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::BinarySemaphore` as the backing primitive. See
1212*61c4878aSAndroid Build Coastguard Worker:ref:`BinarySemaphore <module-pw_sync-binary-semaphore>` for backend
1213*61c4878aSAndroid Build Coastguard Workeravailability.
1214*61c4878aSAndroid Build Coastguard Worker
1215*61c4878aSAndroid Build Coastguard WorkerOptimized Backend
1216*61c4878aSAndroid Build Coastguard Worker-----------------
1217*61c4878aSAndroid Build Coastguard Worker.. list-table::
1218*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
1219*61c4878aSAndroid Build Coastguard Worker
1220*61c4878aSAndroid Build Coastguard Worker   * - Supported on
1221*61c4878aSAndroid Build Coastguard Worker     - Backend module
1222*61c4878aSAndroid Build Coastguard Worker   * - FreeRTOS
1223*61c4878aSAndroid Build Coastguard Worker     - ``pw_sync_freertos:timed_thread_notification``
1224*61c4878aSAndroid Build Coastguard Worker   * - ThreadX
1225*61c4878aSAndroid Build Coastguard Worker     - Not possible, use ``pw_sync:binary_semaphore_timed_thread_notification``
1226*61c4878aSAndroid Build Coastguard Worker   * - embOS
1227*61c4878aSAndroid Build Coastguard Worker     - Not needed, use ``pw_sync:binary_semaphore_timed_thread_notification``
1228*61c4878aSAndroid Build Coastguard Worker   * - STL
1229*61c4878aSAndroid Build Coastguard Worker     - Not planned, use ``pw_sync:binary_semaphore_timed_thread_notification``
1230*61c4878aSAndroid Build Coastguard Worker   * - Zephyr
1231*61c4878aSAndroid Build Coastguard Worker     - Planned
1232*61c4878aSAndroid Build Coastguard Worker   * - CMSIS-RTOS API v2 & RTX5
1233*61c4878aSAndroid Build Coastguard Worker     - Planned
1234*61c4878aSAndroid Build Coastguard Worker
1235*61c4878aSAndroid Build Coastguard WorkerC++
1236*61c4878aSAndroid Build Coastguard Worker---
1237*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::TimedThreadNotification
1238*61c4878aSAndroid Build Coastguard Worker   :members:
1239*61c4878aSAndroid Build Coastguard Worker
1240*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::TimedThreadNotification
1241*61c4878aSAndroid Build Coastguard Worker
1242*61c4878aSAndroid Build Coastguard Worker.. list-table::
1243*61c4878aSAndroid Build Coastguard Worker   :widths: 70 10 10 10
1244*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
1245*61c4878aSAndroid Build Coastguard Worker
1246*61c4878aSAndroid Build Coastguard Worker   * - Safe to use in context
1247*61c4878aSAndroid Build Coastguard Worker     - Thread
1248*61c4878aSAndroid Build Coastguard Worker     - Interrupt
1249*61c4878aSAndroid Build Coastguard Worker     - NMI
1250*61c4878aSAndroid Build Coastguard Worker   * - :cpp:class:`pw::sync::TimedThreadNotification::TimedThreadNotification`
1251*61c4878aSAndroid Build Coastguard Worker     - ✔
1252*61c4878aSAndroid Build Coastguard Worker     -
1253*61c4878aSAndroid Build Coastguard Worker     -
1254*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw::sync::TimedThreadNotification::~TimedThreadNotification`
1255*61c4878aSAndroid Build Coastguard Worker     - ✔
1256*61c4878aSAndroid Build Coastguard Worker     -
1257*61c4878aSAndroid Build Coastguard Worker     -
1258*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`acquire`
1259*61c4878aSAndroid Build Coastguard Worker     - ✔
1260*61c4878aSAndroid Build Coastguard Worker     -
1261*61c4878aSAndroid Build Coastguard Worker     -
1262*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_acquire`
1263*61c4878aSAndroid Build Coastguard Worker     - ✔
1264*61c4878aSAndroid Build Coastguard Worker     -
1265*61c4878aSAndroid Build Coastguard Worker     -
1266*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_acquire_for`
1267*61c4878aSAndroid Build Coastguard Worker     - ✔
1268*61c4878aSAndroid Build Coastguard Worker     -
1269*61c4878aSAndroid Build Coastguard Worker     -
1270*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_acquire_until`
1271*61c4878aSAndroid Build Coastguard Worker     - ✔
1272*61c4878aSAndroid Build Coastguard Worker     -
1273*61c4878aSAndroid Build Coastguard Worker     -
1274*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`release`
1275*61c4878aSAndroid Build Coastguard Worker     - ✔
1276*61c4878aSAndroid Build Coastguard Worker     - ✔
1277*61c4878aSAndroid Build Coastguard Worker     -
1278*61c4878aSAndroid Build Coastguard Worker
1279*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
1280*61c4878aSAndroid Build Coastguard Worker
1281*61c4878aSAndroid Build Coastguard WorkerExamples in C++
1282*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^
1283*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
1284*61c4878aSAndroid Build Coastguard Worker
1285*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/timed_thread_notification.h"
1286*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread/thread_core.h"
1287*61c4878aSAndroid Build Coastguard Worker
1288*61c4878aSAndroid Build Coastguard Worker   class FooHandler() : public pw::thread::ThreadCore {
1289*61c4878aSAndroid Build Coastguard Worker    // Public API invoked by other threads and/or interrupts.
1290*61c4878aSAndroid Build Coastguard Worker    void NewFooAvailable() {
1291*61c4878aSAndroid Build Coastguard Worker      new_foo_notification_.release();
1292*61c4878aSAndroid Build Coastguard Worker    }
1293*61c4878aSAndroid Build Coastguard Worker
1294*61c4878aSAndroid Build Coastguard Worker    private:
1295*61c4878aSAndroid Build Coastguard Worker     pw::sync::TimedThreadNotification new_foo_notification_;
1296*61c4878aSAndroid Build Coastguard Worker
1297*61c4878aSAndroid Build Coastguard Worker     // Thread function.
1298*61c4878aSAndroid Build Coastguard Worker     void Run() override {
1299*61c4878aSAndroid Build Coastguard Worker       while (true) {
1300*61c4878aSAndroid Build Coastguard Worker         if (new_foo_notification_.try_acquire_for(kNotificationTimeout)) {
1301*61c4878aSAndroid Build Coastguard Worker           HandleFoo();
1302*61c4878aSAndroid Build Coastguard Worker         }
1303*61c4878aSAndroid Build Coastguard Worker         DoOtherStuff();
1304*61c4878aSAndroid Build Coastguard Worker       }
1305*61c4878aSAndroid Build Coastguard Worker     }
1306*61c4878aSAndroid Build Coastguard Worker
1307*61c4878aSAndroid Build Coastguard Worker     void HandleFoo();
1308*61c4878aSAndroid Build Coastguard Worker     void DoOtherStuff();
1309*61c4878aSAndroid Build Coastguard Worker   }
1310*61c4878aSAndroid Build Coastguard Worker
1311*61c4878aSAndroid Build Coastguard WorkerCountingSemaphore
1312*61c4878aSAndroid Build Coastguard Worker=================
1313*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync
1314*61c4878aSAndroid Build Coastguard Worker
1315*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`CountingSemaphore` is a synchronization primitive that can be
1316*61c4878aSAndroid Build Coastguard Workerused for counting events and/or resource management where receiver(s) can block
1317*61c4878aSAndroid Build Coastguard Workeron acquire until notifier(s) signal by invoking release.
1318*61c4878aSAndroid Build Coastguard Worker
1319*61c4878aSAndroid Build Coastguard WorkerNote that unlike :cpp:class:`Mutex`, priority inheritance is not used by
1320*61c4878aSAndroid Build Coastguard Workersemaphores meaning semaphores are subject to unbounded priority inversions. Due
1321*61c4878aSAndroid Build Coastguard Workerto this, Pigweed does not recommend semaphores for mutual exclusion.
1322*61c4878aSAndroid Build Coastguard Worker
1323*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`CountingSemaphore` is initialized to being empty or having no
1324*61c4878aSAndroid Build Coastguard Workertokens.
1325*61c4878aSAndroid Build Coastguard Worker
1326*61c4878aSAndroid Build Coastguard WorkerThe entire API is thread safe, but only a subset is interrupt safe.
1327*61c4878aSAndroid Build Coastguard Worker
1328*61c4878aSAndroid Build Coastguard Worker.. Note::
1329*61c4878aSAndroid Build Coastguard Worker   If there is only a single consuming thread, use a
1330*61c4878aSAndroid Build Coastguard Worker   :cpp:class:`ThreadNotification` instead which can be much more efficient on
1331*61c4878aSAndroid Build Coastguard Worker   some RTOSes such as FreeRTOS.
1332*61c4878aSAndroid Build Coastguard Worker
1333*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
1334*61c4878aSAndroid Build Coastguard Worker
1335*61c4878aSAndroid Build Coastguard Worker.. Warning::
1336*61c4878aSAndroid Build Coastguard Worker   Releasing multiple tokens is often not natively supported, meaning you may
1337*61c4878aSAndroid Build Coastguard Worker   end up invoking the native kernel API many times, i.e. once per token you
1338*61c4878aSAndroid Build Coastguard Worker   are releasing!
1339*61c4878aSAndroid Build Coastguard Worker
1340*61c4878aSAndroid Build Coastguard Worker.. list-table::
1341*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
1342*61c4878aSAndroid Build Coastguard Worker
1343*61c4878aSAndroid Build Coastguard Worker   * - Supported on
1344*61c4878aSAndroid Build Coastguard Worker     - Backend module
1345*61c4878aSAndroid Build Coastguard Worker   * - FreeRTOS
1346*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_freertos`
1347*61c4878aSAndroid Build Coastguard Worker   * - ThreadX
1348*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_threadx`
1349*61c4878aSAndroid Build Coastguard Worker   * - embOS
1350*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_embos`
1351*61c4878aSAndroid Build Coastguard Worker   * - STL
1352*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_stl`
1353*61c4878aSAndroid Build Coastguard Worker   * - Zephyr
1354*61c4878aSAndroid Build Coastguard Worker     - Planned
1355*61c4878aSAndroid Build Coastguard Worker   * - CMSIS-RTOS API v2 & RTX5
1356*61c4878aSAndroid Build Coastguard Worker     - Planned
1357*61c4878aSAndroid Build Coastguard Worker
1358*61c4878aSAndroid Build Coastguard WorkerC++
1359*61c4878aSAndroid Build Coastguard Worker---
1360*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::CountingSemaphore
1361*61c4878aSAndroid Build Coastguard Worker   :members:
1362*61c4878aSAndroid Build Coastguard Worker
1363*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::CountingSemaphore
1364*61c4878aSAndroid Build Coastguard Worker
1365*61c4878aSAndroid Build Coastguard Worker.. list-table::
1366*61c4878aSAndroid Build Coastguard Worker   :widths: 70 10 10 10
1367*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
1368*61c4878aSAndroid Build Coastguard Worker
1369*61c4878aSAndroid Build Coastguard Worker   * - Safe to use in context
1370*61c4878aSAndroid Build Coastguard Worker     - Thread
1371*61c4878aSAndroid Build Coastguard Worker     - Interrupt
1372*61c4878aSAndroid Build Coastguard Worker     - NMI
1373*61c4878aSAndroid Build Coastguard Worker   * - :cpp:class:`pw::sync::CountingSemaphore::CountingSemaphore`
1374*61c4878aSAndroid Build Coastguard Worker     - ✔
1375*61c4878aSAndroid Build Coastguard Worker     -
1376*61c4878aSAndroid Build Coastguard Worker     -
1377*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw::sync::CountingSemaphore::~CountingSemaphore`
1378*61c4878aSAndroid Build Coastguard Worker     - ✔
1379*61c4878aSAndroid Build Coastguard Worker     -
1380*61c4878aSAndroid Build Coastguard Worker     -
1381*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`acquire`
1382*61c4878aSAndroid Build Coastguard Worker     - ✔
1383*61c4878aSAndroid Build Coastguard Worker     -
1384*61c4878aSAndroid Build Coastguard Worker     -
1385*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_acquire`
1386*61c4878aSAndroid Build Coastguard Worker     - ✔
1387*61c4878aSAndroid Build Coastguard Worker     - ✔
1388*61c4878aSAndroid Build Coastguard Worker     -
1389*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_acquire_for`
1390*61c4878aSAndroid Build Coastguard Worker     - ✔
1391*61c4878aSAndroid Build Coastguard Worker     -
1392*61c4878aSAndroid Build Coastguard Worker     -
1393*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_acquire_until`
1394*61c4878aSAndroid Build Coastguard Worker     - ✔
1395*61c4878aSAndroid Build Coastguard Worker     -
1396*61c4878aSAndroid Build Coastguard Worker     -
1397*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`release`
1398*61c4878aSAndroid Build Coastguard Worker     - ✔
1399*61c4878aSAndroid Build Coastguard Worker     - ✔
1400*61c4878aSAndroid Build Coastguard Worker     -
1401*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`max`
1402*61c4878aSAndroid Build Coastguard Worker     - ✔
1403*61c4878aSAndroid Build Coastguard Worker     - ✔
1404*61c4878aSAndroid Build Coastguard Worker     - ✔
1405*61c4878aSAndroid Build Coastguard Worker
1406*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
1407*61c4878aSAndroid Build Coastguard Worker
1408*61c4878aSAndroid Build Coastguard WorkerExamples in C++
1409*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^
1410*61c4878aSAndroid Build Coastguard WorkerAs an example, a counting sempahore can be useful to run periodic tasks at
1411*61c4878aSAndroid Build Coastguard Workerfrequencies near or higher than the system clock tick rate in a way which lets
1412*61c4878aSAndroid Build Coastguard Workeryou detect whether you ever fall behind.
1413*61c4878aSAndroid Build Coastguard Worker
1414*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
1415*61c4878aSAndroid Build Coastguard Worker
1416*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/counting_semaphore.h"
1417*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread/thread_core.h"
1418*61c4878aSAndroid Build Coastguard Worker
1419*61c4878aSAndroid Build Coastguard Worker   class PeriodicWorker() : public pw::thread::ThreadCore {
1420*61c4878aSAndroid Build Coastguard Worker    // Public API invoked by a higher frequency timer interrupt.
1421*61c4878aSAndroid Build Coastguard Worker    void TimeToExecute() {
1422*61c4878aSAndroid Build Coastguard Worker      periodic_run_semaphore_.release();
1423*61c4878aSAndroid Build Coastguard Worker    }
1424*61c4878aSAndroid Build Coastguard Worker
1425*61c4878aSAndroid Build Coastguard Worker    private:
1426*61c4878aSAndroid Build Coastguard Worker     pw::sync::CountingSemaphore periodic_run_semaphore_;
1427*61c4878aSAndroid Build Coastguard Worker
1428*61c4878aSAndroid Build Coastguard Worker     // Thread function.
1429*61c4878aSAndroid Build Coastguard Worker     void Run() override {
1430*61c4878aSAndroid Build Coastguard Worker       while (true) {
1431*61c4878aSAndroid Build Coastguard Worker         size_t behind_by_n_cycles = 0;
1432*61c4878aSAndroid Build Coastguard Worker         periodic_run_semaphore_.acquire(); // Wait to run until it's time.
1433*61c4878aSAndroid Build Coastguard Worker         while (periodic_run_semaphore_.try_acquire()) {
1434*61c4878aSAndroid Build Coastguard Worker           ++behind_by_n_cycles;
1435*61c4878aSAndroid Build Coastguard Worker         }
1436*61c4878aSAndroid Build Coastguard Worker         if (behind_by_n_cycles > 0) {
1437*61c4878aSAndroid Build Coastguard Worker           PW_LOG_WARNING("Not keeping up, behind by %d cycles",
1438*61c4878aSAndroid Build Coastguard Worker                          behind_by_n_cycles);
1439*61c4878aSAndroid Build Coastguard Worker         }
1440*61c4878aSAndroid Build Coastguard Worker         DoPeriodicWork();
1441*61c4878aSAndroid Build Coastguard Worker       }
1442*61c4878aSAndroid Build Coastguard Worker     }
1443*61c4878aSAndroid Build Coastguard Worker
1444*61c4878aSAndroid Build Coastguard Worker     void DoPeriodicWork();
1445*61c4878aSAndroid Build Coastguard Worker   }
1446*61c4878aSAndroid Build Coastguard Worker
1447*61c4878aSAndroid Build Coastguard Worker.. _module-pw_sync-binary-semaphore:
1448*61c4878aSAndroid Build Coastguard Worker
1449*61c4878aSAndroid Build Coastguard WorkerBinarySemaphore
1450*61c4878aSAndroid Build Coastguard Worker===============
1451*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync
1452*61c4878aSAndroid Build Coastguard Worker
1453*61c4878aSAndroid Build Coastguard Worker:cpp:class:`BinarySemaphore` is a specialization of CountingSemaphore with an
1454*61c4878aSAndroid Build Coastguard Workerarbitrary token limit of 1. Note that that ``max()`` is >= 1, meaning it may be
1455*61c4878aSAndroid Build Coastguard Workerreleased up to ``max()`` times but only acquired once for those N releases.
1456*61c4878aSAndroid Build Coastguard Worker
1457*61c4878aSAndroid Build Coastguard WorkerImplementations of :cpp:class:`BinarySemaphore` are typically more
1458*61c4878aSAndroid Build Coastguard Workerefficient than the default implementation of :cpp:class:`CountingSemaphore`.
1459*61c4878aSAndroid Build Coastguard Worker
1460*61c4878aSAndroid Build Coastguard WorkerThe :cpp:class:`BinarySemaphore` is initialized to being empty or having no
1461*61c4878aSAndroid Build Coastguard Workertokens.
1462*61c4878aSAndroid Build Coastguard Worker
1463*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
1464*61c4878aSAndroid Build Coastguard Worker
1465*61c4878aSAndroid Build Coastguard WorkerThe entire API is thread safe, but only a subset is interrupt safe.
1466*61c4878aSAndroid Build Coastguard Worker
1467*61c4878aSAndroid Build Coastguard Worker.. Note::
1468*61c4878aSAndroid Build Coastguard Worker   If there is only a single consuming thread, use a
1469*61c4878aSAndroid Build Coastguard Worker   :cpp:class:`ThreadNotification` instead which can be much more efficient on
1470*61c4878aSAndroid Build Coastguard Worker   some RTOSes such as FreeRTOS.
1471*61c4878aSAndroid Build Coastguard Worker
1472*61c4878aSAndroid Build Coastguard Worker.. list-table::
1473*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
1474*61c4878aSAndroid Build Coastguard Worker
1475*61c4878aSAndroid Build Coastguard Worker   * - Supported on
1476*61c4878aSAndroid Build Coastguard Worker     - Backend module
1477*61c4878aSAndroid Build Coastguard Worker   * - FreeRTOS
1478*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_freertos`
1479*61c4878aSAndroid Build Coastguard Worker   * - ThreadX
1480*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_threadx`
1481*61c4878aSAndroid Build Coastguard Worker   * - embOS
1482*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_embos`
1483*61c4878aSAndroid Build Coastguard Worker   * - STL
1484*61c4878aSAndroid Build Coastguard Worker     - :ref:`module-pw_sync_stl`
1485*61c4878aSAndroid Build Coastguard Worker   * - Zephyr
1486*61c4878aSAndroid Build Coastguard Worker     - Planned
1487*61c4878aSAndroid Build Coastguard Worker   * - CMSIS-RTOS API v2 & RTX5
1488*61c4878aSAndroid Build Coastguard Worker     - Planned
1489*61c4878aSAndroid Build Coastguard Worker
1490*61c4878aSAndroid Build Coastguard WorkerC++
1491*61c4878aSAndroid Build Coastguard Worker---
1492*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::sync::BinarySemaphore
1493*61c4878aSAndroid Build Coastguard Worker   :members:
1494*61c4878aSAndroid Build Coastguard Worker
1495*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-push:: pw::sync::BinarySemaphore
1496*61c4878aSAndroid Build Coastguard Worker
1497*61c4878aSAndroid Build Coastguard Worker.. list-table::
1498*61c4878aSAndroid Build Coastguard Worker   :widths: 70 10 10 10
1499*61c4878aSAndroid Build Coastguard Worker   :header-rows: 1
1500*61c4878aSAndroid Build Coastguard Worker
1501*61c4878aSAndroid Build Coastguard Worker   * - Safe to use in context
1502*61c4878aSAndroid Build Coastguard Worker     - Thread
1503*61c4878aSAndroid Build Coastguard Worker     - Interrupt
1504*61c4878aSAndroid Build Coastguard Worker     - NMI
1505*61c4878aSAndroid Build Coastguard Worker   * - :cpp:class:`pw::sync::BinarySemaphore::BinarySemaphore`
1506*61c4878aSAndroid Build Coastguard Worker     - ✔
1507*61c4878aSAndroid Build Coastguard Worker     -
1508*61c4878aSAndroid Build Coastguard Worker     -
1509*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`pw::sync::BinarySemaphore::~BinarySemaphore`
1510*61c4878aSAndroid Build Coastguard Worker     - ✔
1511*61c4878aSAndroid Build Coastguard Worker     -
1512*61c4878aSAndroid Build Coastguard Worker     -
1513*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`acquire`
1514*61c4878aSAndroid Build Coastguard Worker     - ✔
1515*61c4878aSAndroid Build Coastguard Worker     -
1516*61c4878aSAndroid Build Coastguard Worker     -
1517*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_acquire`
1518*61c4878aSAndroid Build Coastguard Worker     - ✔
1519*61c4878aSAndroid Build Coastguard Worker     - ✔
1520*61c4878aSAndroid Build Coastguard Worker     -
1521*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_acquire_for`
1522*61c4878aSAndroid Build Coastguard Worker     - ✔
1523*61c4878aSAndroid Build Coastguard Worker     -
1524*61c4878aSAndroid Build Coastguard Worker     -
1525*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`try_acquire_until`
1526*61c4878aSAndroid Build Coastguard Worker     - ✔
1527*61c4878aSAndroid Build Coastguard Worker     -
1528*61c4878aSAndroid Build Coastguard Worker     -
1529*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`release`
1530*61c4878aSAndroid Build Coastguard Worker     - ✔
1531*61c4878aSAndroid Build Coastguard Worker     - ✔
1532*61c4878aSAndroid Build Coastguard Worker     -
1533*61c4878aSAndroid Build Coastguard Worker   * - :cpp:func:`max`
1534*61c4878aSAndroid Build Coastguard Worker     - ✔
1535*61c4878aSAndroid Build Coastguard Worker     - ✔
1536*61c4878aSAndroid Build Coastguard Worker     - ✔
1537*61c4878aSAndroid Build Coastguard Worker
1538*61c4878aSAndroid Build Coastguard Worker.. cpp:namespace-pop::
1539*61c4878aSAndroid Build Coastguard Worker
1540*61c4878aSAndroid Build Coastguard WorkerExamples in C++
1541*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^
1542*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
1543*61c4878aSAndroid Build Coastguard Worker
1544*61c4878aSAndroid Build Coastguard Worker   #include "pw_sync/binary_semaphore.h"
1545*61c4878aSAndroid Build Coastguard Worker   #include "pw_thread/thread_core.h"
1546*61c4878aSAndroid Build Coastguard Worker
1547*61c4878aSAndroid Build Coastguard Worker   class FooHandler() : public pw::thread::ThreadCore {
1548*61c4878aSAndroid Build Coastguard Worker    // Public API invoked by other threads and/or interrupts.
1549*61c4878aSAndroid Build Coastguard Worker    void NewFooAvailable() {
1550*61c4878aSAndroid Build Coastguard Worker      new_foo_semaphore_.release();
1551*61c4878aSAndroid Build Coastguard Worker    }
1552*61c4878aSAndroid Build Coastguard Worker
1553*61c4878aSAndroid Build Coastguard Worker    private:
1554*61c4878aSAndroid Build Coastguard Worker     pw::sync::BinarySemaphore new_foo_semaphore_;
1555*61c4878aSAndroid Build Coastguard Worker
1556*61c4878aSAndroid Build Coastguard Worker     // Thread function.
1557*61c4878aSAndroid Build Coastguard Worker     void Run() override {
1558*61c4878aSAndroid Build Coastguard Worker       while (true) {
1559*61c4878aSAndroid Build Coastguard Worker         if (new_foo_semaphore_.try_acquire_for(kNotificationTimeout)) {
1560*61c4878aSAndroid Build Coastguard Worker           HandleFoo();
1561*61c4878aSAndroid Build Coastguard Worker         }
1562*61c4878aSAndroid Build Coastguard Worker         DoOtherStuff();
1563*61c4878aSAndroid Build Coastguard Worker       }
1564*61c4878aSAndroid Build Coastguard Worker     }
1565*61c4878aSAndroid Build Coastguard Worker
1566*61c4878aSAndroid Build Coastguard Worker     void HandleFoo();
1567*61c4878aSAndroid Build Coastguard Worker     void DoOtherStuff();
1568*61c4878aSAndroid Build Coastguard Worker   }
1569*61c4878aSAndroid Build Coastguard Worker
1570*61c4878aSAndroid Build Coastguard Worker.. _module-pw_sync-condition-variables:
1571*61c4878aSAndroid Build Coastguard Worker
1572*61c4878aSAndroid Build Coastguard WorkerCondition Variables
1573*61c4878aSAndroid Build Coastguard Worker=====================
1574*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::sync::ConditionVariable` provides a condition variable
1575*61c4878aSAndroid Build Coastguard Workerimplementation that provides semantics and an API very similar to
1576*61c4878aSAndroid Build Coastguard Worker`std::condition_variable
1577*61c4878aSAndroid Build Coastguard Worker<https://en.cppreference.com/w/cpp/thread/condition_variable>`_ in the C++
1578*61c4878aSAndroid Build Coastguard WorkerStandard Library.
1579*61c4878aSAndroid Build Coastguard Worker
1580*61c4878aSAndroid Build Coastguard Worker.. warning::
1581*61c4878aSAndroid Build Coastguard Worker   Condition variables are not a good abstraction for embedded due to spurious
1582*61c4878aSAndroid Build Coastguard Worker   wakeups. As a result, the only ``pw_sync`` backend provided by Pigweed that
1583*61c4878aSAndroid Build Coastguard Worker   supports condition variables is :ref:`module-pw_sync_stl`. Consider using
1584*61c4878aSAndroid Build Coastguard Worker   a ``ThreadNotification`` instead, as these do not cause spurious wakeups and
1585*61c4878aSAndroid Build Coastguard Worker   can be used in an interrupt context.
1586*61c4878aSAndroid Build Coastguard Worker
1587*61c4878aSAndroid Build Coastguard WorkerLimitations
1588*61c4878aSAndroid Build Coastguard Worker-----------
1589*61c4878aSAndroid Build Coastguard WorkerAs a blocking operation, condition variables should not be waited on in an
1590*61c4878aSAndroid Build Coastguard Workerinterrupt context. Less intuitively, condition variables should not be notified
1591*61c4878aSAndroid Build Coastguard Workerin an interrupt context. Notifying a condition variable involves checking the
1592*61c4878aSAndroid Build Coastguard Workercorresponding condition to decide whether to resume waiting threads. This check
1593*61c4878aSAndroid Build Coastguard Workercan happen either on the signaling thread or the waiting thread:
1594*61c4878aSAndroid Build Coastguard Worker
1595*61c4878aSAndroid Build Coastguard Worker- If the signaling thread checks the condition, it needs to exclusively access
1596*61c4878aSAndroid Build Coastguard Worker  the waiters and their associated conditions. Access to this list must be
1597*61c4878aSAndroid Build Coastguard Worker  synchronized with calls to wait on the variable. Additional state checked by
1598*61c4878aSAndroid Build Coastguard Worker  the conditions may also need to be synchronized. As a result, checking the
1599*61c4878aSAndroid Build Coastguard Worker  conditions on the signaling thread may involve blocking and is not suitable
1600*61c4878aSAndroid Build Coastguard Worker  for a interrupt context.
1601*61c4878aSAndroid Build Coastguard Worker- If the waiting threads check their conditions, access to the list of waiters
1602*61c4878aSAndroid Build Coastguard Worker  still needs to be synchronized. Additionally, a thread may find that its
1603*61c4878aSAndroid Build Coastguard Worker  condition is not satisfied, and that it needs to resume waiting. Waking
1604*61c4878aSAndroid Build Coastguard Worker  threads only to resume waiting is costly in terms of both power and
1605*61c4878aSAndroid Build Coastguard Worker  performance.
1606*61c4878aSAndroid Build Coastguard Worker
1607*61c4878aSAndroid Build Coastguard WorkerThe second approach leads to spurious wakeups in a thread context as well. The
1608*61c4878aSAndroid Build Coastguard Workerfirst approach may also have spurious wakeups if the condition changes between
1609*61c4878aSAndroid Build Coastguard Workersignaling the waiter and the waiter reacquiring its lock.
1610*61c4878aSAndroid Build Coastguard Worker
1611*61c4878aSAndroid Build Coastguard Worker.. toctree::
1612*61c4878aSAndroid Build Coastguard Worker   :hidden:
1613*61c4878aSAndroid Build Coastguard Worker   :maxdepth: 1
1614*61c4878aSAndroid Build Coastguard Worker
1615*61c4878aSAndroid Build Coastguard Worker   Backends <backends>
1616