diff options
author | Vojtech Kral <vojtech@kral.hk> | 2018-05-18 18:35:24 +0300 |
---|---|---|
committer | Vojtech Kral <vojtech@kral.hk> | 2018-05-21 19:58:22 +0300 |
commit | 98ae20c3df7ea00c608fe4ab4c504ffa09a8a1aa (patch) | |
tree | dfd7800f9083943d75d57a0b8be0e730e6402d6e /xs/src/avrdude/avrdude-slic3r.cpp | |
parent | a54672fb54a3671e451c28a852a64540d385f335 (diff) |
Firmware updater: Perform work in a background thread
Diffstat (limited to 'xs/src/avrdude/avrdude-slic3r.cpp')
-rw-r--r-- | xs/src/avrdude/avrdude-slic3r.cpp | 119 |
1 files changed, 94 insertions, 25 deletions
diff --git a/xs/src/avrdude/avrdude-slic3r.cpp b/xs/src/avrdude/avrdude-slic3r.cpp index 8e00c73dc..a581371ae 100644 --- a/xs/src/avrdude/avrdude-slic3r.cpp +++ b/xs/src/avrdude/avrdude-slic3r.cpp @@ -1,5 +1,7 @@ #include "avrdude-slic3r.hpp" +#include <thread> + extern "C" { #include "ac_cfg.h" #include "avrdude.h" @@ -8,6 +10,9 @@ extern "C" { namespace Slic3r { + +// C callbacks + // Used by our custom code in avrdude to receive messages that avrdude normally outputs on stdout (see avrdude_message()) static void avrdude_message_handler_closure(const char *msg, unsigned size, void *user_p) { @@ -23,51 +28,115 @@ static void avrdude_progress_handler_closure(const char *task, unsigned progress } -AvrDude::AvrDude() {} -AvrDude::~AvrDude() {} +// Private + +struct AvrDude::priv +{ + std::string sys_config; + std::vector<std::string> args; + MessageFn message_fn; + ProgressFn progress_fn; + CompleteFn complete_fn; + + std::thread avrdude_thread; + + int run(); +}; + +int AvrDude::priv::run() { + std::vector<char*> c_args {{ const_cast<char*>(PACKAGE_NAME) }}; + for (const auto &arg : args) { + c_args.push_back(const_cast<char*>(arg.data())); + } + + if (message_fn) { + ::avrdude_message_handler_set(avrdude_message_handler_closure, reinterpret_cast<void*>(&message_fn)); + } else { + ::avrdude_message_handler_set(nullptr, nullptr); + } + + if (progress_fn) { + ::avrdude_progress_handler_set(avrdude_progress_handler_closure, reinterpret_cast<void*>(&progress_fn)); + } else { + ::avrdude_progress_handler_set(nullptr, nullptr); + } + + const auto res = ::avrdude_main(static_cast<int>(c_args.size()), c_args.data(), sys_config.c_str()); + + ::avrdude_message_handler_set(nullptr, nullptr); + ::avrdude_progress_handler_set(nullptr, nullptr); + return res; +} + + +// Public + +AvrDude::AvrDude() : p(new priv()) {} + +AvrDude::~AvrDude() +{ + if (p && p->avrdude_thread.joinable()) { + p->avrdude_thread.detach(); + } +} AvrDude& AvrDude::sys_config(std::string sys_config) { - m_sys_config = std::move(sys_config); + if (p) { p->sys_config = std::move(sys_config); } + return *this; +} + +AvrDude& AvrDude::args(std::vector<std::string> args) +{ + if (p) { p->args = std::move(args); } return *this; } AvrDude& AvrDude::on_message(MessageFn fn) { - m_message_fn = std::move(fn); + if (p) { p->message_fn = std::move(fn); } return *this; } AvrDude& AvrDude::on_progress(MessageFn fn) { - m_progress_fn = std::move(fn); + if (p) { p->progress_fn = std::move(fn); } return *this; } -int AvrDude::run(std::vector<std::string> args) +AvrDude& AvrDude::on_complete(CompleteFn fn) { - std::vector<char *> c_args {{ const_cast<char*>(PACKAGE_NAME) }}; - for (const auto &arg : args) { - c_args.push_back(const_cast<char*>(arg.data())); - } + if (p) { p->complete_fn = std::move(fn); } + return *this; +} - if (m_message_fn) { - ::avrdude_message_handler_set(avrdude_message_handler_closure, reinterpret_cast<void*>(&m_message_fn)); - } else { - ::avrdude_message_handler_set(nullptr, nullptr); +int AvrDude::run_sync() +{ + return p->run(); +} + +AvrDude::Ptr AvrDude::run() +{ + auto self = std::make_shared<AvrDude>(std::move(*this)); + + if (self->p) { + auto avrdude_thread = std::thread([self]() { + auto res = self->p->run(); + if (self->p->complete_fn) { + self->p->complete_fn(res); + } + }); + self->p->avrdude_thread = std::move(avrdude_thread); } - - if (m_progress_fn) { - ::avrdude_progress_handler_set(avrdude_progress_handler_closure, reinterpret_cast<void*>(&m_progress_fn)); - } else { - ::avrdude_progress_handler_set(nullptr, nullptr); + + return self; +} + +void AvrDude::join() +{ + if (p && p->avrdude_thread.joinable()) { + p->avrdude_thread.join(); } - - const auto res = ::avrdude_main(static_cast<int>(c_args.size()), c_args.data(), m_sys_config.c_str()); - - ::avrdude_message_handler_set(nullptr, nullptr); - ::avrdude_progress_handler_set(nullptr, nullptr); - return res; } |