polybar/include/components/eventloop.hpp

155 lines
3.0 KiB
C++

#pragma once
#include <moodycamel/blockingconcurrentqueue.h>
#include <chrono>
#include "common.hpp"
#include "components/logger.hpp"
#include "modules/meta/base.hpp"
POLYBAR_NS
using module_t = unique_ptr<modules::module_interface>;
using modulemap_t = map<alignment, vector<module_t>>;
enum class event_type : uint8_t {
NONE = 0,
UPDATE,
CHECK,
INPUT,
QUIT,
};
struct event {
uint8_t type{0};
char data[256]{'\0'};
};
class eventloop {
public:
/**
* Queue type
*/
using entry_t = event;
using queue_t = moodycamel::BlockingConcurrentQueue<entry_t>;
using duration_t = chrono::duration<double, std::milli>;
explicit eventloop(const logger& logger, const config& config);
~eventloop() noexcept;
void start();
void wait();
void stop();
bool enqueue(const entry_t& entry);
bool enqueue_delayed(const entry_t& entry);
void set_update_cb(callback<>&& cb);
void set_input_db(callback<string>&& cb);
void add_module(const alignment pos, module_t&& module);
const modulemap_t& modules() const;
size_t module_count() const;
protected:
void dispatch_modules();
void dispatch_queue_worker();
void dispatch_delayed_worker();
inline bool match_event(entry_t evt, event_type type);
inline bool compare_events(entry_t evt, entry_t evt2);
void forward_event(entry_t evt);
void on_update();
void on_input(char* input);
void on_check();
void on_quit();
private:
const logger& m_log;
const config& m_conf;
/**
* @brief Event queue
*/
queue_t m_queue;
/**
* @brief Loaded modules
*/
modulemap_t m_modules;
/**
* @brief Lock used when accessing the module map
*/
std::mutex m_modulelock;
/**
* @brief Flag to indicate current run state
*/
stateflag m_running;
/**
* @brief Callback fired when receiving UPDATE events
*/
callback<> m_update_cb;
/**
* @brief Callback fired for unprocessed INPUT events
*/
callback<string> m_unrecognized_input_cb;
/**
* @brief Time to wait for subsequent events
*/
duration_t m_swallow_time{0ms};
/**
* @brief Maximum amount of subsequent events to swallow within timeframe
*/
size_t m_swallow_limit{0};
/**
* @brief Time until releasing the lock on the delayed enqueue channel
*/
duration_t m_delayed_time;
/**
* @brief Lock used to control the condition variable
*/
std::mutex m_delayed_lock;
/**
* @brief Condition variable used to manage notifications for delayed enqueues
*/
std::condition_variable m_delayed_cond;
/**
* @brief Pending event on the delayed channel
*/
entry_t m_delayed_entry{0};
/**
* @brief Queue worker thread
*/
thread m_queue_thread;
/**
* @brief Delayed notifier thread
*/
thread m_delayed_thread;
};
namespace {
/**
* Configure injection module
*/
template <typename T = unique_ptr<eventloop>>
di::injector<T> configure_eventloop() {
return di::make_injector(configure_logger(), configure_config());
}
}
POLYBAR_NS_END