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