FTXUI
6.1.9
C++ functional terminal UI.
Toggle main menu visibility
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
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
15
namespace
ftxui
{
16
17
// Usage:
18
//
19
// Initialization:
20
// ---------------
21
//
22
// auto receiver = MakeReceiver<std:string>();
23
// auto sender_1= receiver->MakeSender();
24
// auto sender_2 = receiver->MakeSender();
25
//
26
// Then move the senders elsewhere, potentially in a different thread.
27
//
28
// On the producer side:
29
// ----------------------
30
// [thread 1] sender_1->Send("hello");
31
// [thread 2] sender_2->Send("world");
32
//
33
// On the consumer side:
34
// ---------------------
35
// char c;
36
// while(receiver->Receive(&c)) // Return true as long as there is a producer.
37
// print(c)
38
//
39
// Receiver::Receive() returns true when there are no more senders.
40
41
// clang-format off
42
template
<
class
T>
class
SenderImpl
;
43
template
<
class
T>
class
ReceiverImpl
;
44
45
template
<
class
T>
using
Sender
= std::unique_ptr<SenderImpl<T>>;
46
template
<
class
T>
using
Receiver
= std::unique_ptr<ReceiverImpl<T>>;
47
template
<
class
T>
Receiver<T>
MakeReceiver
();
48
// clang-format on
49
50
// ---- Implementation part ----
51
52
template
<
class
T>
53
class
SenderImpl
{
54
public
:
55
SenderImpl
(
const
SenderImpl
&) =
delete
;
56
SenderImpl
(
SenderImpl
&&) =
delete
;
57
SenderImpl
&
operator=
(
const
SenderImpl
&) =
delete
;
58
SenderImpl
&
operator=
(
SenderImpl
&&) =
delete
;
59
void
Send
(T t) { receiver_->Receive(std::move(t)); }
60
~SenderImpl
() { receiver_->ReleaseSender(); }
61
62
Sender<T>
Clone
() {
return
receiver_->MakeSender(); }
63
64
private
:
65
friend
class
ReceiverImpl
<T>;
66
explicit
SenderImpl
(
ReceiverImpl<T>
* consumer) : receiver_(consumer) {}
67
ReceiverImpl<T>
* receiver_;
68
};
69
70
template
<
class
T>
71
class
ReceiverImpl
{
72
public
:
73
Sender<T>
MakeSender
() {
74
std::unique_lock<std::mutex> lock(mutex_);
75
senders_++;
76
return
std::unique_ptr<SenderImpl<T>>(
new
SenderImpl<T>
(
this
));
77
}
78
ReceiverImpl
() =
default
;
79
80
bool
Receive
(T* t) {
81
while
(senders_ || !queue_.empty()) {
82
std::unique_lock<std::mutex> lock(mutex_);
83
if
(queue_.empty()) {
84
notifier_.wait(lock);
85
}
86
if
(queue_.empty()) {
87
continue
;
88
}
89
*t = std::move(queue_.front());
90
queue_.pop();
91
return
true
;
92
}
93
return
false
;
94
}
95
96
bool
ReceiveNonBlocking
(T* t) {
97
std::unique_lock<std::mutex> lock(mutex_);
98
if
(queue_.empty()) {
99
return
false
;
100
}
101
*t = queue_.front();
102
queue_.pop();
103
return
true
;
104
}
105
106
bool
HasPending
() {
107
std::unique_lock<std::mutex> lock(mutex_);
108
return
!queue_.empty();
109
}
110
111
bool
HasQuitted
() {
112
std::unique_lock<std::mutex> lock(mutex_);
113
return
queue_.empty() && !senders_;
114
}
115
116
private
:
117
friend
class
SenderImpl
<T>;
118
119
void
Receive
(T t) {
120
{
121
std::unique_lock<std::mutex> lock(mutex_);
122
queue_.push(std::move(t));
123
}
124
notifier_.notify_one();
125
}
126
127
void
ReleaseSender() {
128
senders_--;
129
notifier_.notify_one();
130
}
131
132
std::mutex mutex_;
133
std::queue<T> queue_;
134
std::condition_variable notifier_;
135
std::atomic<int> senders_{0};
136
};
137
138
template
<
class
T>
139
Receiver<T>
MakeReceiver
() {
140
return
std::make_unique<ReceiverImpl<T>>();
141
}
142
143
}
// namespace ftxui
144
145
#endif
// FTXUI_COMPONENT_RECEIVER_HPP_
ftxui::ReceiverImpl
Definition
receiver.hpp:71
ftxui::ReceiverImpl::ReceiverImpl
ReceiverImpl()=default
ftxui::ReceiverImpl::HasQuitted
bool HasQuitted()
Definition
receiver.hpp:111
ftxui::ReceiverImpl::Receive
bool Receive(T *t)
Definition
receiver.hpp:80
ftxui::ReceiverImpl::ReceiveNonBlocking
bool ReceiveNonBlocking(T *t)
Definition
receiver.hpp:96
ftxui::ReceiverImpl::HasPending
bool HasPending()
Definition
receiver.hpp:106
ftxui::ReceiverImpl::SenderImpl< T >
friend class SenderImpl< T >
Definition
receiver.hpp:117
ftxui::ReceiverImpl::MakeSender
Sender< T > MakeSender()
Definition
receiver.hpp:73
ftxui::SenderImpl
Definition
receiver.hpp:53
ftxui::SenderImpl::ReceiverImpl< T >
friend class ReceiverImpl< T >
Definition
receiver.hpp:65
ftxui::SenderImpl::operator=
SenderImpl & operator=(const SenderImpl &)=delete
ftxui::SenderImpl::Clone
Sender< T > Clone()
Definition
receiver.hpp:62
ftxui::SenderImpl::SenderImpl
SenderImpl(SenderImpl &&)=delete
ftxui::SenderImpl::SenderImpl
SenderImpl(const SenderImpl &)=delete
ftxui::SenderImpl::~SenderImpl
~SenderImpl()
Definition
receiver.hpp:60
ftxui::SenderImpl::operator=
SenderImpl & operator=(SenderImpl &&)=delete
ftxui::SenderImpl::Send
void Send(T t)
Definition
receiver.hpp:59
ftxui
Definition
animation.hpp:10
ftxui::MakeReceiver
Receiver< T > MakeReceiver()
Definition
receiver.hpp:139
ftxui::Receiver
std::unique_ptr< ReceiverImpl< T > > Receiver
Definition
receiver.hpp:46
ftxui::Sender
std::unique_ptr< SenderImpl< T > > Sender
Definition
receiver.hpp:45