2016-10-29 04:48:51 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <moodycamel/blockingconcurrentqueue.h>
|
2016-11-20 22:04:31 +00:00
|
|
|
#include <chrono>
|
2016-10-29 04:48:51 +00:00
|
|
|
|
|
|
|
#include "common.hpp"
|
|
|
|
#include "components/logger.hpp"
|
2016-11-20 22:04:31 +00:00
|
|
|
#include "modules/meta/base.hpp"
|
2016-10-29 04:48:51 +00:00
|
|
|
|
2016-11-19 05:22:44 +00:00
|
|
|
POLYBAR_NS
|
2016-10-29 04:48:51 +00:00
|
|
|
|
|
|
|
using module_t = unique_ptr<modules::module_interface>;
|
|
|
|
using modulemap_t = map<alignment, vector<module_t>>;
|
|
|
|
|
2016-11-25 20:20:50 +00:00
|
|
|
enum class event_type : uint8_t {
|
|
|
|
NONE = 0,
|
|
|
|
UPDATE,
|
|
|
|
CHECK,
|
|
|
|
INPUT,
|
|
|
|
QUIT,
|
|
|
|
};
|
|
|
|
|
2016-10-29 04:48:51 +00:00
|
|
|
struct event {
|
2016-11-25 20:20:50 +00:00
|
|
|
uint8_t type{0};
|
2016-10-29 04:48:51 +00:00
|
|
|
char data[256]{'\0'};
|
|
|
|
};
|
|
|
|
|
2016-12-01 07:41:49 +00:00
|
|
|
struct quit_event {
|
|
|
|
const uint8_t type{static_cast<uint8_t>(event_type::QUIT)};
|
|
|
|
bool reload{false};
|
|
|
|
};
|
|
|
|
|
2016-12-03 21:54:58 +00:00
|
|
|
struct update_event {
|
|
|
|
const uint8_t type{static_cast<uint8_t>(event_type::UPDATE)};
|
|
|
|
bool force{false};
|
|
|
|
};
|
|
|
|
|
|
|
|
struct input_event {
|
|
|
|
const uint8_t type{static_cast<uint8_t>(event_type::INPUT)};
|
|
|
|
char data[256]{'\0'};
|
|
|
|
};
|
|
|
|
|
2016-10-29 04:48:51 +00:00
|
|
|
class eventloop {
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
* Queue type
|
|
|
|
*/
|
|
|
|
using entry_t = event;
|
|
|
|
using queue_t = moodycamel::BlockingConcurrentQueue<entry_t>;
|
2016-11-25 20:20:50 +00:00
|
|
|
using duration_t = chrono::duration<double, std::milli>;
|
2016-10-29 04:48:51 +00:00
|
|
|
|
2016-11-25 20:20:50 +00:00
|
|
|
explicit eventloop(const logger& logger, const config& config);
|
2016-12-01 07:41:49 +00:00
|
|
|
~eventloop();
|
2016-10-29 04:48:51 +00:00
|
|
|
|
2016-11-25 20:20:50 +00:00
|
|
|
void start();
|
|
|
|
void wait();
|
2016-11-02 19:22:45 +00:00
|
|
|
void stop();
|
2016-10-29 04:48:51 +00:00
|
|
|
|
2016-11-25 20:20:50 +00:00
|
|
|
bool enqueue(const entry_t& entry);
|
|
|
|
bool enqueue_delayed(const entry_t& entry);
|
|
|
|
|
2016-12-03 21:54:58 +00:00
|
|
|
void set_update_cb(callback<bool>&& cb);
|
2016-11-02 19:22:45 +00:00
|
|
|
void set_input_db(callback<string>&& cb);
|
2016-10-29 04:48:51 +00:00
|
|
|
|
2016-11-02 19:22:45 +00:00
|
|
|
void add_module(const alignment pos, module_t&& module);
|
2016-11-25 20:20:50 +00:00
|
|
|
const modulemap_t& modules() const;
|
|
|
|
size_t module_count() const;
|
2016-10-29 04:48:51 +00:00
|
|
|
|
2016-12-03 21:54:58 +00:00
|
|
|
static const eventloop::entry_t& make(update_event&& event, bool force = false) {
|
|
|
|
event.force = force;
|
|
|
|
return reinterpret_cast<const eventloop::entry_t&>(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const eventloop::entry_t& make(quit_event&& event, bool reload = false) {
|
|
|
|
event.reload = reload;
|
|
|
|
return reinterpret_cast<const eventloop::entry_t&>(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const eventloop::entry_t& make(input_event&& event, const string& data) {
|
|
|
|
snprintf(event.data, sizeof(event.data), "%s", data.c_str());
|
|
|
|
return reinterpret_cast<const eventloop::entry_t&>(event);
|
|
|
|
}
|
|
|
|
|
2016-10-29 04:48:51 +00:00
|
|
|
protected:
|
2016-11-25 20:20:50 +00:00
|
|
|
void dispatch_modules();
|
|
|
|
void dispatch_queue_worker();
|
|
|
|
void dispatch_delayed_worker();
|
2016-10-29 04:48:51 +00:00
|
|
|
|
2016-11-25 20:20:50 +00:00
|
|
|
inline bool match_event(entry_t evt, event_type type);
|
|
|
|
inline bool compare_events(entry_t evt, entry_t evt2);
|
2016-11-02 19:22:45 +00:00
|
|
|
void forward_event(entry_t evt);
|
2016-10-29 04:48:51 +00:00
|
|
|
|
2016-12-03 21:54:58 +00:00
|
|
|
void on_update(const update_event& evt);
|
|
|
|
void on_input(const input_event& evt);
|
2016-11-02 19:22:45 +00:00
|
|
|
void on_check();
|
2016-12-03 21:54:58 +00:00
|
|
|
void on_quit(const quit_event& evt);
|
2016-10-29 04:48:51 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
const logger& m_log;
|
2016-11-25 20:20:50 +00:00
|
|
|
const config& m_conf;
|
2016-10-29 04:48:51 +00:00
|
|
|
|
2016-11-25 20:20:50 +00:00
|
|
|
/**
|
|
|
|
* @brief Event queue
|
|
|
|
*/
|
2016-10-29 04:48:51 +00:00
|
|
|
queue_t m_queue;
|
2016-11-25 20:20:50 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Loaded modules
|
|
|
|
*/
|
2016-10-29 04:48:51 +00:00
|
|
|
modulemap_t m_modules;
|
2016-11-25 20:20:50 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Flag to indicate current run state
|
|
|
|
*/
|
2016-10-29 04:48:51 +00:00
|
|
|
stateflag m_running;
|
|
|
|
|
2016-11-25 20:20:50 +00:00
|
|
|
/**
|
|
|
|
* @brief Callback fired when receiving UPDATE events
|
|
|
|
*/
|
2016-12-03 21:54:58 +00:00
|
|
|
callback<bool> m_update_cb;
|
2016-11-25 20:20:50 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Callback fired for unprocessed INPUT events
|
|
|
|
*/
|
2016-10-29 04:48:51 +00:00
|
|
|
callback<string> m_unrecognized_input_cb;
|
2016-11-25 20:20:50 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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;
|
2016-10-29 04:48:51 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
/**
|
|
|
|
* Configure injection module
|
|
|
|
*/
|
|
|
|
template <typename T = unique_ptr<eventloop>>
|
|
|
|
di::injector<T> configure_eventloop() {
|
2016-11-25 20:20:50 +00:00
|
|
|
return di::make_injector(configure_logger(), configure_config());
|
2016-10-29 04:48:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-19 05:22:44 +00:00
|
|
|
POLYBAR_NS_END
|