Store all handles inside eventloop

This is needed because the handle's lifetime has to be at least the
lifetime of the eventloop since the eventloop requires the handle's
memory during shutdown (for closing the handles).
This commit is contained in:
patrick96 2021-09-12 16:25:23 +02:00 committed by Patrick Ziegler
parent 2551ea0205
commit 91759a4c96
3 changed files with 43 additions and 33 deletions

View File

@ -116,7 +116,7 @@ class controller : public signal_receiver<SIGN_PRIORITY_CONTROLLER, signals::eve
* This handle is used to notify the eventloop of changes which are not otherwise covered by other handles. * This handle is used to notify the eventloop of changes which are not otherwise covered by other handles.
* E.g. click actions. * E.g. click actions.
*/ */
std::unique_ptr<AsyncHandle> m_notifier{nullptr}; AsyncHandle_t m_notifier{nullptr};
/** /**
* Notification data for the controller. * Notification data for the controller.

View File

@ -148,6 +148,14 @@ struct AsyncHandle : public UVHandle<uv_async_t> {
} }
}; };
using SignalHandle_t = std::unique_ptr<SignalHandle>;
using PollHandle_t = std::unique_ptr<PollHandle>;
using FSEventHandle_t = std::unique_ptr<FSEventHandle>;
using PipeHandle_t = std::unique_ptr<PipeHandle>;
using TimerHandle_t = std::unique_ptr<TimerHandle>;
// shared_ptr because we need a reference outside to call send
using AsyncHandle_t = std::shared_ptr<AsyncHandle>;
class eventloop { class eventloop {
public: public:
eventloop(); eventloop();
@ -157,43 +165,51 @@ class eventloop {
void stop(); void stop();
/**
* TODO make protected
*/
uv_loop_t* get() const {
return m_loop.get();
}
void signal_handler(int signum, std::function<void(int)> fun) { void signal_handler(int signum, std::function<void(int)> fun) {
auto handle = std::make_unique<SignalHandle>(get(), fun); m_sig_handles.emplace_back(std::make_unique<SignalHandle>(get(), fun));
handle->start(signum); m_sig_handles.back()->start(signum);
m_sig_handles.push_back(std::move(handle));
} }
void poll_handler(int events, int fd, std::function<void(int, int)> fun) { void poll_handler(int events, int fd, std::function<void(int, int)> fun) {
auto handle = std::make_unique<PollHandle>(get(), fd, fun); m_poll_handles.emplace_back(std::make_unique<PollHandle>(get(), fd, fun));
handle->start(events); m_poll_handles.back()->start(events);
m_poll_handles.push_back(std::move(handle));
} }
void fs_event_handler(const string& path, std::function<void(const char*, int, int)> fun) { void fs_event_handler(const string& path, std::function<void(const char*, int, int)> fun) {
auto handle = std::make_unique<FSEventHandle>(get(), fun); m_fs_event_handles.emplace_back(std::make_unique<FSEventHandle>(get(), fun));
handle->start(path); m_fs_event_handles.back()->start(path);
m_fs_event_handles.push_back(std::move(handle)); }
void pipe_handle(int fd, std::function<void(const string)> fun) {
m_pipe_handles.emplace_back(std::make_unique<PipeHandle>(get(), fun));
m_pipe_handles.back()->start(fd);
}
void timer_handle(uint64_t timeout, uint64_t repeat, std::function<void(void)> fun) {
m_timer_handles.emplace_back(std::make_unique<TimerHandle>(get(), fun));
// Trigger a single screenshot after 3 seconds
m_timer_handles.back()->start(timeout, repeat);
}
AsyncHandle_t async_handle(std::function<void(void)> fun) {
m_async_handles.emplace_back(std::make_shared<AsyncHandle>(get(), fun));
return m_async_handles.back();
} }
protected: protected:
template <typename H, typename T, typename... Args, void (T::*F)(Args...)> uv_loop_t* get() const {
static void generic_cb(H* handle, Args&&... args) { return m_loop.get();
(static_cast<T*>(handle->data).*F)(std::forward<Args>(args)...);
} }
private: private:
std::unique_ptr<uv_loop_t> m_loop{nullptr}; std::unique_ptr<uv_loop_t> m_loop{nullptr};
vector<std::unique_ptr<SignalHandle>> m_sig_handles; vector<SignalHandle_t> m_sig_handles;
vector<std::unique_ptr<PollHandle>> m_poll_handles; vector<PollHandle_t> m_poll_handles;
vector<std::unique_ptr<FSEventHandle>> m_fs_event_handles; vector<FSEventHandle_t> m_fs_event_handles;
vector<PipeHandle_t> m_pipe_handles;
vector<TimerHandle_t> m_timer_handles;
vector<AsyncHandle_t> m_async_handles;
}; };
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -252,12 +252,8 @@ void controller::read_events(bool confwatch) {
m_bar->start(); m_bar->start();
} }
auto ipc_handle = std::unique_ptr<PipeHandle>(nullptr);
auto screenshot_timer_handle = std::unique_ptr<TimerHandle>(nullptr);
try { try {
eloop = std::make_unique<eventloop>(); eloop = std::make_unique<eventloop>();
auto loop = eloop->get();
eloop->poll_handler( eloop->poll_handler(
UV_READABLE, m_connection.get_file_descriptor(), [this](int status, int events) { conn_cb(status, events); }); UV_READABLE, m_connection.get_file_descriptor(), [this](int status, int events) { conn_cb(status, events); });
@ -272,18 +268,16 @@ void controller::read_events(bool confwatch) {
} }
if (m_ipc) { if (m_ipc) {
ipc_handle = std::make_unique<PipeHandle>(loop, [this](const string payload) { ipc_cb(payload); }); eloop->pipe_handle(m_ipc->get_file_descriptor(), [this](const string payload) { ipc_cb(payload); });
ipc_handle->start(m_ipc->get_file_descriptor());
} }
m_notifier = std::make_unique<AsyncHandle>(loop, [this]() { notifier_handler(); });
if (!m_snapshot_dst.empty()) { if (!m_snapshot_dst.empty()) {
screenshot_timer_handle = std::make_unique<TimerHandle>(loop, [this]() { screenshot_handler(); });
// Trigger a single screenshot after 3 seconds // Trigger a single screenshot after 3 seconds
screenshot_timer_handle->start(3000, 0); eloop->timer_handle(3000, 0, [this]() { screenshot_handler(); });
} }
m_notifier = eloop->async_handle([this]() { notifier_handler(); });
m_eloop_ready.store(true); m_eloop_ready.store(true);
/* /*