From d84363019b4fe162485bd430df4774d1d239cc91 Mon Sep 17 00:00:00 2001 From: pixl Date: Wed, 24 Jun 2020 05:48:03 -0400 Subject: [PATCH] Create a safe thread wrapper --- src/logid/CMakeLists.txt | 4 +- src/logid/util/ExceptionHandler.cpp | 43 +++++++++++++++++ src/logid/util/ExceptionHandler.h | 29 ++++++++++++ src/logid/util/thread.cpp | 72 +++++++++++++++++++++++++++++ src/logid/util/thread.h | 57 +++++++++++++++++++++++ 5 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 src/logid/util/ExceptionHandler.cpp create mode 100644 src/logid/util/ExceptionHandler.h create mode 100644 src/logid/util/thread.cpp create mode 100644 src/logid/util/thread.h diff --git a/src/logid/CMakeLists.txt b/src/logid/CMakeLists.txt index 86d9086..bf7f61a 100644 --- a/src/logid/CMakeLists.txt +++ b/src/logid/CMakeLists.txt @@ -33,7 +33,9 @@ add_executable(logid backend/hidpp20/features/DeviceName.cpp backend/hidpp20/features/Reset.cpp backend/dj/Report.cpp - util/mutex_queue.h) + util/mutex_queue.h + util/thread.cpp + util/ExceptionHandler.cpp) set_target_properties(logid PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/src/logid/util/ExceptionHandler.cpp b/src/logid/util/ExceptionHandler.cpp new file mode 100644 index 0000000..3019806 --- /dev/null +++ b/src/logid/util/ExceptionHandler.cpp @@ -0,0 +1,43 @@ +/* + * Copyright 2019-2020 PixlOne + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#include +#include "../util.h" +#include "ExceptionHandler.h" +#include "../backend/hidpp10/Error.h" +#include "../backend/hidpp20/Error.h" + +using namespace logid; + +void ExceptionHandler::Default(std::exception& error) +{ + try { + throw error; + } catch(backend::hidpp10::Error& e) { + log_printf(WARN, "HID++ 1.0 error ignored on detached thread: %s", + error.what()); + } catch(backend::hidpp20::Error& e) { + log_printf(WARN, "HID++ 2.0 error ignored on detached thread: %s", + error.what()); + } catch(std::system_error& e) { + log_printf(WARN, "System error ignored on detached thread: %s", + error.what()); + } catch(std::exception& e) { + log_printf(WARN, "Error ignored on detached thread: %s", + error.what()); + } +} \ No newline at end of file diff --git a/src/logid/util/ExceptionHandler.h b/src/logid/util/ExceptionHandler.h new file mode 100644 index 0000000..daf9bea --- /dev/null +++ b/src/logid/util/ExceptionHandler.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019-2020 PixlOne + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef LOGID_EXCEPTIONHANDLER_H +#define LOGID_EXCEPTIONHANDLER_H + +#include + +namespace logid { +namespace ExceptionHandler +{ + void Default(std::exception& e); +}} + +#endif //LOGID_EXCEPTIONHANDLER_H diff --git a/src/logid/util/thread.cpp b/src/logid/util/thread.cpp new file mode 100644 index 0000000..3460bd7 --- /dev/null +++ b/src/logid/util/thread.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2019-2020 PixlOne + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#include "thread.h" + +using namespace logid; + +thread::thread(const std::function& function, + const std::function& exception_handler) + : _function (std::make_shared>(function)), + _exception_handler (std::make_shared> (exception_handler)) +{ +} + +thread::~thread() +{ + if(_thread) + if(_thread->joinable()) + _thread->detach(); +} + +void thread::spawn(const std::function& function, + const std::function& exception_handler) +{ + std::thread([function, exception_handler](){ + thread t(function, exception_handler); + t.runSync(); + }).detach(); +} + +void thread::run() +{ + _thread = std::make_shared([f=this->_function, + eh=this->_exception_handler]() { + try { + (*f)(); + } catch (std::exception& e) { + (*eh)(e); + } + }); +} + +void thread::wait() +{ + if(_thread) + if(_thread->joinable()) + _thread->join(); +} + +void thread::runSync() +{ + try { + (*_function)(); + } catch(std::exception& e) { + (*_exception_handler)(e); + } +} \ No newline at end of file diff --git a/src/logid/util/thread.h b/src/logid/util/thread.h new file mode 100644 index 0000000..311a1f6 --- /dev/null +++ b/src/logid/util/thread.h @@ -0,0 +1,57 @@ +/* + * Copyright 2019-2020 PixlOne + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef LOGID_THREAD_H +#define LOGID_THREAD_H + +#include +#include +#include +#include "ExceptionHandler.h" + +namespace logid +{ + class thread + { + public: + explicit thread(const std::function& function, + const std::function& + exception_handler={[](std::exception& e) + {ExceptionHandler::Default(e);}}); + + ~thread(); + + /* This function spawns a new thread and forgets about it, + * safe equivalent to std::thread{...}.detach() + */ + static void spawn(const std::function& function, + const std::function& + exception_handler={[](std::exception& e) + {ExceptionHandler::Default(e);}}); + + void run(); + void wait(); + void runSync(); + private: + std::shared_ptr> _function; + std::shared_ptr> + _exception_handler; + std::shared_ptr _thread = nullptr; + }; +} + +#endif //LOGID_THREAD_H