receiver.hpp
algorithm
atomic
condition_variable
memory
mutex
queue
utility
include/ftxui/component/screen_interactive.hpp
src/ftxui/component/screen_interactive.cpp
src/ftxui/component/terminal_input_parser.cpp
src/ftxui/component/terminal_input_parser.hpp
include/ftxui/component/receiver.hpp
algorithm
atomic
condition_variable
memory
mutex
queue
utility
include/ftxui/component/receiver.hpp
include/ftxui/component/screen_interactive.hpp
src/ftxui/component/button.cpp
src/ftxui/component/component.cpp
src/ftxui/component/component_fuzzer.cpp
src/ftxui/component/hoverable.cpp
src/ftxui/component/input.cpp
src/ftxui/component/loop.cpp
src/ftxui/component/menu.cpp
src/ftxui/component/radiobox.cpp
src/ftxui/component/screen_interactive.cpp
src/ftxui/component/slider.cpp
src/ftxui/component/terminal_input_parser.cpp
src/ftxui/component/terminal_input_parser.hpp
src/ftxui/component/terminal_input_parser_test_fuzzer.cpp
src/ftxui/component/window.cpp
ftxui::SenderImpl
ftxui::ReceiverImpl
ftxui

    //Copyright2020ArthurSonzogni.Allrightsreserved.
    //UseofthissourcecodeisgovernedbytheMITlicensethatcanbefoundin
    //theLICENSEfile.
    #ifndefFTXUI_COMPONENT_RECEIVER_HPP_
    #defineFTXUI_COMPONENT_RECEIVER_HPP_

    #include<algorithm>//forcopy,max
    #include<atomic>//foratomic,__atomic_base
    #include<condition_variable>//forcondition_variable
    #include<memory>//forunique_ptr,make_unique
    #include<mutex>//formutex,unique_lock
    #include<queue>//forqueue
    #include<utility>//formove

    namespaceftxui{

    //Usage:
    //
    //Initialization:
    //---------------
    //
    //autoreceiver=MakeReceiver<std:string>();
    //autosender_1=receiver->MakeSender();
    //autosender_2=receiver->MakeSender();
    //
    //Thenmovethesenderselsewhere,potentiallyinadifferentthread.
    //
    //Ontheproducerside:
    //----------------------
    //[thread1]sender_1->Send("hello");
    //[thread2]sender_2->Send("world");
    //
    //Ontheconsumerside:
    //---------------------
    //charc;
    //while(receiver->Receive(&c))//Returntrueaslongasthereisaproducer.
    //print(c)
    //
    //Receiver::Receive()returnstruewhentherearenomoresenders.

    //clang-formatoff
    template<classT>classSenderImpl;
    template<classT>classReceiverImpl;

    template<classT>usingSender=std::unique_ptr<SenderImpl<T>>;
    template<classT>usingReceiver=std::unique_ptr<ReceiverImpl<T>>;
    template<classT>Receiver<T>MakeReceiver();
    //clang-formaton

    //----Implementationpart----

    template<classT>
    classSenderImpl{
    public:
    SenderImpl(constSenderImpl&)=delete;
    SenderImpl(SenderImpl&&)=delete;
    SenderImpl&operator=(constSenderImpl&)=delete;
    SenderImpl&operator=(SenderImpl&&)=delete;
    voidSend(Tt){receiver_->Receive(std::move(t));}
    ~SenderImpl(){receiver_->ReleaseSender();}

    Sender<T>Clone(){returnreceiver_->MakeSender();}

    private:
    friendclassReceiverImpl<T>;
    explicitSenderImpl(ReceiverImpl<T>*consumer):receiver_(consumer){}
    ReceiverImpl<T>*receiver_;
    };

    template<classT>
    classReceiverImpl{
    public:
    Sender<T>MakeSender(){
    std::unique_lock<std::mutex>lock(mutex_);
    senders_++;
    returnstd::unique_ptr<SenderImpl<T>>(newSenderImpl<T>(this));
    }
    ReceiverImpl()=default;

    boolReceive(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();
    returntrue;
    }
    returnfalse;
    }

    boolReceiveNonBlocking(T*t){
    std::unique_lock<std::mutex>lock(mutex_);
    if(queue_.empty()){
    returnfalse;
    }
    *t=queue_.front();
    queue_.pop();
    returntrue;
    }

    boolHasPending(){
    std::unique_lock<std::mutex>lock(mutex_);
    return!queue_.empty();
    }

    boolHasQuitted(){
    std::unique_lock<std::mutex>lock(mutex_);
    returnqueue_.empty()&&!senders_;
    }

    private:
    friendclassSenderImpl<T>;

    voidReceive(Tt){
    {
    std::unique_lock<std::mutex>lock(mutex_);
    queue_.push(std::move(t));
    }
    notifier_.notify_one();
    }

    voidReleaseSender(){
    senders_--;
    notifier_.notify_one();
    }

    std::mutexmutex_;
    std::queue<T>queue_;
    std::condition_variablenotifier_;
    std::atomic<int>senders_{0};
    };

    template<classT>
    Receiver<T>MakeReceiver(){
    returnstd::make_unique<ReceiverImpl<T>>();
    }

    }//namespaceftxui

    #endif//FTXUI_COMPONENT_RECEIVER_HPP_