Create a safe thread wrapper

This commit is contained in:
pixl 2020-06-24 05:48:03 -04:00
parent ef0a0fab8d
commit d84363019b
No known key found for this signature in database
GPG Key ID: 1866C148CD593B6E
5 changed files with 204 additions and 1 deletions

View File

@ -33,7 +33,9 @@ add_executable(logid
backend/hidpp20/features/DeviceName.cpp backend/hidpp20/features/DeviceName.cpp
backend/hidpp20/features/Reset.cpp backend/hidpp20/features/Reset.cpp
backend/dj/Report.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}) set_target_properties(logid PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
#include <system_error>
#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());
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef LOGID_EXCEPTIONHANDLER_H
#define LOGID_EXCEPTIONHANDLER_H
#include <stdexcept>
namespace logid {
namespace ExceptionHandler
{
void Default(std::exception& e);
}}
#endif //LOGID_EXCEPTIONHANDLER_H

72
src/logid/util/thread.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
#include "thread.h"
using namespace logid;
thread::thread(const std::function<void()>& function,
const std::function<void(std::exception&)>& exception_handler)
: _function (std::make_shared<std::function<void()>>(function)),
_exception_handler (std::make_shared<std::function<void
(std::exception&)>> (exception_handler))
{
}
thread::~thread()
{
if(_thread)
if(_thread->joinable())
_thread->detach();
}
void thread::spawn(const std::function<void()>& function,
const std::function<void(std::exception&)>& exception_handler)
{
std::thread([function, exception_handler](){
thread t(function, exception_handler);
t.runSync();
}).detach();
}
void thread::run()
{
_thread = std::make_shared<std::thread>([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);
}
}

57
src/logid/util/thread.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef LOGID_THREAD_H
#define LOGID_THREAD_H
#include <functional>
#include <memory>
#include <thread>
#include "ExceptionHandler.h"
namespace logid
{
class thread
{
public:
explicit thread(const std::function<void()>& function,
const std::function<void(std::exception&)>&
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<void()>& function,
const std::function<void(std::exception&)>&
exception_handler={[](std::exception& e)
{ExceptionHandler::Default(e);}});
void run();
void wait();
void runSync();
private:
std::shared_ptr<std::function<void()>> _function;
std::shared_ptr<std::function<void(std::exception&)>>
_exception_handler;
std::shared_ptr<std::thread> _thread = nullptr;
};
}
#endif //LOGID_THREAD_H