Improve thread usages.

This commit is contained in:
ArthurSonzogni 2020-03-25 01:15:46 +01:00
parent 0a7b556a12
commit 508b2ef048
2 changed files with 36 additions and 21 deletions

View File

@ -162,6 +162,7 @@ if (FTXUI_BUILD_TESTS AND GTEST_FOUND AND THREADS_FOUND)
target_include_directories(dom_tests target_include_directories(dom_tests
PRIVATE ${GTest_INCLUDE_DIRS} PRIVATE ${GTest_INCLUDE_DIRS}
) )
set_property(TARGET dom_tests PROPERTY CXX_STANDARD 17)
gtest_discover_tests(dom_tests) gtest_discover_tests(dom_tests)
add_test(dom_tests dom_tests) add_test(dom_tests dom_tests)
endif() endif()

View File

@ -28,6 +28,21 @@
namespace ftxui { namespace ftxui {
// Produce a stream of Event from a stream of char.
void CharToEventStream(Receiver<char> receiver, Sender<Event> sender) {
char c;
while (receiver->Receive(&c))
Event::Convert(receiver, sender, c);
}
// Read char from the terminal.
void UnixEventListener(std::atomic<bool>* quit, Sender<char> sender) {
// TODO(arthursonzogni): Use a timeout so that it doesn't block even if the
// user doesn't generate new chars.
while (!*quit)
sender->Send((char)getchar());
}
static const char* HIDE_CURSOR = "\x1B[?25l"; static const char* HIDE_CURSOR = "\x1B[?25l";
static const char* SHOW_CURSOR = "\x1B[?25h"; static const char* SHOW_CURSOR = "\x1B[?25h";
@ -85,7 +100,8 @@ ScreenInteractive ScreenInteractive::FitComponent() {
} }
void ScreenInteractive::PostEvent(Event event) { void ScreenInteractive::PostEvent(Event event) {
event_sender_->Send(event); if (!quit_)
event_sender_->Send(event);
} }
void ScreenInteractive::Loop(Component* component) { void ScreenInteractive::Loop(Component* component) {
@ -140,26 +156,20 @@ void ScreenInteractive::Loop(Component* component) {
std::cout << std::endl; std::cout << std::endl;
}); });
// Produce a stream of Event from a stream of char.
auto char_receiver = MakeReceiver<char>(); auto char_receiver = MakeReceiver<char>();
// Spawn a thread to produce char.
auto char_sender = char_receiver->MakeSender(); auto char_sender = char_receiver->MakeSender();
std::thread read_char([&] {
// TODO(arthursonzogni): Use a timeout so that it doesn't block even if the
// user doesn't generate new chars.
while (!quit_)
char_sender->Send((char)getchar());
char_sender.reset();
});
// Spawn a thread producing events and consumer chars.
auto event_sender = event_receiver_->MakeSender(); auto event_sender = event_receiver_->MakeSender();
std::thread convert_char_to_event([&] { auto char_to_event_stream = std::thread(
char c; CharToEventStream, std::move(char_receiver), std::move(event_sender));
while (char_receiver->Receive(&c))
Event::Convert(char_receiver, event_sender, c); // Depending on the OS, start a thread that will produce events and/or chars.
event_sender.reset(); #if defined(WIN32)
}); // TODO(arthursonzogni) implement here.
#else
auto unix_event_listener =
std::thread(&UnixEventListener, &quit_, std::move(char_sender));
#endif
// The main loop. // The main loop.
while (!quit_) { while (!quit_) {
@ -171,8 +181,9 @@ void ScreenInteractive::Loop(Component* component) {
if (event_receiver_->Receive(&event)) if (event_receiver_->Receive(&event))
component->OnEvent(event); component->OnEvent(event);
} }
read_char.join();
convert_char_to_event.join(); char_to_event_stream.join();
unix_event_listener.join();
OnExit(0); OnExit(0);
} }
@ -231,7 +242,10 @@ void ScreenInteractive::Draw(Component* component) {
} }
std::function<void()> ScreenInteractive::ExitLoopClosure() { std::function<void()> ScreenInteractive::ExitLoopClosure() {
return [this]() { quit_ = true; }; return [this]() {
quit_ = true;
event_sender_.reset();
};
} }
} // namespace ftxui. } // namespace ftxui.