|
||||
File indexing completed on 2025-01-18 09:27:28
0001 // 0002 // Copyright 2017 The Abseil Authors. 0003 // 0004 // Licensed under the Apache License, Version 2.0 (the "License"); 0005 // you may not use this file except in compliance with the License. 0006 // You may obtain a copy of the License at 0007 // 0008 // https://www.apache.org/licenses/LICENSE-2.0 0009 // 0010 // Unless required by applicable law or agreed to in writing, software 0011 // distributed under the License is distributed on an "AS IS" BASIS, 0012 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0013 // See the License for the specific language governing permissions and 0014 // limitations under the License. 0015 // 0016 // ----------------------------------------------------------------------------- 0017 // blocking_counter.h 0018 // ----------------------------------------------------------------------------- 0019 0020 #ifndef ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_ 0021 #define ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_ 0022 0023 #include <atomic> 0024 0025 #include "absl/base/thread_annotations.h" 0026 #include "absl/synchronization/mutex.h" 0027 0028 namespace absl { 0029 ABSL_NAMESPACE_BEGIN 0030 0031 // BlockingCounter 0032 // 0033 // This class allows a thread to block for a pre-specified number of actions. 0034 // `BlockingCounter` maintains a single non-negative abstract integer "count" 0035 // with an initial value `initial_count`. A thread can then call `Wait()` on 0036 // this blocking counter to block until the specified number of events occur; 0037 // worker threads then call 'DecrementCount()` on the counter upon completion of 0038 // their work. Once the counter's internal "count" reaches zero, the blocked 0039 // thread unblocks. 0040 // 0041 // A `BlockingCounter` requires the following: 0042 // - its `initial_count` is non-negative. 0043 // - the number of calls to `DecrementCount()` on it is at most 0044 // `initial_count`. 0045 // - `Wait()` is called at most once on it. 0046 // 0047 // Given the above requirements, a `BlockingCounter` provides the following 0048 // guarantees: 0049 // - Once its internal "count" reaches zero, no legal action on the object 0050 // can further change the value of "count". 0051 // - When `Wait()` returns, it is legal to destroy the `BlockingCounter`. 0052 // - When `Wait()` returns, the number of calls to `DecrementCount()` on 0053 // this blocking counter exactly equals `initial_count`. 0054 // 0055 // Example: 0056 // BlockingCounter bcount(N); // there are N items of work 0057 // ... Allow worker threads to start. 0058 // ... On completing each work item, workers do: 0059 // ... bcount.DecrementCount(); // an item of work has been completed 0060 // 0061 // bcount.Wait(); // wait for all work to be complete 0062 // 0063 class BlockingCounter { 0064 public: 0065 explicit BlockingCounter(int initial_count); 0066 0067 BlockingCounter(const BlockingCounter&) = delete; 0068 BlockingCounter& operator=(const BlockingCounter&) = delete; 0069 0070 // BlockingCounter::DecrementCount() 0071 // 0072 // Decrements the counter's "count" by one, and return "count == 0". This 0073 // function requires that "count != 0" when it is called. 0074 // 0075 // Memory ordering: For any threads X and Y, any action taken by X 0076 // before it calls `DecrementCount()` is visible to thread Y after 0077 // Y's call to `DecrementCount()`, provided Y's call returns `true`. 0078 bool DecrementCount(); 0079 0080 // BlockingCounter::Wait() 0081 // 0082 // Blocks until the counter reaches zero. This function may be called at most 0083 // once. On return, `DecrementCount()` will have been called "initial_count" 0084 // times and the blocking counter may be destroyed. 0085 // 0086 // Memory ordering: For any threads X and Y, any action taken by X 0087 // before X calls `DecrementCount()` is visible to Y after Y returns 0088 // from `Wait()`. 0089 void Wait(); 0090 0091 private: 0092 Mutex lock_; 0093 std::atomic<int> count_; 0094 int num_waiting_ ABSL_GUARDED_BY(lock_); 0095 bool done_ ABSL_GUARDED_BY(lock_); 0096 }; 0097 0098 ABSL_NAMESPACE_END 0099 } // namespace absl 0100 0101 #endif // ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |