FTXUI 6.1.9
C++ functional terminal UI.
载入中...
搜索中...
未找到
receiver.hpp
浏览该文件的文档.
1// Copyright 2020 Arthur Sonzogni. All rights reserved.
2// 本源代码的使用受 MIT 许可协议的约束,该协议可在 LICENSE 文件中找到。
3#ifndef FTXUI_COMPONENT_RECEIVER_HPP_
4#define FTXUI_COMPONENT_RECEIVER_HPP_
5
6#include <algorithm> // for copy, max
7#include <atomic> // for atomic, __atomic_base
8#include <condition_variable> // for condition_variable
10#include <memory> // for unique_ptr, make_unique
11#include <mutex> // for mutex, unique_lock
12#include <queue> // for queue
13#include <utility> // for move
14
15namespace ftxui {
16
17// 已弃用
18//
19// 用法:
20//
21// 初始化:
22// ---------------
23//
24// auto receiver = MakeReceiver<std:string>();
25// auto sender_1= receiver->MakeSender();
26// auto sender_2 = receiver->MakeSender();
27//
28// 然后将发送器移到其他地方,可能在不同的线程中。
29//
30// 在生产者侧:
31// ----------------------
32// [thread 1] sender_1->Send("hello");
33// [thread 2] sender_2->Send("world");
34//
35// 在消费者侧:
36// ---------------------
37// char c;
38// while(receiver->Receive(&c)) // 只要有生产者存在,就返回 true。
39// print(c)
40//
41// 当没有更多发送器时,Receiver::Receive() 返回 true。
42
43// clang-format off
44// 已弃用:
45template<class T> class SenderImpl;
46// 已弃用:
47template<class T> class ReceiverImpl;
48// 已弃用:
49
50// 已弃用:
51template<class T> using Sender = std::unique_ptr<SenderImpl<T>>;
52// 已弃用:
53template<class T> using Receiver = std::unique_ptr<ReceiverImpl<T>>;
54// 已弃用:
55template<class T> Receiver<T> MakeReceiver();
56// clang-format on
57
58// ---- Implementation part ----
59
60template <class T>
61// 已弃用:
63 public:
64 SenderImpl(const SenderImpl&) = delete;
66 SenderImpl& operator=(const SenderImpl&) = delete;
68 void Send(T t) { receiver_->Receive(std::move(t)); }
69 ~SenderImpl() { receiver_->ReleaseSender(); }
70
71 Sender<T> Clone() { return receiver_->MakeSender(); }
72
73 private:
74 friend class ReceiverImpl<T>;
75 explicit SenderImpl(ReceiverImpl<T>* consumer) : receiver_(consumer) {}
76 ReceiverImpl<T>* receiver_;
77};
78
79template <class T>
81 public:
83 std::unique_lock<std::mutex> lock(mutex_);
84 senders_++;
85 return std::unique_ptr<SenderImpl<T>>(new SenderImpl<T>(this));
86 }
87 ReceiverImpl() = default;
88
89 bool Receive(T* t) {
90 while (senders_ || !queue_.empty()) {
91 std::unique_lock<std::mutex> lock(mutex_);
92 if (queue_.empty()) {
93 notifier_.wait(lock);
94 }
95 if (queue_.empty()) {
96 continue;
97 }
98 *t = std::move(queue_.front());
99 queue_.pop();
100 return true;
101 }
102 return false;
103 }
104
106 std::unique_lock<std::mutex> lock(mutex_);
107 if (queue_.empty()) {
108 return false;
109 }
110 *t = queue_.front();
111 queue_.pop();
112 return true;
113 }
114
115 bool HasPending() {
116 std::unique_lock<std::mutex> lock(mutex_);
117 return !queue_.empty();
118 }
119
120 bool HasQuitted() {
121 std::unique_lock<std::mutex> lock(mutex_);
122 return queue_.empty() && !senders_;
123 }
124
125 private:
126 friend class SenderImpl<T>;
127
128 void Receive(T t) {
129 {
130 std::unique_lock<std::mutex> lock(mutex_);
131 queue_.push(std::move(t));
132 }
133 notifier_.notify_one();
134 }
135
136 void ReleaseSender() {
137 senders_--;
138 notifier_.notify_one();
139 }
140
141 std::mutex mutex_;
142 std::queue<T> queue_;
143 std::condition_variable notifier_;
144 std::atomic<int> senders_{0};
145};
146
147template <class T>
149 return std::make_unique<ReceiverImpl<T>>();
150}
151
152} // namespace ftxui
153
154#endif // FTXUI_COMPONENT_RECEIVER_HPP_
ReceiverImpl()=default
friend class SenderImpl< T >
Sender< T > MakeSender()
friend class ReceiverImpl< T >
SenderImpl & operator=(const SenderImpl &)=delete
Sender< T > Clone()
SenderImpl(SenderImpl &&)=delete
SenderImpl(const SenderImpl &)=delete
SenderImpl & operator=(SenderImpl &&)=delete
#include "ftxui/component/component_base.hpp" // 用于 ComponentBase
Receiver< T > MakeReceiver()
std::unique_ptr< ReceiverImpl< T > > Receiver
std::unique_ptr< SenderImpl< T > > Sender