xref: /aosp_15_r20/external/pigweed/pw_sync/public/pw_sync/timed_mutex.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <stdbool.h>
17 
18 #include "pw_chrono/system_clock.h"
19 #include "pw_preprocessor/util.h"
20 #include "pw_sync/lock_annotations.h"
21 #include "pw_sync/mutex.h"
22 
23 #ifdef __cplusplus
24 
25 #include "pw_sync/virtual_basic_lockable.h"
26 
27 namespace pw::sync {
28 
29 /// The `TimedMutex` is a synchronization primitive that can be used to protect
30 /// shared data from being simultaneously accessed by multiple threads with
31 /// timeouts and deadlines, extending the `Mutex`. It offers exclusive,
32 /// non-recursive ownership semantics where priority inheritance is used to
33 /// solve the classic priority-inversion problem. This is thread safe, but NOT
34 /// IRQ safe.
35 ///
36 /// @rst
37 /// .. warning::
38 ///    In order to support global statically constructed TimedMutexes, the user
39 ///    and/or backend MUST ensure that any initialization required in your
40 ///    environment is done prior to the creation and/or initialization of the
41 ///    native synchronization primitives (e.g. kernel initialization).
42 /// @endrst
43 class TimedMutex : public Mutex {
44  public:
45   TimedMutex() = default;
46   ~TimedMutex() = default;
47   TimedMutex(const TimedMutex&) = delete;
48   TimedMutex(TimedMutex&&) = delete;
49   TimedMutex& operator=(const TimedMutex&) = delete;
50   TimedMutex& operator=(TimedMutex&&) = delete;
51 
52   /// Tries to lock the mutex. Blocks until specified the timeout has elapsed or
53   /// the lock is acquired, whichever comes first.
54   /// Returns true if the mutex was successfully acquired.
55   ///
56   /// @b PRECONDITION:
57   ///   The lock isn't already held by this thread. Recursive locking is
58   ///   undefined behavior.
59   [[nodiscard]] bool try_lock_for(chrono::SystemClock::duration timeout)
60       PW_EXCLUSIVE_TRYLOCK_FUNCTION(true);
61 
62   /// Tries to lock the mutex. Blocks until specified deadline has been reached
63   /// or the lock is acquired, whichever comes first.
64   /// Returns true if the mutex was successfully acquired.
65   ///
66   /// @b PRECONDITION:
67   ///   The lock isn't already held by this thread. Recursive locking is
68   ///   undefined behavior.
69   [[nodiscard]] bool try_lock_until(chrono::SystemClock::time_point deadline)
70       PW_EXCLUSIVE_TRYLOCK_FUNCTION(true);
71 };
72 
73 class PW_LOCKABLE("pw::sync::VirtualTimedMutex") VirtualTimedMutex final
74     : public GenericBasicLockable<TimedMutex> {
75  public:
timed_mutex()76   TimedMutex& timed_mutex() { return impl(); }
77 };
78 
79 }  // namespace pw::sync
80 
81 #include "pw_sync_backend/timed_mutex_inline.h"
82 
83 using pw_sync_TimedMutex = pw::sync::TimedMutex;
84 
85 #else  // !defined(__cplusplus)
86 
87 typedef struct pw_sync_TimedMutex pw_sync_TimedMutex;
88 
89 #endif  // __cplusplus
90 
91 PW_EXTERN_C_START
92 
93 /// Invokes the `TimedMutex::lock` member function on the given `mutex`.
94 void pw_sync_TimedMutex_Lock(pw_sync_TimedMutex* mutex)
95     PW_NO_LOCK_SAFETY_ANALYSIS;
96 
97 /// Invokes the `TimedMutex::try_lock` member function on the given `mutex`.
98 bool pw_sync_TimedMutex_TryLock(pw_sync_TimedMutex* mutex)
99     PW_NO_LOCK_SAFETY_ANALYSIS;
100 
101 /// Invokes the `TimedMutex::try_lock_for` member function on the given `mutex`.
102 bool pw_sync_TimedMutex_TryLockFor(pw_sync_TimedMutex* mutex,
103                                    pw_chrono_SystemClock_Duration timeout)
104     PW_NO_LOCK_SAFETY_ANALYSIS;
105 
106 /// Invokes the `TimedMutex::try_lock_until` member function on the given
107 /// `mutex`.
108 bool pw_sync_TimedMutex_TryLockUntil(pw_sync_TimedMutex* mutex,
109                                      pw_chrono_SystemClock_TimePoint deadline)
110     PW_NO_LOCK_SAFETY_ANALYSIS;
111 
112 /// Invokes the `TimedMutex::unlock` member function on the given `mutex`.
113 void pw_sync_TimedMutex_Unlock(pw_sync_TimedMutex* mutex)
114     PW_NO_LOCK_SAFETY_ANALYSIS;
115 
116 PW_EXTERN_C_END
117