1*9356374aSAndroid Build Coastguard Worker // Copyright 2023 The Abseil Authors. 2*9356374aSAndroid Build Coastguard Worker // 3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*9356374aSAndroid Build Coastguard Worker // 7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 8*9356374aSAndroid Build Coastguard Worker // 9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*9356374aSAndroid Build Coastguard Worker // limitations under the License. 14*9356374aSAndroid Build Coastguard Worker // 15*9356374aSAndroid Build Coastguard Worker 16*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_SYNCHRONIZATION_INTERNAL_WAITER_BASE_H_ 17*9356374aSAndroid Build Coastguard Worker #define ABSL_SYNCHRONIZATION_INTERNAL_WAITER_BASE_H_ 18*9356374aSAndroid Build Coastguard Worker 19*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h" 20*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/thread_identity.h" 21*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/internal/kernel_timeout.h" 22*9356374aSAndroid Build Coastguard Worker 23*9356374aSAndroid Build Coastguard Worker namespace absl { 24*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN 25*9356374aSAndroid Build Coastguard Worker namespace synchronization_internal { 26*9356374aSAndroid Build Coastguard Worker 27*9356374aSAndroid Build Coastguard Worker // `Waiter` is a platform specific semaphore implementation that `PerThreadSem` 28*9356374aSAndroid Build Coastguard Worker // waits on to implement blocking in `absl::Mutex`. Implementations should 29*9356374aSAndroid Build Coastguard Worker // inherit from `WaiterCrtp` and must implement `Wait()`, `Post()`, and `Poke()` 30*9356374aSAndroid Build Coastguard Worker // as described in `WaiterBase`. `waiter.h` selects the implementation and uses 31*9356374aSAndroid Build Coastguard Worker // static-dispatch for performance. 32*9356374aSAndroid Build Coastguard Worker class WaiterBase { 33*9356374aSAndroid Build Coastguard Worker public: 34*9356374aSAndroid Build Coastguard Worker WaiterBase() = default; 35*9356374aSAndroid Build Coastguard Worker 36*9356374aSAndroid Build Coastguard Worker // Not copyable or movable 37*9356374aSAndroid Build Coastguard Worker WaiterBase(const WaiterBase&) = delete; 38*9356374aSAndroid Build Coastguard Worker WaiterBase& operator=(const WaiterBase&) = delete; 39*9356374aSAndroid Build Coastguard Worker 40*9356374aSAndroid Build Coastguard Worker // Blocks the calling thread until a matching call to `Post()` or 41*9356374aSAndroid Build Coastguard Worker // `t` has passed. Returns `true` if woken (`Post()` called), 42*9356374aSAndroid Build Coastguard Worker // `false` on timeout. 43*9356374aSAndroid Build Coastguard Worker // 44*9356374aSAndroid Build Coastguard Worker // bool Wait(KernelTimeout t); 45*9356374aSAndroid Build Coastguard Worker 46*9356374aSAndroid Build Coastguard Worker // Restart the caller of `Wait()` as with a normal semaphore. 47*9356374aSAndroid Build Coastguard Worker // 48*9356374aSAndroid Build Coastguard Worker // void Post(); 49*9356374aSAndroid Build Coastguard Worker 50*9356374aSAndroid Build Coastguard Worker // If anyone is waiting, wake them up temporarily and cause them to 51*9356374aSAndroid Build Coastguard Worker // call `MaybeBecomeIdle()`. They will then return to waiting for a 52*9356374aSAndroid Build Coastguard Worker // `Post()` or timeout. 53*9356374aSAndroid Build Coastguard Worker // 54*9356374aSAndroid Build Coastguard Worker // void Poke(); 55*9356374aSAndroid Build Coastguard Worker 56*9356374aSAndroid Build Coastguard Worker // Returns the name of this implementation. Used only for debugging. 57*9356374aSAndroid Build Coastguard Worker // 58*9356374aSAndroid Build Coastguard Worker // static constexpr char kName[]; 59*9356374aSAndroid Build Coastguard Worker 60*9356374aSAndroid Build Coastguard Worker // How many periods to remain idle before releasing resources 61*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_HAVE_THREAD_SANITIZER 62*9356374aSAndroid Build Coastguard Worker static constexpr int kIdlePeriods = 60; 63*9356374aSAndroid Build Coastguard Worker #else 64*9356374aSAndroid Build Coastguard Worker // Memory consumption under ThreadSanitizer is a serious concern, 65*9356374aSAndroid Build Coastguard Worker // so we release resources sooner. The value of 1 leads to 1 to 2 second 66*9356374aSAndroid Build Coastguard Worker // delay before marking a thread as idle. 67*9356374aSAndroid Build Coastguard Worker static constexpr int kIdlePeriods = 1; 68*9356374aSAndroid Build Coastguard Worker #endif 69*9356374aSAndroid Build Coastguard Worker 70*9356374aSAndroid Build Coastguard Worker protected: 71*9356374aSAndroid Build Coastguard Worker static void MaybeBecomeIdle(); 72*9356374aSAndroid Build Coastguard Worker }; 73*9356374aSAndroid Build Coastguard Worker 74*9356374aSAndroid Build Coastguard Worker template <typename T> 75*9356374aSAndroid Build Coastguard Worker class WaiterCrtp : public WaiterBase { 76*9356374aSAndroid Build Coastguard Worker public: 77*9356374aSAndroid Build Coastguard Worker // Returns the Waiter associated with the identity. GetWaiter(base_internal::ThreadIdentity * identity)78*9356374aSAndroid Build Coastguard Worker static T* GetWaiter(base_internal::ThreadIdentity* identity) { 79*9356374aSAndroid Build Coastguard Worker static_assert( 80*9356374aSAndroid Build Coastguard Worker sizeof(T) <= sizeof(base_internal::ThreadIdentity::WaiterState), 81*9356374aSAndroid Build Coastguard Worker "Insufficient space for Waiter"); 82*9356374aSAndroid Build Coastguard Worker return reinterpret_cast<T*>(identity->waiter_state.data); 83*9356374aSAndroid Build Coastguard Worker } 84*9356374aSAndroid Build Coastguard Worker }; 85*9356374aSAndroid Build Coastguard Worker 86*9356374aSAndroid Build Coastguard Worker } // namespace synchronization_internal 87*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END 88*9356374aSAndroid Build Coastguard Worker } // namespace absl 89*9356374aSAndroid Build Coastguard Worker 90*9356374aSAndroid Build Coastguard Worker #endif // ABSL_SYNCHRONIZATION_INTERNAL_WAITER_BASE_H_ 91