/root/doris/be/src/util/countdown_latch.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #pragma once |
19 | | |
20 | | // IWYU pragma: no_include <bits/chrono.h> |
21 | | #include <chrono> |
22 | | #include <condition_variable> |
23 | | #include <mutex> |
24 | | |
25 | | #include "common/logging.h" |
26 | | #include "olap/olap_define.h" |
27 | | |
28 | | namespace doris { |
29 | | |
30 | | // This is a C++ implementation of the Java CountDownLatch |
31 | | // class. |
32 | | // See http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html |
33 | | class CountDownLatch { |
34 | | public: |
35 | | // Initialize the latch with the given initial count. |
36 | 3.12k | explicit CountDownLatch(int count) : _count(count) {} |
37 | | |
38 | | // Decrement the count of this latch by 'amount' |
39 | | // If the new count is less than or equal to zero, then all waiting threads are woken up. |
40 | | // If the count is already zero, this has no effect. |
41 | 3.11k | void count_down(int amount) { |
42 | 3.11k | DCHECK_GE(amount, 0); |
43 | 3.11k | std::lock_guard<std::mutex> lock(_lock); |
44 | 3.11k | if (_count == 0) { |
45 | 2 | return; |
46 | 2 | } |
47 | | |
48 | 3.11k | if (amount >= _count) { |
49 | 3.10k | _count = 0; |
50 | 3.10k | } else { |
51 | 1 | _count -= amount; |
52 | 1 | } |
53 | | |
54 | 3.11k | if (_count == 0) { |
55 | | // Latch has triggered. |
56 | 3.10k | _cond.notify_all(); |
57 | 3.10k | } |
58 | 3.11k | } |
59 | | |
60 | | // Decrement the count of this latch. |
61 | | // If the new count is zero, then all waiting threads are woken up. |
62 | | // If the count is already zero, this has no effect. |
63 | 3.11k | void count_down() { count_down(1); } |
64 | | |
65 | | // Wait until the count on the latch reaches zero. |
66 | | // If the count is already zero, this returns immediately. |
67 | 567 | void wait() { |
68 | 567 | std::unique_lock<std::mutex> lock(_lock); |
69 | 1.10k | while (_count > 0) { |
70 | 533 | _cond.wait(lock); |
71 | 533 | } |
72 | 567 | } |
73 | | |
74 | | // Waits for the count on the latch to reach zero, or until 'delta' time elapses. |
75 | | // Returns true if the count became zero, false otherwise. |
76 | | template <class Rep, class Period> |
77 | 1.03k | bool wait_for(const std::chrono::duration<Rep, Period>& delta) { |
78 | 1.03k | std::unique_lock lock(_lock); |
79 | 1.06k | return _cond.wait_for(lock, delta, [&]() { return _count <= 0; }); _ZZN5doris14CountDownLatch8wait_forIlSt5ratioILl1ELl1000EEEEbRKNSt6chrono8durationIT_T0_EEENKUlvE_clEv Line | Count | Source | 79 | 1.05k | return _cond.wait_for(lock, delta, [&]() { return _count <= 0; }); |
_ZZN5doris14CountDownLatch8wait_forIlSt5ratioILl1ELl1EEEEbRKNSt6chrono8durationIT_T0_EEENKUlvE_clEv Line | Count | Source | 79 | 12 | return _cond.wait_for(lock, delta, [&]() { return _count <= 0; }); |
|
80 | 1.03k | } _ZN5doris14CountDownLatch8wait_forIlSt5ratioILl1ELl1000EEEEbRKNSt6chrono8durationIT_T0_EE Line | Count | Source | 77 | 1.02k | bool wait_for(const std::chrono::duration<Rep, Period>& delta) { | 78 | 1.02k | std::unique_lock lock(_lock); | 79 | 1.02k | return _cond.wait_for(lock, delta, [&]() { return _count <= 0; }); | 80 | 1.02k | } |
_ZN5doris14CountDownLatch8wait_forIlSt5ratioILl1ELl1EEEEbRKNSt6chrono8durationIT_T0_EE Line | Count | Source | 77 | 6 | bool wait_for(const std::chrono::duration<Rep, Period>& delta) { | 78 | 6 | std::unique_lock lock(_lock); | 79 | 6 | return _cond.wait_for(lock, delta, [&]() { return _count <= 0; }); | 80 | 6 | } |
|
81 | | |
82 | | // Reset the latch with the given count. This is equivalent to reconstructing |
83 | | // the latch. If 'count' is 0, and there are currently waiters, those waiters |
84 | | // will be triggered as if you counted down to 0. |
85 | 1 | void reset(uint64_t count) { |
86 | 1 | std::lock_guard<std::mutex> lock(_lock); |
87 | 1 | _count = count; |
88 | 1 | if (_count == 0) { |
89 | | // Awake any waiters if we reset to 0. |
90 | 1 | _cond.notify_all(); |
91 | 1 | } |
92 | 1 | } |
93 | | |
94 | 9.94k | uint64_t count() const { |
95 | 9.94k | std::lock_guard<std::mutex> lock(_lock); |
96 | 9.94k | return _count; |
97 | 9.94k | } |
98 | | |
99 | | private: |
100 | | mutable std::mutex _lock; |
101 | | mutable std::condition_variable _cond; |
102 | | |
103 | | uint64_t _count; |
104 | | |
105 | | CountDownLatch(const CountDownLatch&) = delete; |
106 | | void operator=(const CountDownLatch&) = delete; |
107 | | }; |
108 | | |
109 | | // Utility class which calls latch->CountDown() in its destructor. |
110 | | class CountDownOnScopeExit { |
111 | | public: |
112 | 0 | explicit CountDownOnScopeExit(CountDownLatch* latch) : _latch(latch) {} |
113 | 0 | ~CountDownOnScopeExit() { _latch->count_down(); } |
114 | | |
115 | | private: |
116 | | CountDownLatch* _latch = nullptr; |
117 | | |
118 | | CountDownOnScopeExit(const CountDownOnScopeExit&) = delete; |
119 | | void operator=(const CountDownOnScopeExit&) = delete; |
120 | | }; |
121 | | |
122 | | } // namespace doris |