#pragma once #include #include #include "common.hpp" #include "components/logger.hpp" POLYBAR_NS /** * Runs any libuv function with an integer error code return value and throws an * exception on error. */ #define UV(fun, ...) \ do { \ int res = fun(__VA_ARGS__); \ if (res < 0) { \ throw std::runtime_error( \ __FILE__ ":"s + std::to_string(__LINE__) + ": libuv error for '" #fun "': "s + uv_strerror(res)); \ } \ } while (0); void close_callback(uv_handle_t*); /** * \tparam H Type of the handle * \tparam I Type of the handle passed to the callback. Often the same as H, but not always (e.g. uv_read_start) */ template struct UVHandleGeneric { UVHandleGeneric(function fun) { handle = new H; handle->data = this; this->func = fun; } ~UVHandleGeneric() { close(); } uv_loop_t* loop() const { return handle->loop; } void close() { if (!is_closing()) { uv_close((uv_handle_t*)handle, close_callback); } } bool is_closing() { return !handle || uv_is_closing((uv_handle_t*)handle); } bool is_active() { return uv_is_active((uv_handle_t*)handle) != 0; } void cleanup_resources() { if (handle) { delete handle; handle = nullptr; } } static void callback(I* context, Args... args) { const auto unpackedThis = static_cast(context->data); return unpackedThis->func(std::forward(args)...); } H* handle{nullptr}; function func; }; template struct UVHandle : public UVHandleGeneric { UVHandle(function fun) : UVHandleGeneric(fun) {} }; struct SignalHandle : public UVHandle { SignalHandle(uv_loop_t* loop, function fun); void start(int signum); }; struct PollHandle : public UVHandle { PollHandle(uv_loop_t* loop, int fd, function fun, function err_cb); void start(int events); void poll_cb(int status, int events); function func; function err_cb; }; struct FSEventHandle : public UVHandle { FSEventHandle(uv_loop_t* loop, function fun, function err_cb); void start(const string& path); void fs_event_cb(const char* path, int events, int status); function func; function err_cb; }; struct PipeHandle : public UVHandleGeneric { PipeHandle(uv_loop_t* loop, const string& path, function fun, function eof_cb, function err_cb); void start(); void read_cb(ssize_t nread, const uv_buf_t* buf); function func; function eof_cb; function err_cb; int fd; string path; }; struct TimerHandle : public UVHandle { TimerHandle(uv_loop_t* loop, function fun); void start(uint64_t timeout, uint64_t repeat, function new_cb = function(nullptr)); void stop(); }; struct AsyncHandle : public UVHandle { AsyncHandle(uv_loop_t* loop, function fun); void send(); }; using SignalHandle_t = std::unique_ptr; using PollHandle_t = std::unique_ptr; using FSEventHandle_t = std::unique_ptr; using PipeHandle_t = std::unique_ptr; // shared_ptr because we also return the pointer in order to call methods on it using TimerHandle_t = std::shared_ptr; using AsyncHandle_t = std::shared_ptr; class eventloop { public: eventloop(); ~eventloop(); void run(); void stop(); void signal_handle(int signum, function fun); void poll_handle(int events, int fd, function fun, function err_cb); void fs_event_handle(const string& path, function fun, function err_cb); void pipe_handle( const string& path, function fun, function eof_cb, function err_cb); TimerHandle_t timer_handle(function fun); AsyncHandle_t async_handle(function fun); protected: uv_loop_t* get() const; private: std::unique_ptr m_loop{nullptr}; vector m_sig_handles; vector m_poll_handles; vector m_fs_event_handles; vector m_pipe_handles; vector m_timer_handles; vector m_async_handles; }; POLYBAR_NS_END