1 | // Copyright 2019 Google LLC |
---|---|
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 | #ifndef dap_chan_h |
16 | #define dap_chan_h |
17 | |
18 | #include "dap/optional.h" |
19 | |
20 | #include <condition_variable> |
21 | #include <mutex> |
22 | #include <queue> |
23 | |
24 | namespace dap { |
25 | |
26 | template <typename T> |
27 | struct Chan { |
28 | public: |
29 | void reset(); |
30 | void close(); |
31 | optional<T> take(); |
32 | void put(T&& in); |
33 | void put(const T& in); |
34 | |
35 | private: |
36 | bool closed = false; |
37 | std::queue<T> queue; |
38 | std::condition_variable cv; |
39 | std::mutex mutex; |
40 | }; |
41 | |
42 | template <typename T> |
43 | void Chan<T>::reset() { |
44 | std::unique_lock<std::mutex> lock(mutex); |
45 | queue = {}; |
46 | closed = false; |
47 | } |
48 | |
49 | template <typename T> |
50 | void Chan<T>::close() { |
51 | std::unique_lock<std::mutex> lock(mutex); |
52 | closed = true; |
53 | cv.notify_all(); |
54 | } |
55 | |
56 | template <typename T> |
57 | optional<T> Chan<T>::take() { |
58 | std::unique_lock<std::mutex> lock(mutex); |
59 | cv.wait(lock, [&] { return queue.size() > 0 || closed; }); |
60 | if (queue.size() == 0) { |
61 | return optional<T>(); |
62 | } |
63 | auto out = std::move(queue.front()); |
64 | queue.pop(); |
65 | return optional<T>(std::move(out)); |
66 | } |
67 | |
68 | template <typename T> |
69 | void Chan<T>::put(T&& in) { |
70 | std::unique_lock<std::mutex> lock(mutex); |
71 | auto notify = queue.size() == 0 && !closed; |
72 | queue.push(std::move(in)); |
73 | if (notify) { |
74 | cv.notify_all(); |
75 | } |
76 | } |
77 | |
78 | template <typename T> |
79 | void Chan<T>::put(const T& in) { |
80 | std::unique_lock<std::mutex> lock(mutex); |
81 | auto notify = queue.size() == 0 && !closed; |
82 | queue.push(in); |
83 | if (notify) { |
84 | cv.notify_all(); |
85 | } |
86 | } |
87 | |
88 | } // namespace dap |
89 | |
90 | #endif // dap_chan_h |
91 |