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 | |
parent | a54672fb54a3671e451c28a852a64540d385f335 (diff) |
Firmware updater: Perform work in a background thread
Diffstat (limited to 'xs/src/avrdude')
-rw-r--r-- | xs/src/avrdude/avrdude-slic3r.cpp | 119 | ||||
-rw-r--r-- | xs/src/avrdude/avrdude-slic3r.hpp | 25 |
2 files changed, 112 insertions, 32 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; } diff --git a/xs/src/avrdude/avrdude-slic3r.hpp b/xs/src/avrdude/avrdude-slic3r.hpp index ecae654b2..097e46028 100644 --- a/xs/src/avrdude/avrdude-slic3r.hpp +++ b/xs/src/avrdude/avrdude-slic3r.hpp @@ -1,9 +1,9 @@ #ifndef slic3r_avrdude_slic3r_hpp_ #define slic3r_avrdude_slic3r_hpp_ +#include <memory> #include <vector> #include <string> -#include <ostream> #include <functional> namespace Slic3r { @@ -11,11 +11,13 @@ namespace Slic3r { class AvrDude { public: + typedef std::shared_ptr<AvrDude> Ptr; typedef std::function<void(const char * /* msg */, unsigned /* size */)> MessageFn; typedef std::function<void(const char * /* task */, unsigned /* progress */)> ProgressFn; + typedef std::function<void(int /* exit status */)> CompleteFn; AvrDude(); - AvrDude(AvrDude &&) = delete; + AvrDude(AvrDude &&) = default; AvrDude(const AvrDude &) = delete; AvrDude &operator=(AvrDude &&) = delete; AvrDude &operator=(const AvrDude &) = delete; @@ -23,17 +25,26 @@ public: // Set location of avrdude's main configuration file AvrDude& sys_config(std::string sys_config); + + // Set avrdude cli arguments + AvrDude& args(std::vector<std::string> args); + // Set message output callback AvrDude& on_message(MessageFn fn); + // Set progress report callback // Progress is reported per each task (reading / writing), progress is reported in percents. AvrDude& on_progress(MessageFn fn); - - int run(std::vector<std::string> args); + + // Called when avrdude's main function finishes + AvrDude& on_complete(CompleteFn fn); + + int run_sync(); + Ptr run(); + void join(); private: - std::string m_sys_config; - MessageFn m_message_fn; - ProgressFn m_progress_fn; + struct priv; + std::unique_ptr<priv> p; }; |