mirror of
				https://github.com/ArthurSonzogni/FTXUI.git
				synced 2025-10-31 18:48:11 +08:00 
			
		
		
		
	 d20b84f720
			
		
	
	d20b84f720
	
	
		
			
	
		
	
	
		
			Some checks are pending
		
		
	
	Build / Bazel, ${{ matrix.cxx }}, ${{ matrix.os }} (cl, cl, windows-latest) (push) Waiting to run
				
			Build / Bazel, ${{ matrix.cxx }}, ${{ matrix.os }} (clang, clang++, macos-latest) (push) Waiting to run
				
			Build / Bazel, ${{ matrix.cxx }}, ${{ matrix.os }} (clang, clang++, ubuntu-latest) (push) Waiting to run
				
			Build / Bazel, ${{ matrix.cxx }}, ${{ matrix.os }} (gcc, g++, macos-latest) (push) Waiting to run
				
			Build / Bazel, ${{ matrix.cxx }}, ${{ matrix.os }} (gcc, g++, ubuntu-latest) (push) Waiting to run
				
			Build / CMake, ${{ matrix.compiler }}, ${{ matrix.os }} (cl, Windows MSVC, windows-latest) (push) Waiting to run
				
			Build / CMake, ${{ matrix.compiler }}, ${{ matrix.os }} (gcc, Linux GCC, ubuntu-latest) (push) Waiting to run
				
			Build / CMake, ${{ matrix.compiler }}, ${{ matrix.os }} (llvm, llvm-cov gcov, Linux Clang, ubuntu-latest) (push) Waiting to run
				
			Build / CMake, ${{ matrix.compiler }}, ${{ matrix.os }} (llvm, llvm-cov gcov, MacOS clang, macos-latest) (push) Waiting to run
				
			Build / Test modules (llvm, ubuntu-latest) (push) Waiting to run
				
			Documentation / documentation (push) Waiting to run
				
			
		
			
				
	
	
		
			156 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2020 Arthur Sonzogni. All rights reserved.
 | |
| // Use of this source code is governed by the MIT license that can be found in
 | |
| // the LICENSE file.
 | |
| #ifndef FTXUI_COMPONENT_RECEIVER_HPP_
 | |
| #define FTXUI_COMPONENT_RECEIVER_HPP_
 | |
| 
 | |
| #include <ftxui/util/warn_windows_macro.hpp>
 | |
| #include <algorithm>           // for copy, max
 | |
| #include <atomic>              // for atomic, __atomic_base
 | |
| #include <condition_variable>  // for condition_variable
 | |
| #include <memory>              // for unique_ptr, make_unique
 | |
| #include <mutex>               // for mutex, unique_lock
 | |
| #include <queue>               // for queue
 | |
| #include <utility>             // for move
 | |
| 
 | |
| namespace ftxui {
 | |
| 
 | |
| // Deprecated
 | |
| //
 | |
| // Usage:
 | |
| //
 | |
| // Initialization:
 | |
| // ---------------
 | |
| //
 | |
| // auto receiver = MakeReceiver<std:string>();
 | |
| // auto sender_1= receiver->MakeSender();
 | |
| // auto sender_2 = receiver->MakeSender();
 | |
| //
 | |
| // Then move the senders elsewhere, potentially in a different thread.
 | |
| //
 | |
| // On the producer side:
 | |
| // ----------------------
 | |
| // [thread 1] sender_1->Send("hello");
 | |
| // [thread 2] sender_2->Send("world");
 | |
| //
 | |
| // On the consumer side:
 | |
| // ---------------------
 | |
| // char c;
 | |
| // while(receiver->Receive(&c)) // Return true as long as there is a producer.
 | |
| //   print(c)
 | |
| //
 | |
| // Receiver::Receive() returns true when there are no more senders.
 | |
| 
 | |
| // clang-format off
 | |
| // Deprecated:
 | |
| template<class T> class SenderImpl;
 | |
| // Deprecated:
 | |
| template<class T> class ReceiverImpl;
 | |
| // Deprecated:
 | |
| 
 | |
| // Deprecated:
 | |
| template<class T> using Sender = std::unique_ptr<SenderImpl<T>>;
 | |
| // Deprecated:
 | |
| template<class T> using Receiver = std::unique_ptr<ReceiverImpl<T>>;
 | |
| // Deprecated:
 | |
| template<class T> Receiver<T> MakeReceiver();
 | |
| // clang-format on
 | |
| 
 | |
| // ---- Implementation part ----
 | |
| 
 | |
| template <class T>
 | |
| // Deprecated:
 | |
| class SenderImpl {
 | |
|  public:
 | |
|   SenderImpl(const SenderImpl&) = delete;
 | |
|   SenderImpl(SenderImpl&&) = delete;
 | |
|   SenderImpl& operator=(const SenderImpl&) = delete;
 | |
|   SenderImpl& operator=(SenderImpl&&) = delete;
 | |
|   void Send(T t) { receiver_->Receive(std::move(t)); }
 | |
|   ~SenderImpl() { receiver_->ReleaseSender(); }
 | |
| 
 | |
|   Sender<T> Clone() { return receiver_->MakeSender(); }
 | |
| 
 | |
|  private:
 | |
|   friend class ReceiverImpl<T>;
 | |
|   explicit SenderImpl(ReceiverImpl<T>* consumer) : receiver_(consumer) {}
 | |
|   ReceiverImpl<T>* receiver_;
 | |
| };
 | |
| 
 | |
| template <class T>
 | |
| class ReceiverImpl {
 | |
|  public:
 | |
|   Sender<T> MakeSender() {
 | |
|     std::unique_lock<std::mutex> lock(mutex_);
 | |
|     senders_++;
 | |
|     return std::unique_ptr<SenderImpl<T>>(new SenderImpl<T>(this));
 | |
|   }
 | |
|   ReceiverImpl() = default;
 | |
| 
 | |
|   bool Receive(T* t) {
 | |
|     while (senders_ || !queue_.empty()) {
 | |
|       std::unique_lock<std::mutex> lock(mutex_);
 | |
|       if (queue_.empty()) {
 | |
|         notifier_.wait(lock);
 | |
|       }
 | |
|       if (queue_.empty()) {
 | |
|         continue;
 | |
|       }
 | |
|       *t = std::move(queue_.front());
 | |
|       queue_.pop();
 | |
|       return true;
 | |
|     }
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   bool ReceiveNonBlocking(T* t) {
 | |
|     std::unique_lock<std::mutex> lock(mutex_);
 | |
|     if (queue_.empty()) {
 | |
|       return false;
 | |
|     }
 | |
|     *t = queue_.front();
 | |
|     queue_.pop();
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   bool HasPending() {
 | |
|     std::unique_lock<std::mutex> lock(mutex_);
 | |
|     return !queue_.empty();
 | |
|   }
 | |
| 
 | |
|   bool HasQuitted() {
 | |
|     std::unique_lock<std::mutex> lock(mutex_);
 | |
|     return queue_.empty() && !senders_;
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   friend class SenderImpl<T>;
 | |
| 
 | |
|   void Receive(T t) {
 | |
|     {
 | |
|       std::unique_lock<std::mutex> lock(mutex_);
 | |
|       queue_.push(std::move(t));
 | |
|     }
 | |
|     notifier_.notify_one();
 | |
|   }
 | |
| 
 | |
|   void ReleaseSender() {
 | |
|     senders_--;
 | |
|     notifier_.notify_one();
 | |
|   }
 | |
| 
 | |
|   std::mutex mutex_;
 | |
|   std::queue<T> queue_;
 | |
|   std::condition_variable notifier_;
 | |
|   std::atomic<int> senders_{0};
 | |
| };
 | |
| 
 | |
| template <class T>
 | |
| Receiver<T> MakeReceiver() {
 | |
|   return std::make_unique<ReceiverImpl<T>>();
 | |
| }
 | |
| 
 | |
| }  // namespace ftxui
 | |
| 
 | |
| #endif  // FTXUI_COMPONENT_RECEIVER_HPP_
 |