xref: /aosp_15_r20/external/abseil-cpp/absl/synchronization/blocking_counter.h (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker //
2*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors.
3*9356374aSAndroid Build Coastguard Worker //
4*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*9356374aSAndroid Build Coastguard Worker //
8*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
9*9356374aSAndroid Build Coastguard Worker //
10*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*9356374aSAndroid Build Coastguard Worker // limitations under the License.
15*9356374aSAndroid Build Coastguard Worker //
16*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
17*9356374aSAndroid Build Coastguard Worker // blocking_counter.h
18*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
19*9356374aSAndroid Build Coastguard Worker 
20*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_
21*9356374aSAndroid Build Coastguard Worker #define ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_
22*9356374aSAndroid Build Coastguard Worker 
23*9356374aSAndroid Build Coastguard Worker #include <atomic>
24*9356374aSAndroid Build Coastguard Worker 
25*9356374aSAndroid Build Coastguard Worker #include "absl/base/thread_annotations.h"
26*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/mutex.h"
27*9356374aSAndroid Build Coastguard Worker 
28*9356374aSAndroid Build Coastguard Worker namespace absl {
29*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
30*9356374aSAndroid Build Coastguard Worker 
31*9356374aSAndroid Build Coastguard Worker // BlockingCounter
32*9356374aSAndroid Build Coastguard Worker //
33*9356374aSAndroid Build Coastguard Worker // This class allows a thread to block for a pre-specified number of actions.
34*9356374aSAndroid Build Coastguard Worker // `BlockingCounter` maintains a single non-negative abstract integer "count"
35*9356374aSAndroid Build Coastguard Worker // with an initial value `initial_count`. A thread can then call `Wait()` on
36*9356374aSAndroid Build Coastguard Worker // this blocking counter to block until the specified number of events occur;
37*9356374aSAndroid Build Coastguard Worker // worker threads then call 'DecrementCount()` on the counter upon completion of
38*9356374aSAndroid Build Coastguard Worker // their work. Once the counter's internal "count" reaches zero, the blocked
39*9356374aSAndroid Build Coastguard Worker // thread unblocks.
40*9356374aSAndroid Build Coastguard Worker //
41*9356374aSAndroid Build Coastguard Worker // A `BlockingCounter` requires the following:
42*9356374aSAndroid Build Coastguard Worker //     - its `initial_count` is non-negative.
43*9356374aSAndroid Build Coastguard Worker //     - the number of calls to `DecrementCount()` on it is at most
44*9356374aSAndroid Build Coastguard Worker //       `initial_count`.
45*9356374aSAndroid Build Coastguard Worker //     - `Wait()` is called at most once on it.
46*9356374aSAndroid Build Coastguard Worker //
47*9356374aSAndroid Build Coastguard Worker // Given the above requirements, a `BlockingCounter` provides the following
48*9356374aSAndroid Build Coastguard Worker // guarantees:
49*9356374aSAndroid Build Coastguard Worker //     - Once its internal "count" reaches zero, no legal action on the object
50*9356374aSAndroid Build Coastguard Worker //       can further change the value of "count".
51*9356374aSAndroid Build Coastguard Worker //     - When `Wait()` returns, it is legal to destroy the `BlockingCounter`.
52*9356374aSAndroid Build Coastguard Worker //     - When `Wait()` returns, the number of calls to `DecrementCount()` on
53*9356374aSAndroid Build Coastguard Worker //       this blocking counter exactly equals `initial_count`.
54*9356374aSAndroid Build Coastguard Worker //
55*9356374aSAndroid Build Coastguard Worker // Example:
56*9356374aSAndroid Build Coastguard Worker //     BlockingCounter bcount(N);         // there are N items of work
57*9356374aSAndroid Build Coastguard Worker //     ... Allow worker threads to start.
58*9356374aSAndroid Build Coastguard Worker //     ... On completing each work item, workers do:
59*9356374aSAndroid Build Coastguard Worker //     ... bcount.DecrementCount();      // an item of work has been completed
60*9356374aSAndroid Build Coastguard Worker //
61*9356374aSAndroid Build Coastguard Worker //     bcount.Wait();                    // wait for all work to be complete
62*9356374aSAndroid Build Coastguard Worker //
63*9356374aSAndroid Build Coastguard Worker class BlockingCounter {
64*9356374aSAndroid Build Coastguard Worker  public:
65*9356374aSAndroid Build Coastguard Worker   explicit BlockingCounter(int initial_count);
66*9356374aSAndroid Build Coastguard Worker 
67*9356374aSAndroid Build Coastguard Worker   BlockingCounter(const BlockingCounter&) = delete;
68*9356374aSAndroid Build Coastguard Worker   BlockingCounter& operator=(const BlockingCounter&) = delete;
69*9356374aSAndroid Build Coastguard Worker 
70*9356374aSAndroid Build Coastguard Worker   // BlockingCounter::DecrementCount()
71*9356374aSAndroid Build Coastguard Worker   //
72*9356374aSAndroid Build Coastguard Worker   // Decrements the counter's "count" by one, and return "count == 0". This
73*9356374aSAndroid Build Coastguard Worker   // function requires that "count != 0" when it is called.
74*9356374aSAndroid Build Coastguard Worker   //
75*9356374aSAndroid Build Coastguard Worker   // Memory ordering: For any threads X and Y, any action taken by X
76*9356374aSAndroid Build Coastguard Worker   // before it calls `DecrementCount()` is visible to thread Y after
77*9356374aSAndroid Build Coastguard Worker   // Y's call to `DecrementCount()`, provided Y's call returns `true`.
78*9356374aSAndroid Build Coastguard Worker   bool DecrementCount();
79*9356374aSAndroid Build Coastguard Worker 
80*9356374aSAndroid Build Coastguard Worker   // BlockingCounter::Wait()
81*9356374aSAndroid Build Coastguard Worker   //
82*9356374aSAndroid Build Coastguard Worker   // Blocks until the counter reaches zero. This function may be called at most
83*9356374aSAndroid Build Coastguard Worker   // once. On return, `DecrementCount()` will have been called "initial_count"
84*9356374aSAndroid Build Coastguard Worker   // times and the blocking counter may be destroyed.
85*9356374aSAndroid Build Coastguard Worker   //
86*9356374aSAndroid Build Coastguard Worker   // Memory ordering: For any threads X and Y, any action taken by X
87*9356374aSAndroid Build Coastguard Worker   // before X calls `DecrementCount()` is visible to Y after Y returns
88*9356374aSAndroid Build Coastguard Worker   // from `Wait()`.
89*9356374aSAndroid Build Coastguard Worker   void Wait();
90*9356374aSAndroid Build Coastguard Worker 
91*9356374aSAndroid Build Coastguard Worker  private:
92*9356374aSAndroid Build Coastguard Worker   Mutex lock_;
93*9356374aSAndroid Build Coastguard Worker   std::atomic<int> count_;
94*9356374aSAndroid Build Coastguard Worker   int num_waiting_ ABSL_GUARDED_BY(lock_);
95*9356374aSAndroid Build Coastguard Worker   bool done_ ABSL_GUARDED_BY(lock_);
96*9356374aSAndroid Build Coastguard Worker };
97*9356374aSAndroid Build Coastguard Worker 
98*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
99*9356374aSAndroid Build Coastguard Worker }  // namespace absl
100*9356374aSAndroid Build Coastguard Worker 
101*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_
102