ArthurSonzogni / FTXUI

:computer: C++ Functional Terminal User Interface. :heart:
MIT License
6.64k stars 399 forks source link

Struggling with custom event #133

Closed journeytosilius closed 3 years ago

journeytosilius commented 3 years ago

Hi, first of all thank you for making this amazing library !

My problem is that I can't find any example on how to trigger an screen update from an external event. My program gets json messages through a socket and my goal is to get to update the contents on the screen once a new message arrives. Right now, I have this socket receiving messages on a thread that returns a future, and to test it I'm passing the result to a paragraph. but I can't seem to be able to trigger an screen update following this example : https://arthursonzogni.com/FTXUI/doc/_2examples_2component_2homescreen_8cpp-example.html

The update seems to be triggered here. In my code I have removed the shift references since I'm not using a graph yet.

  std::thread update([&screen, &shift]() {
    for (;;) {
      using namespace std::chrono_literals;
      std::this_thread::sleep_for(0.05s);
      shift++;
      screen.PostEvent(Event::Custom);
    }
  });

Any guidance or help will be much appreciated

ArthurSonzogni commented 3 years ago

Thanks!

screen.PostEvent(Event::Custom);

is thread safe and will request a new frame to be drawn on the thread calling screen.Loop().

So I believe what you did works. Could you help me figure out what doesn't work?

Here is an example I built yesterday: https://github.com/SAtacker/beagle-config/pull/7 that you might want to look. Threads aren't easy to deals with, I am exposing the Receiver/Sender utility class that FTXUI uses internally: https://github.com/ArthurSonzogni/FTXUI/blob/master/include/ftxui/component/receiver.hpp

journeytosilius commented 3 years ago

yeah ! this is kind of what I am trying now, after reading about the receiver component , just a simple test :

void recv_msg(ftxui::Sender<std::wstring> &sender_1)
{

    KlineUtils kutils;

    sequence candle_sequence;

    string interval = "1m";

    string socket_address = "ipc:///home/xavier/ftxtui/" + interval;

    zmq::context_t ctx;

    zmq::socket_t socket(ctx, zmq::socket_type::pull);

    socket.bind(socket_address);

    while (true)
    {

        zmq::message_t message;

        socket.recv(message);

        string message_str = message.to_string();

        nlohmann::json j = nlohmann::json::parse(message_str);

        cout << j[299]["c"] << endl;

        std::string s = j[299]["c"].dump();

        std::wstring w = LR"(CURRENT PRICE: )" + fs::path(s).wstring();

        sender_1->Send(w);

        cout << "sender sent" << endl;

    }
}

void proc_received(Receiver<std::wstring> &receiver){

    std::vector<std::wstring> received;

    while (receiver->HasPending()) {
      std::wstring str;
      receiver->Receive(&str);
      received.push_back(str);
    }

    for ( auto v : received){
        cout << &v << endl;
    }

}

int main(int argc, const char *argv[])
{

    Receiver<std::wstring> receiver = MakeReceiver<std::wstring>();

    ftxui::Sender<std::wstring> sender_1 = receiver->MakeSender();

    thread t1;
    t1 = thread(recv_msg,ref(sender_1));
    thread t2;
    t2 = thread(proc_received, ref(receiver));
    t1.join();
    t2.join();

The thread where the receiver should be ? receiving and pushing to the vector from the sender doesn't print anything, meaning the while loop is not fiding any pending messages to be delivered ? Thanks !

ArthurSonzogni commented 3 years ago

If thread2 is quick enough, (receiver->HasPending()) will be false, explaining what you are seeing.

What happen if you use:

    while (true) {
      std::wstring str;
      receiver->Receive(&str);
      std::cerr << "received: " << str << std::endl;
    }
}

Also, please pass sender_1 ownership by move. Don't use ref(sender_1). Same for receiver.

journeytosilius commented 3 years ago

Ok yes it makes total sense ! Now I'm getting the messages delivered, I will try to implement a screen and to update it, thanks !