From de6489110031e31579e82686bfd0742d78d25b76 Mon Sep 17 00:00:00 2001 From: Joseph Lenox Date: Thu, 17 May 2018 21:19:20 -0500 Subject: [PATCH] Implemented callback system with a registration function that manipulates a stack. Stack access is protected by a mutex. Writes block until mutex is gotten, reads will try again later in event handler. --- src/GUI/GUI.cpp | 27 ++++++++++++++++++++++++++- src/GUI/GUI.hpp | 17 ++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/GUI/GUI.cpp b/src/GUI/GUI.cpp index 9370e4afe..b72e7b84a 100644 --- a/src/GUI/GUI.cpp +++ b/src/GUI/GUI.cpp @@ -83,8 +83,24 @@ bool App::OnInit() && ($Settings->{_}{version_check} // 1) && (!$Settings->{_}{last_version_check} || (time - $Settings->{_}{last_version_check}) >= 86400); */ - + // run callback functions during idle on the main frame + this->Bind(wxEVT_IDLE, + [this](wxIdleEvent& e) { + std::function func {nullptr}; // + // try to get the mutex. If we can't, just skip this idle event and get the next one. + if (!this->callback_register.try_lock()) return; + // pop callback + if (cb.size() >= 1) { + func = cb.top(); + cb.pop(); + } + // unlock mutex + this->callback_register.unlock(); + try { // call the function if it's not nullptr; + if (func != nullptr) func(); + } catch (std::exception& e) { Slic3r::Log::error(LogChannel, LOG_WSTRING("Exception thrown: " << e.what())); } + }); /* EVT_IDLE($frame, sub { while (my $cb = shift @cb) { @@ -184,4 +200,13 @@ void App::load_presets() { */ } +void App::CallAfter(std::function cb_function) { + // set mutex + this->callback_register.lock(); + // push function onto stack + this->cb.emplace(cb_function); + // unset mutex + this->callback_register.unlock(); +} + }} // namespace Slic3r::GUI diff --git a/src/GUI/GUI.hpp b/src/GUI/GUI.hpp index 82c4b2082..83389bbf2 100644 --- a/src/GUI/GUI.hpp +++ b/src/GUI/GUI.hpp @@ -5,10 +5,13 @@ #include "Notifier.hpp" #include #include +#include +#include namespace Slic3r { namespace GUI { + // Friendly indices for the preset lists. enum class PresetID { PRINT = 0, @@ -29,6 +32,11 @@ public: /// Move/resize a named TopLevelWindow (includes Frames) from Settings void restore_window_pos(wxTopLevelWindow* window, const wxString& name ); + /// Function to add callback functions to the idle loop stack. + void CallAfter(std::function cb_function); + + + private: std::shared_ptr gui_config; // GUI-specific configuration options std::unique_ptr notifier {nullptr}; @@ -37,8 +45,15 @@ private: void load_presets(); wxString datadir {""}; - const std::string LogChannel {"GUI"}; //< Which log these messages should go to. + const std::string LogChannel {"APP"}; //< Which log these messages should go to. + + /// Lock to guard the callback stack + std::mutex callback_register; + + /// callbacks registered to run during idle event. + std::stack > cb {}; }; + }} // namespace Slic3r::GUI #endif // GUI_HPP