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.
This commit is contained in:
Joseph Lenox 2018-05-17 21:19:20 -05:00
parent 5f2fa5b5fb
commit 7f485cd094
2 changed files with 42 additions and 2 deletions

View File

@ -85,6 +85,22 @@ bool App::OnInit()
*/ */
// run callback functions during idle on the main frame // run callback functions during idle on the main frame
this->Bind(wxEVT_IDLE,
[this](wxIdleEvent& e) {
std::function<void()> 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 { EVT_IDLE($frame, sub {
while (my $cb = shift @cb) { while (my $cb = shift @cb) {
@ -184,4 +200,13 @@ void App::load_presets() {
*/ */
} }
void App::CallAfter(std::function<void()> 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 }} // namespace Slic3r::GUI

View File

@ -5,10 +5,13 @@
#include "Notifier.hpp" #include "Notifier.hpp"
#include <string> #include <string>
#include <vector> #include <vector>
#include <stack>
#include <mutex>
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
// Friendly indices for the preset lists. // Friendly indices for the preset lists.
enum class PresetID { enum class PresetID {
PRINT = 0, PRINT = 0,
@ -29,6 +32,11 @@ public:
/// Move/resize a named TopLevelWindow (includes Frames) from Settings /// Move/resize a named TopLevelWindow (includes Frames) from Settings
void restore_window_pos(wxTopLevelWindow* window, const wxString& name ); void restore_window_pos(wxTopLevelWindow* window, const wxString& name );
/// Function to add callback functions to the idle loop stack.
void CallAfter(std::function<void()> cb_function);
private: private:
std::shared_ptr<Settings> gui_config; // GUI-specific configuration options std::shared_ptr<Settings> gui_config; // GUI-specific configuration options
std::unique_ptr<Notifier> notifier {nullptr}; std::unique_ptr<Notifier> notifier {nullptr};
@ -37,8 +45,15 @@ private:
void load_presets(); void load_presets();
wxString datadir {""}; 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<std::function<void()> > cb {};
}; };
}} // namespace Slic3r::GUI }} // namespace Slic3r::GUI
#endif // GUI_HPP #endif // GUI_HPP