FTXUI 6.1.9
C++ functional terminal UI.
Loading...
Searching...
No Matches
receiver.hpp
Go to the documentation of this file.
1// Copyright 2020 Arthur Sonzogni. All rights reserved.
2// Use of this source code is governed by the MIT license that can be found in
3// the LICENSE file.
4#ifndef FTXUI_COMPONENT_RECEIVER_HPP_
5#define FTXUI_COMPONENT_RECEIVER_HPP_
6
7#include <algorithm> // for copy, max
8#include <atomic> // for atomic, __atomic_base
9#include <condition_variable> // for condition_variable
11#include <memory> // for unique_ptr, make_unique
12#include <mutex> // for mutex, unique_lock
13#include <queue> // for queue
14#include <utility> // for move
15
16namespace ftxui {
17
18// Deprecated
19//
20// Usage:
21//
22// Initialization:
23// ---------------
24//
25// auto receiver = MakeReceiver<std:string>();
26// auto sender_1= receiver->MakeSender();
27// auto sender_2 = receiver->MakeSender();
28//
29// Then move the senders elsewhere, potentially in a different thread.
30//
31// On the producer side:
32// ----------------------
33// [thread 1] sender_1->Send("hello");
34// [thread 2] sender_2->Send("world");
35//
36// On the consumer side:
37// ---------------------
38// char c;
39// while(receiver->Receive(&c)) // Return true as long as there is a producer.
40// print(c)
41//
42// Receiver::Receive() returns true when there are no more senders.
43
44// clang-format off
45// Deprecated:
46template<class T> class SenderImpl;
47// Deprecated:
48template<class T> class ReceiverImpl;
49// Deprecated:
50
51// Deprecated:
52template<class T> using Sender = std::unique_ptr<SenderImpl<T>>;
53// Deprecated:
54template<class T> using Receiver = std::unique_ptr<ReceiverImpl<T>>;
55// Deprecated:
56template<class T> Receiver<T> MakeReceiver();
57// clang-format on
58
59// ---- Implementation part ----
60
61template <class T>
62// Deprecated:
64 public:
65 SenderImpl(const SenderImpl&) = delete;
67 SenderImpl& operator=(const SenderImpl&) = delete;
69 void Send(T t) { receiver_->Receive(std::move(t)); }
70 ~SenderImpl() { receiver_->ReleaseSender(); }
71
72 Sender<T> Clone() { return receiver_->MakeSender(); }
73
74 private:
75 friend class ReceiverImpl<T>;
76 explicit SenderImpl(ReceiverImpl<T>* consumer) : receiver_(consumer) {}
77 ReceiverImpl<T>* receiver_;
78};
79
80template <class T>
82 public:
84 std::unique_lock<std::mutex> lock(mutex_);
85 senders_++;
86 return std::unique_ptr<SenderImpl<T>>(new SenderImpl<T>(this));
87 }
88 ReceiverImpl() = default;
89
90 bool Receive(T* t) {
91 while (senders_ || !queue_.empty()) {
92 std::unique_lock<std::mutex> lock(mutex_);
93 if (queue_.empty()) {
94 notifier_.wait(lock);
95 }
96 if (queue_.empty()) {
97 continue;
98 }
99 *t = std::move(queue_.front());
100 queue_.pop();
101 return true;
102 }
103 return false;
104 }
105
107 std::unique_lock<std::mutex> lock(mutex_);
108 if (queue_.empty()) {
109 return false;
110 }
111 *t = queue_.front();
112 queue_.pop();
113 return true;
114 }
115
116 bool HasPending() {
117 std::unique_lock<std::mutex> lock(mutex_);
118 return !queue_.empty();
119 }
120
121 bool HasQuitted() {
122 std::unique_lock<std::mutex> lock(mutex_);
123 return queue_.empty() && !senders_;
124 }
125
126 private:
127 friend class SenderImpl<T>;
128
129 void Receive(T t) {
130 {
131 std::unique_lock<std::mutex> lock(mutex_);
132 queue_.push(std::move(t));
133 }
134 notifier_.notify_one();
135 }
136
137 void ReleaseSender() {
138 senders_--;
139 notifier_.notify_one();
140 }
141
142 std::mutex mutex_;
143 std::queue<T> queue_;
144 std::condition_variable notifier_;
145 std::atomic<int> senders_{0};
146};
147
148template <class T>
150 return std::make_unique<ReceiverImpl<T>>();
151}
152
153} // namespace ftxui
154
155#endif // FTXUI_COMPONENT_RECEIVER_HPP_
ReceiverImpl()=default
bool Receive(T *t)
Definition receiver.hpp:90
bool ReceiveNonBlocking(T *t)
Definition receiver.hpp:106
friend class SenderImpl< T >
Definition receiver.hpp:127
Sender< T > MakeSender()
Definition receiver.hpp:83
friend class ReceiverImpl< T >
Definition receiver.hpp:75
SenderImpl & operator=(const SenderImpl &)=delete
Sender< T > Clone()
Definition receiver.hpp:72
SenderImpl(SenderImpl &&)=delete
SenderImpl(const SenderImpl &)=delete
SenderImpl & operator=(SenderImpl &&)=delete
The FTXUI ftxui:: namespace.
Definition animation.hpp:10
Receiver< T > MakeReceiver()
Definition receiver.hpp:149
std::unique_ptr< ReceiverImpl< T > > Receiver
Definition receiver.hpp:54
std::unique_ptr< SenderImpl< T > > Sender
Definition receiver.hpp:52