Console Library 8.0.0
A header-only library that makes C++ simple
Loading...
Searching...
No Matches
channel.h
Go to the documentation of this file.
1
8
9/*
10Copyright (c) 2026 MrXie1109
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files (the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions:
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29*/
30
31#pragma once
32#include <condition_variable>
33#include <cstddef>
34#include <mutex>
35
36#include "../core/csexc.h"
37
38namespace console {
39 template <class T, size_t N>
40 class Channel;
41
47 template <class T, size_t N>
51
52 public:
54 using iterator_category = std::input_iterator_tag;
56 using value_type = T;
58 using difference_type = std::ptrdiff_t;
60 using pointer = T *;
62 using reference = T &;
63
64 explicit ChannelIterator(Channel<T, N> &channel) : channel_(channel) {}
65
72 return cache_;
73 }
74
79 T *operator->() { return &cache_; }
80
86 ChannelIterator &operator++() { return *this; }
87
93 ChannelIterator operator++(int) { return *this; }
94
100 bool operator==(const ChannelIterator &) const {
101 return !static_cast<bool>(channel_);
102 }
103
109 bool operator!=(const ChannelIterator &) const {
110 return static_cast<bool>(channel_);
111 }
112 };
113
120 template <class T, size_t N = 0>
121 class Channel {
123 size_t read_index_{0};
124 size_t write_index_{0};
125 mutable std::mutex mutex_;
126 std::condition_variable r_cv_;
127 std::condition_variable w_cv_;
128 bool closed_{false};
129
130 public:
132 Channel() = default;
133
141 bool operator<<(const T &value) {
142 std::unique_lock<std::mutex> lock(mutex_);
143 w_cv_.wait(lock,
144 [this] { return write_index_ - read_index_ < N || closed_; });
145 if (closed_) return false;
146 buffer_[write_index_ % N] = value;
147 ++write_index_;
148 r_cv_.notify_one();
149 return true;
150 }
151
159 bool operator<<(T &&value) {
160 std::unique_lock<std::mutex> lock(mutex_);
161 w_cv_.wait(lock,
162 [this] { return write_index_ - read_index_ < N || closed_; });
163 if (closed_) return false;
164 buffer_[write_index_ % N] = std::move(value);
165 ++write_index_;
166 r_cv_.notify_one();
167 return true;
168 }
169
176 bool operator<<=(const T &value) {
177 std::unique_lock<std::mutex> lock(mutex_);
178 if (closed_ || write_index_ - read_index_ >= N) return false;
179 buffer_[write_index_ % N] = value;
180 ++write_index_;
181 r_cv_.notify_one();
182 return true;
183 }
184
191 bool operator<<=(T &&value) {
192 std::unique_lock<std::mutex> lock(mutex_);
193 if (closed_ || write_index_ - read_index_ >= N) return false;
194 buffer_[write_index_ % N] = std::move(value);
195 ++write_index_;
196 r_cv_.notify_one();
197 return true;
198 }
199
207 bool operator>>(T &value) {
208 std::unique_lock<std::mutex> lock(mutex_);
209 r_cv_.wait(lock,
210 [this] { return write_index_ - read_index_ > 0 || closed_; });
211 if (closed_ && write_index_ - read_index_ == 0) return false;
212 value = std::move(buffer_[read_index_ % N]);
213 ++read_index_;
214 w_cv_.notify_one();
215 return true;
216 }
217
225 bool operator>>=(T &value) {
226 std::unique_lock<std::mutex> lock(mutex_);
227 if (write_index_ - read_index_ == 0) return false;
228 value = std::move(buffer_[read_index_ % N]);
229 ++read_index_;
230 w_cv_.notify_one();
231 return true;
232 }
233
242 std::unique_lock<std::mutex> lock(mutex_);
243 r_cv_.wait(lock,
244 [this] { return write_index_ - read_index_ > 0 || closed_; });
245 if (closed_ && write_index_ - read_index_ == 0)
246 throw AsyncError("Channel has been closed.");
247 T value = std::move(buffer_[read_index_ % N]);
248 ++read_index_;
249 w_cv_.notify_one();
250 return value;
251 }
252
260 std::unique_ptr<T> operator->() {
261 std::unique_lock<std::mutex> lock(mutex_);
262 r_cv_.wait(lock,
263 [this] { return write_index_ - read_index_ > 0 || closed_; });
264 if (closed_ && write_index_ - read_index_ == 0)
265 throw AsyncError("Channel has been closed.");
266 std::unique_ptr<T> ptr(new T(std::move(buffer_[read_index_ % N])));
267 ++read_index_;
268 w_cv_.notify_one();
269 return ptr;
270 }
271
278 explicit operator bool() const {
279 std::unique_lock<std::mutex> lock(mutex_);
280 return !closed_ || write_index_ - read_index_ > 0;
281 }
282
287 friend void close(Channel &channel) {
288 std::unique_lock<std::mutex> lock(channel.mutex_);
289 channel.closed_ = true;
290 channel.r_cv_.notify_all();
291 channel.w_cv_.notify_all();
292 }
293
296
298 iterator begin() { return iterator(*this); }
300 iterator end() { return iterator(*this); }
301
303 Channel(const Channel &) = delete;
305 Channel &operator=(const Channel &) = delete;
307 Channel(Channel &&) = delete;
309 Channel &operator=(Channel &&) = delete;
310 };
311
317 template <class T>
318 class Channel<T, 0> {
320 mutable std::mutex mutex_;
321 std::condition_variable r_cv_;
322 std::condition_variable w_cv_;
323 bool empty_ = true;
324 bool closed_ = false;
325
326 public:
328 Channel() = default;
329
337 bool operator<<(const T &value) {
338 std::unique_lock<std::mutex> lock(mutex_);
339 w_cv_.wait(lock, [this] { return empty_ || closed_; });
340 if (closed_) return false;
341 buffer_ = value;
342 empty_ = false;
343 r_cv_.notify_one();
344 return true;
345 }
346
354 bool operator<<(T &&value) {
355 std::unique_lock<std::mutex> lock(mutex_);
356 w_cv_.wait(lock, [this] { return empty_ || closed_; });
357 if (closed_) return false;
358 buffer_ = std::move(value);
359 empty_ = false;
360 r_cv_.notify_one();
361 return true;
362 }
363
371 bool operator>>(T &value) {
372 std::unique_lock<std::mutex> lock(mutex_);
373 r_cv_.wait(lock, [this] { return !empty_ || closed_; });
374 if (closed_ && empty_) return false;
375 value = std::move(buffer_);
376 empty_ = true;
377 w_cv_.notify_one();
378 return true;
379 }
380
389 std::unique_lock<std::mutex> lock(mutex_);
390 r_cv_.wait(lock, [this] { return !empty_ || closed_; });
391 if (closed_ && empty_) throw AsyncError("Channel has been closed.");
392 T value = std::move(buffer_);
393 empty_ = true;
394 w_cv_.notify_one();
395 return value;
396 }
397
405 std::unique_ptr<T> operator->() {
406 std::unique_lock<std::mutex> lock(mutex_);
407 r_cv_.wait(lock, [this] { return !empty_ || closed_; });
408 if (closed_ && empty_) throw AsyncError("Channel has been closed.");
409 std::unique_ptr<T> ptr(new T(std::move(buffer_)));
410 empty_ = true;
411 w_cv_.notify_one();
412 return ptr;
413 }
414
421 explicit operator bool() const {
422 std::unique_lock<std::mutex> lock(mutex_);
423 return !closed_ || !empty_;
424 }
425
430 friend void close(Channel &channel) {
431 std::unique_lock<std::mutex> lock(channel.mutex_);
432 channel.closed_ = true;
433 channel.r_cv_.notify_all();
434 channel.w_cv_.notify_all();
435 }
436
439
441 iterator begin() { return iterator(*this); }
443 iterator end() { return iterator(*this); }
444
446 Channel(const Channel &) = delete;
448 Channel &operator=(const Channel &) = delete;
450 Channel(Channel &&) = delete;
452 Channel &operator=(Channel &&) = delete;
453 };
454
464 template <class T, size_t N, class F>
465 inline F for_each(Channel<T, N> &channel, F &&func) {
466 T value;
467 while (channel >> value) func(value);
468 return std::forward<F>(func);
469 }
470}
AsyncError(const std::string &msg)
构造 ConsoleError。
Definition csexc.h:193
Channel(const Channel &)=delete
删除复制构造函数。
bool operator<<(T &&value)
向通道写入数据。
Definition channel.h:354
bool closed_
关闭标志
Definition channel.h:324
iterator end()
迭代器的 end 函数。
Definition channel.h:443
bool operator<<(const T &value)
向通道写入数据。
Definition channel.h:337
T operator*()
从通道读取数据。
Definition channel.h:388
std::condition_variable w_cv_
写 条件变量
Definition channel.h:322
bool empty_
缓冲区是否为空
Definition channel.h:323
Channel & operator=(Channel &&)=delete
删除移动赋值函数。
std::unique_ptr< T > operator->()
从通道读取数据。
Definition channel.h:405
std::mutex mutex_
互斥锁
Definition channel.h:320
std::condition_variable r_cv_
读 条件变量
Definition channel.h:321
Channel()=default
默认构造函数。
iterator begin()
迭代器的 begin 函数。
Definition channel.h:441
Channel(Channel &&)=delete
删除移动构造函数。
bool operator>>(T &value)
从通道读取数据。
Definition channel.h:371
T buffer_
缓冲区
Definition channel.h:319
Channel & operator=(const Channel &)=delete
删除复制赋值函数。
friend void close(Channel &channel)
关闭通道。
Definition channel.h:430
ChannelIterator< T, 0 > iterator
迭代器类型。
Definition channel.h:438
环形缓冲区通道,用于线程间通信。
Definition channel.h:121
std::condition_variable r_cv_
读 条件变量
Definition channel.h:126
std::unique_ptr< T > operator->()
从通道读取数据。
Definition channel.h:260
bool operator<<(T &&value)
向通道写入数据。
Definition channel.h:159
bool operator<<(const T &value)
向通道写入数据。
Definition channel.h:141
Channel & operator=(const Channel &)=delete
删除复制赋值函数。
std::mutex mutex_
互斥锁
Definition channel.h:125
size_t read_index_
读索引
Definition channel.h:123
std::condition_variable w_cv_
写 条件变量
Definition channel.h:127
iterator end()
迭代器的 end 函数。
Definition channel.h:300
bool operator>>(T &value)
从通道读取数据。
Definition channel.h:207
size_t write_index_
写索引
Definition channel.h:124
ChannelIterator< T, N > iterator
迭代器类型。
Definition channel.h:295
bool operator<<=(const T &value)
尝试向通道写入数据。
Definition channel.h:176
bool operator>>=(T &value)
从通道尝试读取数据(非阻塞)。
Definition channel.h:225
iterator begin()
迭代器的 begin 函数。
Definition channel.h:298
Channel & operator=(Channel &&)=delete
删除移动赋值函数。
bool closed_
关闭标志
Definition channel.h:128
Channel(Channel &&)=delete
删除移动构造函数。
Channel()=default
默认构造函数。
T buffer_[N]
缓冲区
Definition channel.h:122
friend void close(Channel &channel)
关闭通道。
Definition channel.h:287
T operator*()
从通道读取数据。
Definition channel.h:241
bool operator<<=(T &&value)
尝试向通道写入数据。
Definition channel.h:191
Channel(const Channel &)=delete
删除复制构造函数。
通道迭代器。
Definition channel.h:48
T value_type
值类型。
Definition channel.h:56
ChannelIterator operator++(int)
后置递增。
Definition channel.h:93
T & reference
引用类型。
Definition channel.h:62
std::ptrdiff_t difference_type
差异类型。
Definition channel.h:58
std::input_iterator_tag iterator_category
迭代器类别。
Definition channel.h:54
T & operator*()
解引用查询。
Definition channel.h:70
bool operator!=(const ChannelIterator &) const
比较不等。
Definition channel.h:109
T * operator->()
成员访问查询。
Definition channel.h:79
ChannelIterator & operator++()
前置递增。
Definition channel.h:86
bool operator==(const ChannelIterator &) const
比较相等。
Definition channel.h:100
T * pointer
指针类型。
Definition channel.h:60
ChannelIterator(Channel< T, N > &channel)
Definition channel.h:64
T cache_
Definition channel.h:50
Channel< T, N > & channel_
Definition channel.h:49
定义 console 库使用的自定义异常类层次结构。
本库所有组件所在的顶层命名空间。
@ N
Definition kb.h:93
@ T
Definition kb.h:99
F for_each(Channel< T, N > &channel, F &&func)
遍历通道中的所有元素。
Definition channel.h:465