polybar/include/components/eventloop.hpp

166 lines
5.2 KiB
C++
Raw Normal View History

2021-02-20 20:26:45 +00:00
#pragma once
#include <uv.h>
#include <stdexcept>
2021-02-20 20:26:45 +00:00
#include "common.hpp"
2021-09-11 09:46:37 +00:00
#include "components/logger.hpp"
2021-02-20 20:26:45 +00:00
POLYBAR_NS
/**
* Runs any libuv function with an integer error code return value and throws an
* exception on error.
*/
2021-09-12 13:42:30 +00:00
#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)); \
} \
2021-09-11 09:46:37 +00:00
} while (0);
2021-09-12 20:28:27 +00:00
void close_callback(uv_handle_t*);
2021-09-12 13:42:30 +00:00
/**
* \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)
*/
2021-09-11 09:46:50 +00:00
template <typename H, typename I, typename... Args>
struct UVHandleGeneric {
2021-09-13 17:19:39 +00:00
UVHandleGeneric(function<void(Args...)> fun) {
2021-09-12 20:28:27 +00:00
handle = new H;
handle->data = this;
this->func = fun;
}
~UVHandleGeneric() {
close();
}
2021-09-13 17:56:24 +00:00
uv_loop_t* loop() const {
return handle->loop;
}
void close() {
if (!is_closing()) {
2021-09-12 20:28:27 +00:00
uv_close((uv_handle_t*)handle, close_callback);
}
2021-03-10 23:36:03 +00:00
}
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() {
2021-09-12 20:28:27 +00:00
if (handle) {
delete handle;
handle = nullptr;
}
}
static void callback(I* context, Args... args) {
const auto unpackedThis = static_cast<const UVHandleGeneric*>(context->data);
return unpackedThis->func(std::forward<Args>(args)...);
}
H* handle{nullptr};
2021-09-13 17:19:39 +00:00
function<void(Args...)> func;
2021-09-11 09:46:50 +00:00
};
template <typename H, typename... Args>
struct UVHandle : public UVHandleGeneric<H, H, Args...> {
2021-09-13 17:19:39 +00:00
UVHandle(function<void(Args...)> fun) : UVHandleGeneric<H, H, Args...>(fun) {}
2021-03-10 23:36:03 +00:00
};
struct SignalHandle : public UVHandle<uv_signal_t, int> {
2021-09-13 17:19:39 +00:00
SignalHandle(uv_loop_t* loop, function<void(int)> fun);
2021-09-12 20:28:27 +00:00
void start(int signum);
2021-03-10 23:36:03 +00:00
};
2021-03-10 23:36:03 +00:00
struct PollHandle : public UVHandle<uv_poll_t, int, int> {
2021-09-13 17:19:39 +00:00
PollHandle(uv_loop_t* loop, int fd, function<void(uv_poll_event)> fun, function<void(int)> err_cb);
2021-09-12 20:28:27 +00:00
void start(int events);
void poll_cb(int status, int events);
2021-09-13 17:19:39 +00:00
function<void(uv_poll_event)> func;
function<void(int)> err_cb;
2021-03-10 23:54:24 +00:00
};
struct FSEventHandle : public UVHandle<uv_fs_event_t, const char*, int, int> {
2021-09-13 17:19:39 +00:00
FSEventHandle(uv_loop_t* loop, function<void(const char*, uv_fs_event)> fun, function<void(int)> err_cb);
2021-09-12 20:28:27 +00:00
void start(const string& path);
void fs_event_cb(const char* path, int events, int status);
2021-09-13 17:19:39 +00:00
function<void(const char*, uv_fs_event)> func;
function<void(int)> err_cb;
};
2021-09-11 09:46:50 +00:00
struct PipeHandle : public UVHandleGeneric<uv_pipe_t, uv_stream_t, ssize_t, const uv_buf_t*> {
2021-09-13 17:56:24 +00:00
PipeHandle(uv_loop_t* loop, const string& path, function<void(const string)> fun, function<void(void)> eof_cb,
function<void(int)> err_cb);
void start();
2021-09-12 20:28:27 +00:00
void read_cb(ssize_t nread, const uv_buf_t* buf);
2021-09-12 13:42:30 +00:00
2021-09-13 17:19:39 +00:00
function<void(const string)> func;
function<void(void)> eof_cb;
function<void(int)> err_cb;
2021-09-12 13:42:30 +00:00
int fd;
2021-09-13 17:56:24 +00:00
string path;
2021-09-11 09:46:50 +00:00
};
2021-09-12 13:53:14 +00:00
struct TimerHandle : public UVHandle<uv_timer_t> {
2021-09-13 17:19:39 +00:00
TimerHandle(uv_loop_t* loop, function<void(void)> fun);
void start(uint64_t timeout, uint64_t repeat, function<void(void)> new_cb = function<void(void)>(nullptr));
void stop();
2021-09-12 13:53:14 +00:00
};
2021-09-12 13:57:05 +00:00
struct AsyncHandle : public UVHandle<uv_async_t> {
2021-09-13 17:19:39 +00:00
AsyncHandle(uv_loop_t* loop, function<void(void)> fun);
2021-09-12 20:28:27 +00:00
void send();
2021-09-12 13:57:05 +00:00
};
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>;
// shared_ptr because we also return the pointer in order to call methods on it
using TimerHandle_t = std::shared_ptr<TimerHandle>;
using AsyncHandle_t = std::shared_ptr<AsyncHandle>;
2021-02-20 20:26:45 +00:00
class eventloop {
public:
eventloop();
~eventloop();
void run();
void stop();
2021-09-13 17:19:39 +00:00
void signal_handle(int signum, function<void(int)> fun);
void poll_handle(int events, int fd, function<void(uv_poll_event)> fun, function<void(int)> err_cb);
void fs_event_handle(const string& path, function<void(const char*, uv_fs_event)> fun, function<void(int)> err_cb);
2021-09-13 17:56:24 +00:00
void pipe_handle(
const string& path, function<void(const string)> fun, function<void(void)> eof_cb, function<void(int)> err_cb);
TimerHandle_t timer_handle(function<void(void)> fun);
2021-09-13 17:19:39 +00:00
AsyncHandle_t async_handle(function<void(void)> fun);
2021-03-10 23:54:24 +00:00
protected:
2021-09-12 20:28:27 +00:00
uv_loop_t* get() const;
2021-02-20 20:26:45 +00:00
private:
std::unique_ptr<uv_loop_t> m_loop{nullptr};
vector<SignalHandle_t> m_sig_handles;
vector<PollHandle_t> m_poll_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;
2021-02-20 20:26:45 +00:00
};
POLYBAR_NS_END