Propagate timer exceptions to the main thread

This commit is contained in:
King_DuckZ 2020-08-15 22:52:20 +01:00
parent 85c240b53d
commit f648e3a8a2
7 changed files with 35 additions and 6 deletions

View file

@ -42,4 +42,8 @@ void Event::on_loop_stopping_local() noexcept {
} }
} }
void Event::set_exception (std::exception_ptr ptr) {
m_eventia->set_exception(ptr);
}
} //namespace eve } //namespace eve

View file

@ -17,6 +17,8 @@
#pragma once #pragma once
#include <exception>
namespace eve { namespace eve {
class Context; class Context;
@ -28,6 +30,7 @@ protected:
virtual ~Event() noexcept; virtual ~Event() noexcept;
virtual void on_loop_stopping() noexcept = 0; virtual void on_loop_stopping() noexcept = 0;
void set_exception (std::exception_ptr ptr);
private: private:
void on_loop_stopping_local() noexcept; void on_loop_stopping_local() noexcept;

View file

@ -26,6 +26,7 @@
#include <utility> #include <utility>
#include <future> #include <future>
#include <stdexcept> #include <stdexcept>
#include <atomic>
namespace eve { namespace eve {
@ -51,12 +52,14 @@ struct Eventia::LocalData {
Context context; Context context;
std::promise<void> loop_end_promise; std::promise<void> loop_end_promise;
std::future<void> loop_end; std::future<void> loop_end;
std::atomic_bool mark_loop_end;
}; };
Eventia::LocalData::LocalData(Eventia* eventia) : Eventia::LocalData::LocalData(Eventia* eventia) :
loop(ev::AUTO), loop(ev::AUTO),
context{ &loop, &ev_mutex, &async, eventia }, context{ &loop, &ev_mutex, &async, eventia },
loop_end(loop_end_promise.get_future()) loop_end(loop_end_promise.get_future()),
mark_loop_end(true)
{ {
} }
@ -86,11 +89,13 @@ Eventia::~Eventia() noexcept {
std::function<void()> Eventia::event_functor() { std::function<void()> Eventia::event_functor() {
return std::function<void()>([this]() { return std::function<void()>([this]() {
m_local->mark_loop_end = true;
std::unique_lock<std::mutex> lock(m_local->ev_mutex); std::unique_lock<std::mutex> lock(m_local->ev_mutex);
m_local->loop.run(0); m_local->loop.run(0);
#if !defined(NDEBUG) #if !defined(NDEBUG)
std::cout << "ev loop stopped\n"; std::cout << "ev loop stopped\n";
#endif #endif
if (m_local->mark_loop_end)
m_local->loop_end_promise.set_value(); m_local->loop_end_promise.set_value();
}); });
} }
@ -124,6 +129,12 @@ void Eventia::unlock_mutex_libev() noexcept {
m_local->ev_mutex.unlock(); m_local->ev_mutex.unlock();
} }
void Eventia::set_exception (std::exception_ptr ptr) {
m_local->mark_loop_end = false;
this->stop();
m_local->loop_end_promise.set_exception(ptr);
}
const Context& Eventia::context() { const Context& Eventia::context() {
return m_local->context; return m_local->context;
} }

View file

@ -19,6 +19,7 @@
#include <memory> #include <memory>
#include <functional> #include <functional>
#include <exception>
namespace eve { namespace eve {
@ -47,6 +48,7 @@ private:
void lock_mutex_libev() noexcept; void lock_mutex_libev() noexcept;
void unlock_mutex_libev() noexcept; void unlock_mutex_libev() noexcept;
void set_exception (std::exception_ptr ptr);
const Context& context(); const Context& context();
unsigned int register_stop_callback (std::function<void()>&& cb); unsigned int register_stop_callback (std::function<void()>&& cb);

View file

@ -24,7 +24,7 @@ namespace eve {
class Context; class Context;
class Signal : public Event { class Signal : private Event {
public: public:
Signal() = delete; Signal() = delete;
Signal(Signal&&) = default; Signal(Signal&&) = default;
@ -35,6 +35,8 @@ public:
virtual void on_signal() = 0; virtual void on_signal() = 0;
protected: protected:
using Event::set_exception;
private: private:
struct LocalData; struct LocalData;

View file

@ -36,6 +36,7 @@ public:
protected: protected:
void set_timer (double delay); void set_timer (double delay);
using Event::set_exception;
private: private:
struct LocalData; struct LocalData;

View file

@ -18,6 +18,7 @@
#pragma once #pragma once
#include "timer_base.hpp" #include "timer_base.hpp"
#include <exception>
namespace oro { namespace oro {
class Api; class Api;
@ -54,9 +55,14 @@ inline TimerOroApi<Method>::TimerOroApi (
template<auto Method> template<auto Method>
inline void TimerOroApi<Method>::fetch_data() { inline void TimerOroApi<Method>::fetch_data() {
try {
auto results = (oro_api().*Method)(); auto results = (oro_api().*Method)();
set_next_timer(results.first); set_next_timer(results.first);
this->update_db(results.second); this->update_db(results.second);
}
catch (...) {
this->set_exception(std::current_exception());
}
} }
} //namespace duck } //namespace duck