xref: /aosp_15_r20/external/pigweed/pw_sync/public/pw_sync/lock_traits.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2023 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 <type_traits>
17 #include <utility>
18 
19 /// This file provide trait types that can be used to check C++ lock-related
20 /// named requirements: BasicLockable, Lockable, and TimedLockable.
21 
22 namespace pw::sync {
23 
24 /// Checks if a type is a basic lock.
25 ///
26 /// If `Lock` satisfies \em BasicLockable, provides the member constant value
27 /// equal to true. Otherwise value is false.
28 ///
29 /// @{
30 template <typename Lock, typename = void>
31 struct is_basic_lockable : std::false_type {};
32 
33 template <typename Lock>
34 struct is_basic_lockable<Lock,
35                          std::void_t<decltype(std::declval<Lock>().lock()),
36                                      decltype(std::declval<Lock>().unlock())>>
37     : std::true_type {};
38 /// @}
39 
40 /// Helper variable template for `is_basic_lockable<Lock>::value`.
41 template <typename Lock>
42 inline constexpr bool is_basic_lockable_v = is_basic_lockable<Lock>::value;
43 
44 /// Checks if a type is a lock.
45 ///
46 /// If `Lock` satisfies C++'s \em Lockable named requirement, provides the
47 /// member constant value equal to true. Otherwise value is false.
48 ///
49 /// @{
50 template <typename Lock, typename = void>
51 struct is_lockable : std::false_type {};
52 
53 template <typename Lock>
54 struct is_lockable<Lock, std::void_t<decltype(std::declval<Lock>().try_lock())>>
55     : is_basic_lockable<Lock> {};
56 /// @}
57 
58 /// Helper variable template for `is_lockable<Lock>::value`.
59 template <typename Lock>
60 inline constexpr bool is_lockable_v = is_lockable<Lock>::value;
61 
62 /// Checks if a type is can be locked within a set time.
63 ///
64 /// If `Lock` has a valid `try_lock_for` method, as described by C++'s
65 /// \em TimedLockable named requirement, provides the member constant value
66 /// equal to true. Otherwise value is false.
67 ///
68 /// @{
69 template <typename Lock, typename Duration, typename = void>
70 struct is_lockable_for : std::false_type {};
71 
72 template <typename Lock, typename Duration>
73 struct is_lockable_for<Lock,
74                        Duration,
75                        std::void_t<decltype(std::declval<Lock>().try_lock_for(
76                            std::declval<Duration>()))>> : is_lockable<Lock> {};
77 /// @}
78 
79 /// Helper variable template for `is_lockable_for<Lock, Duration>::value`.
80 template <typename Lock, typename Duration>
81 inline constexpr bool is_lockable_for_v =
82     is_lockable_for<Lock, Duration>::value;
83 
84 /// Checks if a type is can be locked by a set time.
85 ///
86 /// If `Lock` has a valid `try_lock_until` method, as described by C++'s
87 /// \em TimedLockable named requirement, provides the member constant value
88 /// equal to true. Otherwise value is false.
89 ///
90 /// @{
91 template <typename Lock, typename TimePoint, typename = void>
92 struct is_lockable_until : std::false_type {};
93 
94 template <typename Lock, typename TimePoint>
95 struct is_lockable_until<
96     Lock,
97     TimePoint,
98     std::void_t<decltype(std::declval<Lock>().try_lock_until(
99         std::declval<TimePoint>()))>> : is_lockable<Lock> {};
100 /// @}
101 
102 /// Helper variable template for `is_lockable_until<Lock, TimePoint>::value`.
103 template <typename Lock, typename TimePoint>
104 inline constexpr bool is_lockable_until_v =
105     is_lockable_until<Lock, TimePoint>::value;
106 
107 /// Checks if a lock type is timed-lockable.
108 ///
109 /// If `Lock` satisfies C++'s \em TimedLockable named requirement, provides the
110 /// member constant value equal to true. Otherwise value is false.
111 template <typename Lock, typename Clock>
112 struct is_timed_lockable
113     : std::integral_constant<
114           bool,
115           is_lockable_for_v<Lock, typename Clock::duration> &&
116               is_lockable_until_v<Lock, typename Clock::time_point>> {};
117 
118 /// Helper variable template for `is_timed_lockable<Lock, Clock>::value`.
119 template <typename Lock, typename Clock>
120 inline constexpr bool is_timed_lockable_v =
121     is_timed_lockable<Lock, Clock>::value;
122 
123 }  // namespace pw::sync
124