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