pw_sync: split out pw::sync::TimedMutex from pw::sync::Mutex
Change-Id: I6a52123759045658cc21aaa3254279d95c23ed6e
Requires: pigweed-internal:11280
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/40083
Reviewed-by: Wyatt Hepler <hepler@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Pigweed-Auto-Submit: Ewout van Bekkum <ewout@google.com>
diff --git a/pw_sync/docs.rst b/pw_sync/docs.rst
index aec5900..de5a125 100644
--- a/pw_sync/docs.rst
+++ b/pw_sync/docs.rst
@@ -45,15 +45,10 @@
the classic priority-inversion problem.
The Mutex's API is C++11 STL
-`std::timed_mutex <https://en.cppreference.com/w/cpp/thread/timed_mutex>`_ like,
+`std::mutex <https://en.cppreference.com/w/cpp/thread/mutex>`_ like,
meaning it is a
-`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_,
-`Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_, and
-`TimedLockable <https://en.cppreference.com/w/cpp/named_req/TimedLockable>`_.
-
-.. Warning::
- This interface will likely be split between a Mutex and TimedMutex to ease
- portability for baremetal support.
+`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_
+and `Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_.
.. list-table::
@@ -93,6 +88,177 @@
**Precondition:** The lock isn't already held by this thread. Recursive
locking is undefined behavior.
+ .. cpp:function:: void unlock()
+
+ Unlocks the mutex. Failures are fatal.
+
+ **Precondition:** The mutex is held by this thread.
+
+
+ .. list-table::
+
+ * - *Safe to use in context*
+ - *Thread*
+ - *Interrupt*
+ - *NMI*
+ * - ``Mutex::Mutex``
+ - ✔
+ -
+ -
+ * - ``Mutex::~Mutex``
+ - ✔
+ -
+ -
+ * - ``void Mutex::lock``
+ - ✔
+ -
+ -
+ * - ``bool Mutex::try_lock``
+ - ✔
+ -
+ -
+ * - ``void Mutex::unlock``
+ - ✔
+ -
+ -
+
+Examples in C++
+^^^^^^^^^^^^^^^
+.. code-block:: cpp
+
+ #include "pw_sync/mutex.h"
+
+ pw::sync::Mutex mutex;
+
+ void ThreadSafeCriticalSection() {
+ mutex.lock();
+ NotThreadSafeCriticalSection();
+ mutex.unlock();
+ }
+
+
+Alternatively you can use C++'s RAII helpers to ensure you always unlock.
+
+.. code-block:: cpp
+
+ #include <mutex>
+
+ #include "pw_sync/mutex.h"
+
+ pw::sync::Mutex mutex;
+
+ void ThreadSafeCriticalSection() {
+ std::lock_guard lock(mutex);
+ NotThreadSafeCriticalSection();
+ }
+
+
+C
+-
+The Mutex must be created in C++, however it can be passed into C using the
+``pw_sync_Mutex`` opaque struct alias.
+
+.. cpp:function:: void pw_sync_Mutex_Lock(pw_sync_Mutex* mutex)
+
+ Invokes the ``Mutex::lock`` member function on the given ``mutex``.
+
+.. cpp:function:: bool pw_sync_Mutex_TryLock(pw_sync_Mutex* mutex)
+
+ Invokes the ``Mutex::try_lock`` member function on the given ``mutex``.
+
+.. cpp:function:: void pw_sync_Mutex_Unlock(pw_sync_Mutex* mutex)
+
+ Invokes the ``Mutex::unlock`` member function on the given ``mutex``.
+
+.. list-table::
+
+ * - *Safe to use in context*
+ - *Thread*
+ - *Interrupt*
+ - *NMI*
+ * - ``void pw_sync_Mutex_Lock``
+ - ✔
+ -
+ -
+ * - ``bool pw_sync_Mutex_TryLock``
+ - ✔
+ -
+ -
+ * - ``void pw_sync_Mutex_Unlock``
+ - ✔
+ -
+ -
+
+Example in C
+^^^^^^^^^^^^
+.. code-block:: cpp
+
+ #include "pw_sync/mutex.h"
+
+ pw::sync::Mutex mutex;
+
+ extern pw_sync_Mutex mutex; // This can only be created in C++.
+
+ void ThreadSafeCriticalSection(void) {
+ pw_sync_Mutex_Lock(&mutex);
+ NotThreadSafeCriticalSection();
+ pw_sync_Mutex_Unlock(&mutex);
+ }
+
+TimedMutex
+==========
+The TimedMutex is an extension of the Mutex which offers timeout and deadline
+based semantics.
+
+The TimedMutex's API is C++11 STL
+`std::timed_mutex <https://en.cppreference.com/w/cpp/thread/timed_mutex>`_ like,
+meaning it is a
+`BasicLockable <https://en.cppreference.com/w/cpp/named_req/BasicLockable>`_,
+`Lockable <https://en.cppreference.com/w/cpp/named_req/Lockable>`_, and
+`TimedLockable <https://en.cppreference.com/w/cpp/named_req/TimedLockable>`_.
+
+Note that the ``TimedMutex`` is a derived ``Mutex`` class, meaning that
+a ``TimedMutex`` can be used by someone who needs the basic ``Mutex``. This is
+in stark contrast to the C++ STL's
+`std::timed_mutex <https://en.cppreference.com/w/cpp/thread/timed_mutex>`_.
+
+
+.. list-table::
+
+ * - *Supported on*
+ - *Backend module*
+ * - FreeRTOS
+ - :ref:`module-pw_sync_freertos`
+ * - ThreadX
+ - :ref:`module-pw_sync_threadx`
+ * - embOS
+ - :ref:`module-pw_sync_embos`
+ * - STL
+ - :ref:`module-pw_sync_stl`
+ * - Zephyr
+ - Planned
+ * - CMSIS-RTOS API v2 & RTX5
+ - Planned
+
+C++
+---
+.. cpp:class:: pw::sync::TimedMutex
+
+ .. cpp:function:: void lock()
+
+ Locks the mutex, blocking indefinitely. Failures are fatal.
+
+ **Precondition:** The lock isn't already held by this thread. Recursive
+ locking is undefined behavior.
+
+ .. cpp:function:: bool try_lock()
+
+ Attempts to lock the mutex in a non-blocking manner.
+ Returns true if the mutex was successfully acquired.
+
+ **Precondition:** The lock isn't already held by this thread. Recursive
+ locking is undefined behavior.
+
.. cpp:function:: bool try_lock_for(chrono::SystemClock::duration for_at_least)
Attempts to lock the mutex where, if needed, blocking for at least the
@@ -124,31 +290,31 @@
- *Thread*
- *Interrupt*
- *NMI*
- * - ``Mutex::Mutex``
+ * - ``TimedMutex::TimedMutex``
- ✔
-
-
- * - ``Mutex::~Mutex``
+ * - ``TimedMutex::~TimedMutex``
- ✔
-
-
- * - ``void Mutex::lock``
+ * - ``void TimedMutex::lock``
- ✔
-
-
- * - ``bool Mutex::try_lock``
+ * - ``bool TimedMutex::try_lock``
- ✔
-
-
- * - ``bool Mutex::try_lock_for``
+ * - ``bool TimedMutex::try_lock_for``
- ✔
-
-
- * - ``bool Mutex::try_lock_until``
+ * - ``bool TimedMutex::try_lock_until``
- ✔
-
-
- * - ``void Mutex::unlock``
+ * - ``void TimedMutex::unlock``
- ✔
-
-
@@ -158,15 +324,9 @@
.. code-block:: cpp
#include "pw_chrono/system_clock.h"
- #include "pw_sync/mutex.h"
+ #include "pw_sync/timed_mutex.h"
- pw::sync::Mutex mutex;
-
- void ThreadSafeCriticalSection() {
- mutex.lock();
- NotThreadSafeCriticalSection();
- mutex.unlock();
- }
+ pw::sync::TimedMutex mutex;
bool ThreadSafeCriticalSectionWithTimeout(
const SystemClock::duration timeout) {
@@ -186,14 +346,9 @@
#include <mutex>
#include "pw_chrono/system_clock.h"
- #include "pw_sync/mutex.h"
+ #include "pw_sync/timed_mutex.h"
- pw::sync::Mutex mutex;
-
- void ThreadSafeCriticalSection() {
- std::lock_guard lock(mutex);
- NotThreadSafeCriticalSection();
- }
+ pw::sync::TimedMutex mutex;
bool ThreadSafeCriticalSectionWithTimeout(
const SystemClock::duration timeout) {
@@ -209,28 +364,28 @@
C
-
-The Mutex must be created in C++, however it can be passed into C using the
-``pw_sync_Mutex`` opaque struct alias.
+The TimedMutex must be created in C++, however it can be passed into C using the
+``pw_sync_TimedMutex`` opaque struct alias.
-.. cpp:function:: void pw_sync_Mutex_Lock(pw_sync_Mutex* mutex)
+.. cpp:function:: void pw_sync_TimedMutex_Lock(pw_sync_TimedMutex* mutex)
- Invokes the ``Mutex::lock`` member function on the given ``mutex``.
+ Invokes the ``TimedMutex::lock`` member function on the given ``mutex``.
-.. cpp:function:: bool pw_sync_Mutex_TryLock(pw_sync_Mutex* mutex)
+.. cpp:function:: bool pw_sync_TimedMutex_TryLock(pw_sync_TimedMutex* mutex)
- Invokes the ``Mutex::try_lock`` member function on the given ``mutex``.
+ Invokes the ``TimedMutex::try_lock`` member function on the given ``mutex``.
-.. cpp:function:: bool pw_sync_Mutex_TryLockFor(pw_sync_Mutex* mutex, pw_chrono_SystemClock_Duration for_at_least)
+.. cpp:function:: bool pw_sync_TimedMutex_TryLockFor(pw_sync_TimedMutex* mutex, pw_chrono_SystemClock_Duration for_at_least)
- Invokes the ``Mutex::try_lock_for`` member function on the given ``mutex``.
+ Invokes the ``TimedMutex::try_lock_for`` member function on the given ``mutex``.
-.. cpp:function:: bool pw_sync_Mutex_TryLockUntil(pw_sync_Mutex* mutex, pw_chrono_SystemClock_TimePoint until_at_least)
+.. cpp:function:: bool pw_sync_TimedMutex_TryLockUntil(pw_sync_TimedMutex* mutex, pw_chrono_SystemClock_TimePoint until_at_least)
- Invokes the ``Mutex::try_lock_until`` member function on the given ``mutex``.
+ Invokes the ``TimedMutex::try_lock_until`` member function on the given ``mutex``.
-.. cpp:function:: void pw_sync_Mutex_Unlock(pw_sync_Mutex* mutex)
+.. cpp:function:: void pw_sync_TimedMutex_Unlock(pw_sync_TimedMutex* mutex)
- Invokes the ``Mutex::unlock`` member function on the given ``mutex``.
+ Invokes the ``TimedMutex::unlock`` member function on the given ``mutex``.
.. list-table::
@@ -238,23 +393,23 @@
- *Thread*
- *Interrupt*
- *NMI*
- * - ``void pw_sync_Mutex_Lock``
+ * - ``void pw_sync_TimedMutex_Lock``
- ✔
-
-
- * - ``bool pw_sync_Mutex_TryLock``
+ * - ``bool pw_sync_TimedMutex_TryLock``
- ✔
-
-
- * - ``bool pw_sync_Mutex_TryLockFor``
+ * - ``bool pw_sync_TimedMutex_TryLockFor``
- ✔
-
-
- * - ``bool pw_sync_Mutex_TryLockUntil``
+ * - ``bool pw_sync_TimedMutex_TryLockUntil``
- ✔
-
-
- * - ``void pw_sync_Mutex_Unlock``
+ * - ``void pw_sync_TimedMutex_Unlock``
- ✔
-
-
@@ -264,25 +419,19 @@
.. code-block:: cpp
#include "pw_chrono/system_clock.h"
- #include "pw_sync/mutex.h"
+ #include "pw_sync/timed_mutex.h"
- pw::sync::Mutex mutex;
+ pw::sync::TimedMutex mutex;
- extern pw_sync_Mutex mutex; // This can only be created in C++.
-
- void ThreadSafeCriticalSection(void) {
- pw_sync_Mutex_Lock(&mutex);
- NotThreadSafeCriticalSection();
- pw_sync_Mutex_Unlock(&mutex);
- }
+ extern pw_sync_TimedMutex mutex; // This can only be created in C++.
bool ThreadSafeCriticalSectionWithTimeout(
const pw_chrono_SystemClock_Duration timeout) {
- if (!pw_sync_Mutex_TryLockFor(&mutex, timeout)) {
+ if (!pw_sync_TimedMutex_TryLockFor(&mutex, timeout)) {
return false;
}
NotThreadSafeCriticalSection();
- pw_sync_Mutex_Unlock(&mutex);
+ pw_sync_TimedMutex_Unlock(&mutex);
return true;
}