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;
}