From 56779a5902317ad8e35e5cec520bdc463b3ff896 Mon Sep 17 00:00:00 2001 From: Patrick Ziegler Date: Sat, 15 Oct 2022 23:21:40 +0200 Subject: [PATCH] Make the event loop return shared_ptrs (#2842) * Return shared_ptr from eventloop * Add -Wdeprecated-copy-dtor warning Produces a warning if classes don't have explicit copy operations if they have a user-defined constructor. This helps us stick to the rule of 5 (kinda, no warnings for missing move operators). * Clean up eventloop * Fix compiler warnings * Fix fs_event_handle_t name --- .clang-tidy | 4 +- .gitignore | 3 + cmake/cxx.cmake | 2 +- include/components/bar.hpp | 8 +- include/components/controller.hpp | 4 +- include/components/eventloop.hpp | 155 ++++++++++++++---------- include/errors.hpp | 4 +- include/ipc/ipc.hpp | 6 +- include/modules/meta/inotify_module.hpp | 9 +- include/utils/inotify.hpp | 8 +- include/utils/mixins.hpp | 8 +- include/x11/connection.hpp | 2 - src/components/bar.cpp | 14 +-- src/components/controller.cpp | 26 ++-- src/components/eventloop.cpp | 112 ++++++++++++++--- src/ipc/ipc.cpp | 22 ++-- src/polybar-msg.cpp | 6 +- src/utils/inotify.cpp | 17 ++- 18 files changed, 266 insertions(+), 144 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index b558598b..d28a1322 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -16,6 +16,7 @@ Checks: ' -modernize-raw-string-literal, -modernize-use-bool-literals, -modernize-use-trailing-return-type, + -readability-identifier-length, -readability-implicit-bool-cast, -readability-else-after-return, -readability-named-parameter, @@ -26,7 +27,8 @@ Checks: ' -cppcoreguidelines-pro-type-reinterpret-cast, -cppcoreguidelines-pro-type-union-access, -cppcoreguidelines-pro-type-cstyle-cast, - -cppcoreguidelines-pro-bounds-constant-array-index + -cppcoreguidelines-pro-bounds-constant-array-index, + -cppcoreguidelines-owning-memory, ' CheckOptions: diff --git a/.gitignore b/.gitignore index e25c24ce..ae63d1bc 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,7 @@ .tags *.user +# clangd +/.cache + polybar-*.tar diff --git a/cmake/cxx.cmake b/cmake/cxx.cmake index ecc0194f..9e4aa08f 100644 --- a/cmake/cxx.cmake +++ b/cmake/cxx.cmake @@ -24,7 +24,7 @@ set(THREADS_PREFER_PTHREAD_FLAG ON) set(POLYBAR_FLAGS "" CACHE STRING "C++ compiler flags used for compiling polybar") -list(APPEND cxx_base -Wall -Wextra -Wpedantic) +list(APPEND cxx_base -Wall -Wextra -Wpedantic -Wdeprecated-copy-dtor) list(APPEND cxx_debug -DDEBUG -g2) list(APPEND cxx_minsizerel "") list(APPEND cxx_sanitize -O0 -g -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls) diff --git a/include/components/bar.hpp b/include/components/bar.hpp index 60331e54..3e5f3f1a 100644 --- a/include/components/bar.hpp +++ b/include/components/bar.hpp @@ -107,10 +107,10 @@ class bar : public xpp::event::sink m_dblclicks; - eventloop::TimerHandle& m_leftclick_timer{m_loop.handle()}; - eventloop::TimerHandle& m_middleclick_timer{m_loop.handle()}; - eventloop::TimerHandle& m_rightclick_timer{m_loop.handle()}; - eventloop::TimerHandle& m_dim_timer{m_loop.handle()}; + eventloop::timer_handle_t m_leftclick_timer{m_loop.handle()}; + eventloop::timer_handle_t m_middleclick_timer{m_loop.handle()}; + eventloop::timer_handle_t m_rightclick_timer{m_loop.handle()}; + eventloop::timer_handle_t m_dim_timer{m_loop.handle()}; bool m_visible{true}; }; diff --git a/include/components/controller.hpp b/include/components/controller.hpp index cb0a72e7..6ddb661b 100644 --- a/include/components/controller.hpp +++ b/include/components/controller.hpp @@ -55,7 +55,7 @@ class controller : public signal_receiver([this]() { notifier_handler(); })}; + eventloop::async_handle_t m_notifier{m_loop.handle([this]() { notifier_handler(); })}; /** * Notification data for the controller. diff --git a/include/components/eventloop.hpp b/include/components/eventloop.hpp index 7c1908e2..e5d4eeee 100644 --- a/include/components/eventloop.hpp +++ b/include/components/eventloop.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "common.hpp" #include "components/logger.hpp" @@ -36,12 +37,12 @@ namespace eventloop { get()->data = this; } - Self& leak(std::unique_ptr h) { + void leak(std::shared_ptr h) { lifetime_extender = std::move(h); - return *lifetime_extender; } void unleak() { + reset_callbacks(); lifetime_extender.reset(); } @@ -73,6 +74,15 @@ namespace eventloop { } protected: + ~Handle() = default; + + /** + * Resets all callbacks stored in the handle as part of closing the handle. + * + * This releases any lambda captures, breaking possible cyclic dependencies in shared_ptr. + */ + virtual void reset_callbacks() = 0; + /** * Generic callback function that can be used for all uv handle callbacks. * @@ -128,14 +138,14 @@ namespace eventloop { uv_loop_t* uv_loop; /** - * The handle stores the unique_ptr to itself so that it effectively leaks memory. + * The handle stores the shared_ptr to itself so that it effectively leaks memory. * * This saves us from having to guarantee that the handle's lifetime extends to at least after it is closed. * * Once the handle is closed, either explicitly or by walking all handles when the loop shuts down, this reference * is reset and the object is explicitly destroyed. */ - std::unique_ptr lifetime_extender; + std::shared_ptr lifetime_extender; }; struct ErrorEvent { @@ -144,54 +154,32 @@ namespace eventloop { using cb_error = cb_event; - class WriteRequest : public non_copyable_mixin { + class WriteRequest : public non_copyable_mixin, public non_movable_mixin { public: using cb_write = cb_void; - WriteRequest(cb_write user_cb, cb_error err_cb) : write_callback(user_cb), write_err_cb(err_cb) { - get()->data = this; - }; + WriteRequest(cb_write&& user_cb, cb_error&& err_cb); - static WriteRequest& create(cb_write user_cb, cb_error err_cb) { - auto r = std::make_unique(user_cb, err_cb); - return r->leak(std::move(r)); - }; + static WriteRequest& create(cb_write&& user_cb, cb_error&& err_cb); - uv_write_t* get() { - return &req; - } + uv_write_t* get(); /** * Trigger the write callback. * * After that, this object is destroyed. */ - void trigger(int status) { - if (status < 0) { - if (write_err_cb) { - write_err_cb(ErrorEvent{status}); - } - } else { - if (write_callback) { - write_callback(); - } - } - - unleak(); - } + void trigger(int status); protected: - WriteRequest& leak(std::unique_ptr h) { - lifetime_extender = std::move(h); - return *lifetime_extender; - } + WriteRequest& leak(std::unique_ptr h); - void unleak() { - lifetime_extender.reset(); - } + void unleak(); + + void reset_callbacks(); private: - uv_write_t req; + uv_write_t req{}; cb_write write_callback; cb_error write_err_cb; @@ -208,13 +196,16 @@ namespace eventloop { int signum; }; - class SignalHandle : public Handle { + class SignalHandle final : public Handle { public: using Handle::Handle; using cb = cb_event; void init(); - void start(int signum, cb user_cb); + void start(int signum, cb&& user_cb); + + protected: + void reset_callbacks() override; private: cb callback; @@ -224,15 +215,18 @@ namespace eventloop { uv_poll_event event; }; - class PollHandle : public Handle { + class PollHandle final : public Handle { public: using Handle::Handle; using cb = cb_event; void init(int fd); - void start(int events, cb user_cb, cb_error err_cb); + void start(int events, cb&& user_cb, cb_error&& err_cb); static void poll_callback(uv_poll_t*, int status, int events); + protected: + void reset_callbacks() override; + private: cb callback; cb_error err_cb; @@ -243,41 +237,50 @@ namespace eventloop { uv_fs_event event; }; - class FSEventHandle : public Handle { + class FSEventHandle final : public Handle { public: using Handle::Handle; using cb = cb_event; void init(); - void start(const string& path, int flags, cb user_cb, cb_error err_cb); + void start(const string& path, int flags, cb&& user_cb, cb_error&& err_cb); static void fs_event_callback(uv_fs_event_t*, const char* path, int events, int status); + protected: + void reset_callbacks() override; + private: cb callback; cb_error err_cb; }; - class TimerHandle : public Handle { + class TimerHandle final : public Handle { public: using Handle::Handle; using cb = cb_void; void init(); - void start(uint64_t timeout, uint64_t repeat, cb user_cb); + void start(uint64_t timeout, uint64_t repeat, cb&& user_cb); void stop(); + protected: + void reset_callbacks() override; + private: cb callback; }; - class AsyncHandle : public Handle { + class AsyncHandle final : public Handle { public: using Handle::Handle; using cb = cb_void; - void init(cb user_cb); + void init(cb&& user_cb); void send(); + protected: + void reset_callbacks() override; + private: cb callback; }; @@ -295,9 +298,9 @@ namespace eventloop { using cb_read_eof = cb_void; using cb_connection = cb_void; - void listen(int backlog, cb_connection user_cb, cb_error err_cb) { - this->connection_callback = user_cb; - this->connection_err_cb = err_cb; + void listen(int backlog, cb_connection&& user_cb, cb_error&& err_cb) { + this->connection_callback = std::move(user_cb); + this->connection_err_cb = std::move(err_cb); UV(uv_listen, this->template get(), backlog, connection_cb); }; @@ -316,11 +319,11 @@ namespace eventloop { UV(uv_accept, this->template get(), client.template get()); } - void read_start(cb_read fun, cb_void eof_cb, cb_error err_cb) { - this->read_callback = fun; - this->read_eof_cb = eof_cb; - this->read_err_cb = err_cb; - UV(uv_read_start, this->template get(), &this->alloc_callback, read_cb); + void read_start(cb_read &&fun, cb_void&& eof_cb, cb_error&& err_cb) { + this->read_callback = std::move(fun); + this->read_eof_cb = std::move(eof_cb); + this->read_err_cb = std::move(err_cb); + UV(uv_read_start, this->template get(), &this->alloc_callback, &read_cb); }; static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { @@ -340,8 +343,8 @@ namespace eventloop { } }; - void write(const vector& data, WriteRequest::cb_write user_cb = {}, cb_error err_cb = {}) { - WriteRequest& req = WriteRequest::create(user_cb, err_cb); + void write(const vector& data, WriteRequest::cb_write&& user_cb = {}, cb_error&& err_cb = {}) { + WriteRequest& req = WriteRequest::create(std::move(user_cb), std::move(err_cb)); uv_buf_t buf{(char*)data.data(), data.size()}; @@ -349,6 +352,17 @@ namespace eventloop { [](uv_write_t* r, int status) { static_cast(r->data)->trigger(status); }); } + protected: + ~StreamHandle() = default; + + void reset_callbacks() override { + read_callback = nullptr; + read_eof_cb = nullptr; + read_err_cb = nullptr; + connection_callback = nullptr; + connection_err_cb = nullptr; + } + private: /** * Callback for receiving data @@ -371,7 +385,7 @@ namespace eventloop { cb_error connection_err_cb; }; - class PipeHandle : public StreamHandle { + class PipeHandle final : public StreamHandle { public: using StreamHandle::StreamHandle; using cb_connect = cb_void; @@ -381,7 +395,10 @@ namespace eventloop { void bind(const string& path); - void connect(const string& name, cb_connect user_cb, cb_error err_cb); + void connect(const string& name, cb_connect&& user_cb, cb_error&& err_cb); + + protected: + void reset_callbacks() override; private: static void connect_cb(uv_connect_t* req, int status); @@ -390,13 +407,16 @@ namespace eventloop { cb_connect connect_callback; }; - class PrepareHandle : public Handle { + class PrepareHandle final : public Handle { public: using Handle::Handle; using cb = cb_void; void init(); - void start(cb user_cb); + void start(cb&& user_cb); + + protected: + void reset_callbacks() override; private: static void connect_cb(uv_connect_t* req, int status); @@ -404,6 +424,14 @@ namespace eventloop { cb callback; }; + using signal_handle_t = shared_ptr; + using poll_handle_t = shared_ptr; + using fs_event_handle_t = shared_ptr; + using timer_handle_t = shared_ptr; + using async_handle_t = shared_ptr; + using pipe_handle_t = shared_ptr; + using prepare_handle_t = shared_ptr; + class loop : public non_copyable_mixin, public non_movable_mixin { public: loop(); @@ -413,10 +441,11 @@ namespace eventloop { uint64_t now() const; template - H& handle(Args... args) { - auto ptr = make_unique(get()); + shared_ptr handle(Args&&... args) { + auto ptr = make_shared(get()); ptr->init(std::forward(args)...); - return ptr->leak(std::move(ptr)); + ptr->leak(ptr); + return ptr; } uv_loop_t* get() const; diff --git a/include/errors.hpp b/include/errors.hpp index 2ca554bb..654f4459 100644 --- a/include/errors.hpp +++ b/include/errors.hpp @@ -8,14 +8,13 @@ POLYBAR_NS -using std::strerror; using std::exception; using std::runtime_error; +using std::strerror; class application_error : public runtime_error { public: explicit application_error(const string& message, int code = 0) : runtime_error(message), code(code) {} - virtual ~application_error() {} int code{0}; }; @@ -24,7 +23,6 @@ class system_error : public application_error { explicit system_error() : application_error(strerror(errno), errno) {} explicit system_error(const string& message) : application_error(message + " (reason: " + strerror(errno) + ")", errno) {} - virtual ~system_error() {} }; #define DEFINE_CHILD_ERROR(error, parent) \ diff --git a/include/ipc/ipc.hpp b/include/ipc/ipc.hpp index 7e2e0068..fb642ac8 100644 --- a/include/ipc/ipc.hpp +++ b/include/ipc/ipc.hpp @@ -42,14 +42,14 @@ namespace ipc { const logger& m_log; eventloop::loop& m_loop; - eventloop::PipeHandle& socket; + eventloop::pipe_handle_t socket; class connection : public non_copyable_mixin, public non_movable_mixin { public: using cb = std::function&)>; connection(eventloop::loop& loop, cb msg_callback); ~connection(); - eventloop::PipeHandle& client_pipe; + eventloop::pipe_handle_t client_pipe; decoder dec; }; @@ -79,7 +79,7 @@ namespace ipc { struct fifo { fifo(eventloop::loop& loop, ipc& ipc, const string& path); ~fifo(); - eventloop::PipeHandle& pipe_handle; + eventloop::pipe_handle_t pipe_handle; }; unique_ptr ipc_pipe; diff --git a/include/modules/meta/inotify_module.hpp b/include/modules/meta/inotify_module.hpp index 06b165f7..f335ae91 100644 --- a/include/modules/meta/inotify_module.hpp +++ b/include/modules/meta/inotify_module.hpp @@ -55,7 +55,6 @@ namespace modules { watches.back().attach(w.second); } } catch (const system_error& e) { - watches.clear(); this->m_log.err("%s: Error while creating inotify watch (what: %s)", this->name(), e.what()); CAST_MOD(Impl)->sleep(0.1s); return; @@ -67,11 +66,6 @@ namespace modules { if (w.poll(1000 / watches.size())) { auto event = w.get_event(); - - for (auto&& w : watches) { - w.remove(true); - } - if (CAST_MOD(Impl)->on_event(event)) { CAST_MOD(Impl)->broadcast(); } @@ -79,8 +73,9 @@ namespace modules { return; } - if (!this->running()) + if (!this->running()) { break; +} } CAST_MOD(Impl)->idle(); } diff --git a/include/utils/inotify.hpp b/include/utils/inotify.hpp index e2db3d0a..8722b606 100644 --- a/include/utils/inotify.hpp +++ b/include/utils/inotify.hpp @@ -6,6 +6,7 @@ #include #include "common.hpp" +#include "utils/mixins.hpp" POLYBAR_NS @@ -18,16 +19,19 @@ struct inotify_event { int mask = 0; }; -class inotify_watch { +class inotify_watch : public non_copyable_mixin { public: explicit inotify_watch(string path); ~inotify_watch(); + inotify_watch(inotify_watch&& other) noexcept; + inotify_watch& operator=(inotify_watch&& other) noexcept; + void attach(int mask = IN_MODIFY); void remove(bool force = false); bool poll(int wait_ms = 1000) const; inotify_event get_event() const; - const string path() const; + string path() const; int get_file_descriptor() const; protected: diff --git a/include/utils/mixins.hpp b/include/utils/mixins.hpp index f3d82590..1df342d2 100644 --- a/include/utils/mixins.hpp +++ b/include/utils/mixins.hpp @@ -13,8 +13,8 @@ class non_copyable_mixin { non_copyable_mixin& operator=(const non_copyable_mixin&) = delete; protected: - non_copyable_mixin() {} - ~non_copyable_mixin() {} + non_copyable_mixin() = default; + ~non_copyable_mixin() = default; }; /** @@ -26,8 +26,8 @@ class non_movable_mixin { non_movable_mixin& operator=(non_movable_mixin&&) = delete; protected: - non_movable_mixin() {} - ~non_movable_mixin() {} + non_movable_mixin() = default; + ~non_movable_mixin() = default; }; POLYBAR_NS_END diff --git a/include/x11/connection.hpp b/include/x11/connection.hpp index 4147920f..d8eb22a8 100644 --- a/include/x11/connection.hpp +++ b/include/x11/connection.hpp @@ -43,8 +43,6 @@ namespace detail { m_root_window = screen_of_display(default_screen())->root; } - virtual ~connection_base() {} - void operator()(const shared_ptr& error) const override { check(error); } diff --git a/src/components/bar.cpp b/src/components/bar.cpp index a41bb9bf..9186d31d 100644 --- a/src/components/bar.cpp +++ b/src/components/bar.cpp @@ -692,12 +692,12 @@ void bar::handle(const evt::destroy_notify& evt) { */ void bar::handle(const evt::enter_notify&) { if (m_opts.dimmed) { - m_dim_timer.start(25, 0, [this]() { + m_dim_timer->start(25, 0, [this]() { m_opts.dimmed = false; m_sig.emit(dim_window{1.0}); }); - } else if (m_dim_timer.is_active()) { - m_dim_timer.stop(); + } else if (m_dim_timer->is_active()) { + m_dim_timer->stop(); } } @@ -711,7 +711,7 @@ void bar::handle(const evt::leave_notify&) { // Only trigger dimming, if the dim-value is not fully opaque. if (m_opts.dimvalue < 1.0) { if (!m_opts.dimmed) { - m_dim_timer.start(3000, 0, [this]() { + m_dim_timer->start(3000, 0, [this]() { m_opts.dimmed = true; m_sig.emit(dim_window{double(m_opts.dimvalue)}); }); @@ -820,11 +820,11 @@ void bar::handle(const evt::button_press& evt) { if (!has_dblclick) { trigger_click(btn, pos); } else if (btn == mousebtn::LEFT) { - check_double(m_leftclick_timer, btn, pos); + check_double(*m_leftclick_timer, btn, pos); } else if (btn == mousebtn::MIDDLE) { - check_double(m_middleclick_timer, btn, pos); + check_double(*m_middleclick_timer, btn, pos); } else if (btn == mousebtn::RIGHT) { - check_double(m_rightclick_timer, btn, pos); + check_double(*m_rightclick_timer, btn, pos); } else { trigger_click(btn, pos); } diff --git a/src/components/controller.cpp b/src/components/controller.cpp index 9fff6adb..31721191 100644 --- a/src/components/controller.cpp +++ b/src/components/controller.cpp @@ -154,7 +154,7 @@ void controller::trigger_update(bool force) { } void controller::trigger_notification() { - m_notifier.send(); + m_notifier->send(); } void controller::stop(bool reload) { @@ -196,12 +196,12 @@ void controller::signal_handler(int signum) { } void controller::create_config_watcher(const string& filename) { - auto& fs_event_handler = m_loop.handle(); - fs_event_handler.start( + auto fs_event_handle = m_loop.handle(); + fs_event_handle->start( filename, 0, [this](const auto& e) { confwatch_handler(e.path); }, - [this, &fs_event_handler](const auto& e) { + [this, &handle = *fs_event_handle](const auto& e) { m_log.err("libuv error while watching included file for changes: %s", uv_strerror(e.status)); - fs_event_handler.close(); + handle.close(); }); } @@ -247,16 +247,16 @@ void controller::read_events(bool confwatch) { m_log.info("Entering event loop (thread-id=%lu)", this_thread::get_id()); try { - auto& x_poll_handle = m_loop.handle(m_connection.get_file_descriptor()); - x_poll_handle.start( + auto x_poll_handle = m_loop.handle(m_connection.get_file_descriptor()); + x_poll_handle->start( UV_READABLE, [this](const auto&) { conn_cb(); }, [this](const auto& e) { m_log.err("libuv error while polling X connection: "s + uv_strerror(e.status)); stop(false); }); - auto& x_prepare_handle = m_loop.handle(); - x_prepare_handle.start([this]() { + auto x_prepare_handle = m_loop.handle(); + x_prepare_handle->start([this]() { /* * We have to also handle events in the prepare handle (which runs right * before polling for IO) to process any already queued X events which @@ -267,8 +267,8 @@ void controller::read_events(bool confwatch) { }); for (auto s : {SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGALRM}) { - auto& signal_handle = m_loop.handle(); - signal_handle.start(s, [this](const auto& e) { signal_handler(e.signum); }); + auto signal_handle = m_loop.handle(); + signal_handle->start(s, [this](const auto& e) { signal_handler(e.signum); }); } if (confwatch) { @@ -281,8 +281,8 @@ void controller::read_events(bool confwatch) { if (!m_snapshot_dst.empty()) { // Trigger a single screenshot after 3 seconds - auto& timer_handle = m_loop.handle(); - timer_handle.start(3000, 0, [this]() { screenshot_handler(); }); + auto timer_handle = m_loop.handle(); + timer_handle->start(3000, 0, [this]() { screenshot_handler(); }); } if (!m_writeback) { diff --git a/src/components/eventloop.cpp b/src/components/eventloop.cpp index e48f7029..f144d93f 100644 --- a/src/components/eventloop.cpp +++ b/src/components/eventloop.cpp @@ -1,6 +1,7 @@ #include "components/eventloop.hpp" #include +#include #include "errors.hpp" @@ -46,15 +47,64 @@ namespace eventloop { } } + // WriteRequest {{{ + WriteRequest::WriteRequest(cb_write&& user_cb, cb_error&& err_cb) + : write_callback(std::move(user_cb)), write_err_cb(std::move(err_cb)) { + get()->data = this; + } + + WriteRequest& WriteRequest::create(cb_write&& user_cb, cb_error&& err_cb) { + auto r = std::make_unique(std::move(user_cb), std::move(err_cb)); + return r->leak(std::move(r)); + } + + uv_write_t* WriteRequest::get() { + return &req; + } + + void WriteRequest::trigger(int status) { + if (status < 0) { + if (write_err_cb) { + write_err_cb(ErrorEvent{status}); + } + } else { + if (write_callback) { + write_callback(); + } + } + + unleak(); + } + + WriteRequest& WriteRequest::leak(std::unique_ptr h) { + lifetime_extender = std::move(h); + return *lifetime_extender; + } + + void WriteRequest::unleak() { + reset_callbacks(); + lifetime_extender.reset(); + } + + void WriteRequest::reset_callbacks() { + write_callback = nullptr; + write_err_cb = nullptr; + } + // }}} + // SignalHandle {{{ void SignalHandle::init() { UV(uv_signal_init, loop(), get()); } - void SignalHandle::start(int signum, cb user_cb) { - this->callback = user_cb; + void SignalHandle::start(int signum, cb&& user_cb) { + this->callback = std::move(user_cb); UV(uv_signal_start, get(), event_cb, signum); } + + void SignalHandle::reset_callbacks() { + callback = nullptr; + } // }}} // PollHandle {{{ @@ -62,9 +112,9 @@ namespace eventloop { UV(uv_poll_init, loop(), get(), fd); } - void PollHandle::start(int events, cb user_cb, cb_error err_cb) { - this->callback = user_cb; - this->err_cb = err_cb; + void PollHandle::start(int events, cb&& user_cb, cb_error&& err_cb) { + this->callback = std::move(user_cb); + this->err_cb = std::move(err_cb); UV(uv_poll_start, get(), events, &poll_callback); } @@ -77,6 +127,11 @@ namespace eventloop { self.callback(PollEvent{(uv_poll_event)events}); } + + void PollHandle::reset_callbacks() { + callback = nullptr; + err_cb = nullptr; + } // }}} // FSEventHandle {{{ @@ -84,9 +139,9 @@ namespace eventloop { UV(uv_fs_event_init, loop(), get()); } - void FSEventHandle::start(const string& path, int flags, cb user_cb, cb_error err_cb) { - this->callback = user_cb; - this->err_cb = err_cb; + void FSEventHandle::start(const string& path, int flags, cb&& user_cb, cb_error&& err_cb) { + this->callback = std::move(user_cb); + this->err_cb = std::move(err_cb); UV(uv_fs_event_start, get(), fs_event_callback, path.c_str(), flags); } @@ -100,6 +155,10 @@ namespace eventloop { self.callback(FSEvent{path, (uv_fs_event)events}); } + void FSEventHandle::reset_callbacks() { + callback = nullptr; + err_cb = nullptr; + } // }}} // PipeHandle {{{ @@ -115,9 +174,9 @@ namespace eventloop { UV(uv_pipe_bind, get(), path.c_str()); } - void PipeHandle::connect(const string& name, cb_connect user_cb, cb_error err_cb) { - this->connect_callback = user_cb; - this->connect_err_cb = err_cb; + void PipeHandle::connect(const string& name, cb_connect&& user_cb, cb_error&& err_cb) { + this->connect_callback = std::move(user_cb); + this->connect_err_cb = std::move(err_cb); uv_pipe_connect(new uv_connect_t(), get(), name.c_str(), connect_cb); } @@ -132,6 +191,12 @@ namespace eventloop { delete req; } + + void PipeHandle::reset_callbacks() { + StreamHandle::reset_callbacks(); + connect_callback = nullptr; + connect_err_cb = nullptr; + } // }}} // TimerHandle {{{ @@ -139,25 +204,33 @@ namespace eventloop { UV(uv_timer_init, loop(), get()); } - void TimerHandle::start(uint64_t timeout, uint64_t repeat, cb user_cb) { - this->callback = user_cb; + void TimerHandle::start(uint64_t timeout, uint64_t repeat, cb&& user_cb) { + this->callback = std::move(user_cb); UV(uv_timer_start, get(), void_event_cb<&TimerHandle::callback>, timeout, repeat); } void TimerHandle::stop() { UV(uv_timer_stop, get()); } + + void TimerHandle::reset_callbacks() { + callback = nullptr; + } // }}} // AsyncHandle {{{ - void AsyncHandle::init(cb user_cb) { - this->callback = user_cb; + void AsyncHandle::init(cb&& user_cb) { + this->callback = std::move(user_cb); UV(uv_async_init, loop(), get(), void_event_cb<&AsyncHandle::callback>); } void AsyncHandle::send() { UV(uv_async_send, get()); } + + void AsyncHandle::reset_callbacks() { + callback = nullptr; + } // }}} // PrepareHandle {{{ @@ -165,10 +238,14 @@ namespace eventloop { UV(uv_prepare_init, loop(), get()); } - void PrepareHandle::start(cb user_cb) { - this->callback = user_cb; + void PrepareHandle::start(cb&& user_cb) { + this->callback = std::move(user_cb); UV(uv_prepare_start, get(), void_event_cb<&PrepareHandle::callback>); } + + void PrepareHandle::reset_callbacks() { + callback = nullptr; + } // }}} // eventloop {{{ @@ -227,3 +304,4 @@ namespace eventloop { } // namespace eventloop POLYBAR_NS_END + diff --git a/src/ipc/ipc.cpp b/src/ipc/ipc.cpp index 66506f15..df75490c 100644 --- a/src/ipc/ipc.cpp +++ b/src/ipc/ipc.cpp @@ -57,12 +57,12 @@ namespace ipc { m_log.info("Opening ipc socket at '%s'", sock_path); m_log.notice("Listening for IPC messages (PID: %d)", getpid()); - socket.bind(sock_path); - socket.listen( + socket->bind(sock_path); + socket->listen( 4, [this]() { on_connection(); }, [this](const auto& e) { m_log.err("libuv error while listening to IPC socket: %s", uv_strerror(e.status)); - socket.close(); + socket->close(); }); } @@ -124,7 +124,7 @@ namespace ipc { } else { response = encode(TYPE_ERR, "Unrecognized IPC message type " + to_string(type)); } - c.client_pipe.write( + c.client_pipe->write( response, [this, &c]() { remove_client(c); }, [this, &c](const auto& e) { m_log.err("ipc: libuv error while writing to IPC socket: %s", uv_strerror(e.status)); @@ -133,16 +133,16 @@ namespace ipc { }); auto& c = *connection; - socket.accept(c.client_pipe); + socket->accept(*c.client_pipe); - c.client_pipe.read_start( + c.client_pipe->read_start( [this, &c](const auto& e) { try { c.dec.on_read((const uint8_t*)e.data, e.len); } catch (const decoder::error& e) { m_log.err("ipc: Failed to decode IPC message (reason: %s)", e.what()); - c.client_pipe.write( + c.client_pipe->write( encode(TYPE_ERR, "Invalid binary message format: "s + e.what()), [this, &c]() { remove_client(c); }, [this, &c](const auto& e) { m_log.err("ipc: libuv error while writing to IPC socket: %s", uv_strerror(e.status)); @@ -171,7 +171,7 @@ namespace ipc { }) {} ipc::connection::~connection() { - client_pipe.close(); + client_pipe->close(); } ipc::fifo::fifo(loop& loop, ipc& ipc, const string& path) : pipe_handle(loop.handle()) { @@ -180,8 +180,8 @@ namespace ipc { throw system_error("Failed to open pipe '" + path + "'"); } - pipe_handle.open(fd); - pipe_handle.read_start([&ipc](const auto& e) mutable { ipc.receive_data(string(e.data, e.len)); }, + pipe_handle->open(fd); + pipe_handle->read_start([&ipc](const auto& e) mutable { ipc.receive_data(string(e.data, e.len)); }, [&ipc]() { ipc.receive_eof(); }, [&ipc](const auto& e) mutable { ipc.m_log.err("libuv error while listening to IPC channel: %s", uv_strerror(e.status)); @@ -190,7 +190,7 @@ namespace ipc { } ipc::fifo::~fifo() { - pipe_handle.close(); + pipe_handle->close(); } /** diff --git a/src/polybar-msg.cpp b/src/polybar-msg.cpp index f1a9c127..7cc5d81a 100644 --- a/src/polybar-msg.cpp +++ b/src/polybar-msg.cpp @@ -262,11 +262,11 @@ int run(int argc, char** argv) { */ int idx = decoders.size() - 1; - auto& conn = loop.handle(); - conn.connect( + auto conn = loop.handle(); + conn->connect( channel, [&conn, &decoders, pid, type, payload, channel, idx]() { - on_connection(conn, decoders[idx], pid, type, payload); + on_connection(*conn, decoders[idx], pid, type, payload); }, [&](const auto& e) { fprintf(stderr, "%s: Failed to connect to '%s' (err: '%s')\n", exec, channel.c_str(), uv_strerror(e.status)); diff --git a/src/utils/inotify.cpp b/src/utils/inotify.cpp index ccd75a9e..6445149b 100644 --- a/src/utils/inotify.cpp +++ b/src/utils/inotify.cpp @@ -24,6 +24,21 @@ inotify_watch::~inotify_watch() { } } +inotify_watch::inotify_watch(inotify_watch&& other) noexcept { + std::swap(m_path, other.m_path); + std::swap(m_wd, other.m_wd); + std::swap(m_fd, other.m_fd); + std::swap(m_mask, other.m_mask); +} + +inotify_watch& inotify_watch::operator=(inotify_watch&& other) noexcept { + std::swap(m_path, other.m_path); + std::swap(m_wd, other.m_wd); + std::swap(m_fd, other.m_fd); + std::swap(m_mask, other.m_mask); + return *this; +} + /** * Attach inotify watch */ @@ -101,7 +116,7 @@ inotify_event inotify_watch::get_event() const { /** * Get watch file path */ -const string inotify_watch::path() const { +string inotify_watch::path() const { return m_path; }