Fix EventLoopDispatcher

Fixes callback not called due to dispatcher freed when instance go out of scope. Preserves the EventLoopSignal if there are pending invocations
This commit is contained in:
blagoev 2017-05-06 15:33:06 +03:00
parent 468e69d76e
commit 33bb01be11

View File

@ -45,13 +45,17 @@ template <typename... Args>
class EventLoopDispatcher<void(Args...)> { class EventLoopDispatcher<void(Args...)> {
using Tuple = std::tuple<typename std::remove_reference<Args>::type...>; using Tuple = std::tuple<typename std::remove_reference<Args>::type...>;
private: private:
struct Callback;
struct State { struct State {
public: public:
State(std::function<void(Args...)> func) : m_func(func) { } State(std::function<void(Args...)> func) : m_func(func), m_signal(nullptr) { }
const std::function<void(Args...)> m_func; const std::function<void(Args...)> m_func;
std::queue<Tuple> m_invocations; std::queue<Tuple> m_invocations;
std::mutex m_mutex; std::mutex m_mutex;
std::shared_ptr<EventLoopSignal<Callback>> m_signal;
}; };
const std::shared_ptr<State> m_state; const std::shared_ptr<State> m_state;
@ -67,6 +71,7 @@ private:
::_apply_polyfill::apply(tuple, m_state->m_func); ::_apply_polyfill::apply(tuple, m_state->m_func);
m_state->m_invocations.pop(); m_state->m_invocations.pop();
} }
m_state->m_signal = nullptr;
} }
}; };
const std::shared_ptr<EventLoopSignal<Callback>> m_signal; const std::shared_ptr<EventLoopSignal<Callback>> m_signal;
@ -92,6 +97,7 @@ public:
{ {
std::unique_lock<std::mutex> lock(m_state->m_mutex); std::unique_lock<std::mutex> lock(m_state->m_mutex);
m_state->m_signal = m_signal;
m_state->m_invocations.push(std::make_tuple(args...)); m_state->m_invocations.push(std::make_tuple(args...));
} }
m_signal->notify(); m_signal->notify();