FTXUI  0.8.1
C++ functional terminal UI.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
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 
14 namespace 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
41 template<class T> class SenderImpl;
42 template<class T> class ReceiverImpl;
43 
44 template<class T> using Sender = std::unique_ptr<SenderImpl<T>>;
45 template<class T> using Receiver = std::unique_ptr<ReceiverImpl<T>>;
46 template<class T> Receiver<T> MakeReceiver();
47 // clang-format on
48 
49 // ---- Implementation part ----
50 
51 template <class T>
52 class SenderImpl {
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 
65 template <class T>
66 class ReceiverImpl {
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 
116 template <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.
ftxui::Receiver
std::unique_ptr< ReceiverImpl< T > > Receiver
Definition: receiver.hpp:45
ftxui::SenderImpl
Definition: receiver.hpp:41
ftxui::SenderImpl::Clone
Sender< T > Clone()
Definition: receiver.hpp:57
ftxui
Definition: captured_mouse.hpp:6
ftxui::ReceiverImpl::ReceiverImpl
ReceiverImpl()
Definition: receiver.hpp:73
ftxui::ReceiverImpl::Receive
bool Receive(T *t)
Definition: receiver.hpp:75
ftxui::ReceiverImpl::MakeSender
Sender< T > MakeSender()
Definition: receiver.hpp:68
ftxui::SenderImpl::~SenderImpl
~SenderImpl()
Definition: receiver.hpp:55
ftxui::MakeReceiver
Receiver< T > MakeReceiver()
Definition: receiver.hpp:117
ftxui::Sender
std::unique_ptr< SenderImpl< T > > Sender
Definition: receiver.hpp:44
ftxui::ReceiverImpl::HasPending
bool HasPending()
Definition: receiver.hpp:89
ftxui::ReceiverImpl::SenderImpl< T >
friend class SenderImpl< T >
Definition: receiver.hpp:95
ftxui::ReceiverImpl
Definition: receiver.hpp:42
ftxui::SenderImpl::Send
void Send(T t)
Definition: receiver.hpp:54