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