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
24namespace dap {
25
26template <typename T>
27struct 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
42template <typename T>
43void Chan<T>::reset() {
44 std::unique_lock<std::mutex> lock(mutex);
45 queue = {};
46 closed = false;
47}
48
49template <typename T>
50void Chan<T>::close() {
51 std::unique_lock<std::mutex> lock(mutex);
52 closed = true;
53 cv.notify_all();
54}
55
56template <typename T>
57optional<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
68template <typename T>
69void 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
78template <typename T>
79void 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