From e1e17e82406edb9af31e171f94c9f916015fdc39 Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Wed, 23 Nov 2022 23:51:32 +0300 Subject: [PATCH 1/3] Add new example --- src/examples/rppqt/CMakeLists.txt | 1 + .../rppqt/multi_threaded/CMakeLists.txt | 9 +++ .../rppqt/multi_threaded/multi_threaded.cpp | 71 +++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 src/examples/rppqt/multi_threaded/CMakeLists.txt create mode 100644 src/examples/rppqt/multi_threaded/multi_threaded.cpp diff --git a/src/examples/rppqt/CMakeLists.txt b/src/examples/rppqt/CMakeLists.txt index 63ad10165..1ee9dc328 100644 --- a/src/examples/rppqt/CMakeLists.txt +++ b/src/examples/rppqt/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(interactive_window) add_subdirectory(doxygen) +add_subdirectory(multi_threaded) diff --git a/src/examples/rppqt/multi_threaded/CMakeLists.txt b/src/examples/rppqt/multi_threaded/CMakeLists.txt new file mode 100644 index 000000000..048b988ab --- /dev/null +++ b/src/examples/rppqt/multi_threaded/CMakeLists.txt @@ -0,0 +1,9 @@ +SET(TARGET multi_threaded) +add_executable(${TARGET} + ${TARGET}.cpp +) + +target_link_libraries(${TARGET} PRIVATE rppqt ${RPP_QT_TARGET}::Widgets) +set_target_properties(${TARGET} PROPERTIES FOLDER Examples/rppqt) + +rpp_add_qt_support_to_executable(${TARGET}) \ No newline at end of file diff --git a/src/examples/rppqt/multi_threaded/multi_threaded.cpp b/src/examples/rppqt/multi_threaded/multi_threaded.cpp new file mode 100644 index 000000000..9b47b63d8 --- /dev/null +++ b/src/examples/rppqt/multi_threaded/multi_threaded.cpp @@ -0,0 +1,71 @@ +#include +#include + +#include + +#include +#include +#include +#include +#include + +int main(int argc, char* argv[]) +{ + QApplication app{argc, argv}; + QVBoxLayout vbox{}; + + QLabel label{}; + QPushButton button{"CLick me"}; + vbox.addWidget(&label); + vbox.addWidget(&button); + QMainWindow window{}; + + window.setCentralWidget(new QWidget); + window.centralWidget()->setLayout(&vbox); + + window.show(); + + rpp::source::interval(std::chrono::seconds{1}) + .tap([](const auto&) + { + std::cout << "Interval from thread: " << std::this_thread::get_id() << std::endl; + }) + .combine_latest([](size_t index, size_t amount_of_clicks) + { + return QString("Seconds since start: %1 Clicks since start: %2").arg(index).arg(amount_of_clicks); + }, + rppqt::source::from_signal(button, &QPushButton::pressed).scan(size_t{}, + [](size_t seed, const auto&) + { + return seed + 1; + }) + .tap([](const auto&) + { + std::cout << "Click from thread: " << + std::this_thread::get_id() << std::endl; + }) + .start_with(size_t{0})) + .subscribe_on(rpp::schedulers::new_thread{}) + .observe_on(rppqt::schedulers::main_thread_scheduler{}) + .subscribe([&](const QString& text) + { + std::cout << "Text updated from thread: " << std::this_thread::get_id() << std::endl; + label.setText(text); + }); + + std::cout << "Application thread: " << std::this_thread::get_id() << std::endl; + + // There we have application's thread, "new_thread" where observable subscribed and interval events happened. + // But we need to update GUI's objects in main thread, so, we forces observable to emit items to subscribe in QT's main thread + // Example of output: + /* + Application thread: 19748 <----- main thread + Interval from thread: 30604 <----- interval happens from another thread + Text updated from thread: 19748 <----- but update then transfered to main thread + Click from thread: 19748 <----- click happens from main thread due to QT logic + Text updated from thread: 19748 <----- and update happens in main thread + Interval from thread: 30604 + Text updated from thread: 19748 + */ + return app.exec(); +} From ca639f5e278297ccc88e515133fd94303b4371f8 Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Wed, 23 Nov 2022 23:51:38 +0300 Subject: [PATCH 2/3] Minor update --- src/rppqt/rppqt/schedulers/main_thread_scheduler.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rppqt/rppqt/schedulers/main_thread_scheduler.hpp b/src/rppqt/rppqt/schedulers/main_thread_scheduler.hpp index 103ab6bbf..4f7929329 100644 --- a/src/rppqt/rppqt/schedulers/main_thread_scheduler.hpp +++ b/src/rppqt/rppqt/schedulers/main_thread_scheduler.hpp @@ -56,7 +56,7 @@ class main_thread_scheduler final : public rpp::schedulers::details::scheduler_t throw utils::no_active_qapplication{ "Pointer to application is null. Create QApplication before using main_thread_scheduler!"}; - const auto duration = std::chrono::duration_cast(now() - time_point).count(); + const auto duration = std::max(std::chrono::milliseconds{0}, std::chrono::duration_cast(time_point - now())); QTimer::singleShot(duration, application, std::move(fn)); } From 59faf94ad27baebaa4bf7c81a6436f1d40190218 Mon Sep 17 00:00:00 2001 From: Aleksey Loginov Date: Wed, 23 Nov 2022 23:51:57 +0300 Subject: [PATCH 3/3] Update version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 295332d34..007fd0488 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ include(cmake/prelude.cmake) project( ReactivePlusPlus - VERSION 0.1.4 + VERSION 0.2.0 DESCRIPTION "ReactivePlusPlus is library for building asynchronous event-driven streams of data with help of sequences of primitive operators in the declarative form" HOMEPAGE_URL "https://github.com/victimsnino/ReactivePlusPlus" LANGUAGES CXX