fix: Throttle X input events
- Limit the amount of allowed input events - Yield on lock failure - Cleanup
This commit is contained in:
parent
adf18108c3
commit
d879d6d42e
@ -8,7 +8,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake/modules)
|
|||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wno-unused-parameter -Wno-unused-local-typedefs")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wno-unused-parameter -Wno-unused-local-typedefs")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG -O0 -g2")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG -O0 -g2")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "utils/math.hpp"
|
#include "utils/math.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
#include "utils/threading.hpp"
|
#include "utils/threading.hpp"
|
||||||
|
#include "utils/throttle.hpp"
|
||||||
#if ENABLE_I3
|
#if ENABLE_I3
|
||||||
#include "utils/i3.hpp"
|
#include "utils/i3.hpp"
|
||||||
#endif
|
#endif
|
||||||
@ -83,6 +84,9 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
|||||||
* This is done outside the constructor due to boost::di noexcept
|
* This is done outside the constructor due to boost::di noexcept
|
||||||
*/
|
*/
|
||||||
void bootstrap(bool nodraw = false) { //{{{
|
void bootstrap(bool nodraw = false) { //{{{
|
||||||
|
// limit the amount of allowed input events to 1 per 60ms
|
||||||
|
m_throttler = throttle_util::make_throttler(1, 60ms);
|
||||||
|
|
||||||
m_screen = m_connection.screen();
|
m_screen = m_connection.screen();
|
||||||
m_visual = m_connection.visual_type(m_screen, 32).get();
|
m_visual = m_connection.visual_type(m_screen, 32).get();
|
||||||
auto monitors = randr_util::get_monitors(m_connection, m_connection.screen()->root);
|
auto monitors = randr_util::get_monitors(m_connection, m_connection.screen()->root);
|
||||||
@ -588,6 +592,10 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
|||||||
* Mouse button event handler
|
* Mouse button event handler
|
||||||
*/
|
*/
|
||||||
void handle(const evt::button_press& evt) { // {{{
|
void handle(const evt::button_press& evt) { // {{{
|
||||||
|
if (!m_throttler->passthrough(throttle_util::strategy::try_once_or_leave_yolo{})) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::lock_guard<threading_util::spin_lock> lck(m_lock);
|
std::lock_guard<threading_util::spin_lock> lck(m_lock);
|
||||||
{
|
{
|
||||||
m_log.trace("bar: Received button press event: %i at pos(%i, %i)",
|
m_log.trace("bar: Received button press event: %i at pos(%i, %i)",
|
||||||
@ -980,6 +988,7 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
|||||||
unique_ptr<fontmanager> m_fontmanager;
|
unique_ptr<fontmanager> m_fontmanager;
|
||||||
|
|
||||||
threading_util::spin_lock m_lock;
|
threading_util::spin_lock m_lock;
|
||||||
|
throttle_util::throttle_t m_throttler;
|
||||||
|
|
||||||
xcb_screen_t* m_screen;
|
xcb_screen_t* m_screen;
|
||||||
xcb_visualtype_t* m_visual;
|
xcb_visualtype_t* m_visual;
|
||||||
|
@ -76,8 +76,6 @@ class controller {
|
|||||||
m_log.trace("controller: Stop modules");
|
m_log.trace("controller: Stop modules");
|
||||||
for (auto&& block : m_modules) {
|
for (auto&& block : m_modules) {
|
||||||
for (auto&& module : block.second) {
|
for (auto&& module : block.second) {
|
||||||
module->on_update.clear();
|
|
||||||
module->on_stop.clear();
|
|
||||||
module->stop();
|
module->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,9 +209,6 @@ class controller {
|
|||||||
m_log.trace("controller: Start modules");
|
m_log.trace("controller: Start modules");
|
||||||
for (auto&& block : m_modules) {
|
for (auto&& block : m_modules) {
|
||||||
for (auto&& module : block.second) {
|
for (auto&& module : block.second) {
|
||||||
module->on_update.connect(this, &controller::on_module_update);
|
|
||||||
module->on_stop.connect(this, &controller::on_module_stop);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
module->start();
|
module->start();
|
||||||
} catch (const application_error& err) {
|
} catch (const application_error& err) {
|
||||||
@ -407,6 +402,11 @@ class controller {
|
|||||||
else
|
else
|
||||||
throw application_error("Unknown module: " + module_name);
|
throw application_error("Unknown module: " + module_name);
|
||||||
|
|
||||||
|
auto& module = modules.back();
|
||||||
|
|
||||||
|
module->set_writer(delegate::MakeDelegate(this, &controller::on_module_update));
|
||||||
|
module->set_terminator(delegate::MakeDelegate(this, &controller::on_module_stop));
|
||||||
|
|
||||||
module_count++;
|
module_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,14 +415,15 @@ class controller {
|
|||||||
throw application_error("No modules created");
|
throw application_error("No modules created");
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_module_update(string module_name) {
|
void on_module_update(string /* module_name */) {
|
||||||
if (!m_mutex.try_lock_for(50ms))
|
if (!m_mutex.try_lock_for(50ms)) {
|
||||||
|
this_thread::yield();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
std::lock_guard<std::timed_mutex> guard(m_mutex, std::adopt_lock);
|
std::lock_guard<std::timed_mutex> guard(m_mutex, std::adopt_lock);
|
||||||
|
|
||||||
if (!m_running)
|
if (!m_running)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_throttler->passthrough(m_throttle_strategy)) {
|
if (!m_throttler->passthrough(m_throttle_strategy)) {
|
||||||
m_log.trace("controller: Update event throttled");
|
m_log.trace("controller: Update event throttled");
|
||||||
return;
|
return;
|
||||||
@ -489,7 +490,10 @@ class controller {
|
|||||||
m_bar->parse(contents);
|
m_bar->parse(contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_module_stop(string module_name) {
|
void on_module_stop(string /* module_name */) {
|
||||||
|
if (!m_running)
|
||||||
|
return;
|
||||||
|
|
||||||
for (auto&& block : m_modules) {
|
for (auto&& block : m_modules) {
|
||||||
for (auto&& module : block.second) {
|
for (auto&& module : block.second) {
|
||||||
if (module->running())
|
if (module->running())
|
||||||
@ -502,9 +506,12 @@ class controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void on_module_click(string input) {
|
void on_module_click(string input) {
|
||||||
if (!m_mutex.try_lock())
|
if (!m_clickmtx.try_lock()) {
|
||||||
|
this_thread::yield();
|
||||||
return;
|
return;
|
||||||
std::lock_guard<std::timed_mutex> guard(m_mutex, std::adopt_lock);
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> guard(m_clickmtx, std::adopt_lock);
|
||||||
|
|
||||||
for (auto&& block : m_modules) {
|
for (auto&& block : m_modules) {
|
||||||
for (auto&& module : block.second) {
|
for (auto&& module : block.second) {
|
||||||
@ -538,6 +545,7 @@ class controller {
|
|||||||
unique_ptr<traymanager> m_traymanager;
|
unique_ptr<traymanager> m_traymanager;
|
||||||
|
|
||||||
std::timed_mutex m_mutex;
|
std::timed_mutex m_mutex;
|
||||||
|
std::mutex m_clickmtx;
|
||||||
|
|
||||||
stateflag m_stdout{false};
|
stateflag m_stdout{false};
|
||||||
stateflag m_running{false};
|
stateflag m_running{false};
|
||||||
|
@ -18,8 +18,8 @@ LEMONBUDDY_NS
|
|||||||
#define DEFAULT_FORMAT "format"
|
#define DEFAULT_FORMAT "format"
|
||||||
|
|
||||||
#define DEFINE_MODULE(name, type) struct name : public type<name>
|
#define DEFINE_MODULE(name, type) struct name : public type<name>
|
||||||
#define CONST_CAST_MODULE(name) static_cast<name const&>(*this)
|
#define CONST_MOD(name) static_cast<name const&>(*this)
|
||||||
#define CAST_MODULE(name) static_cast<name*>(this)
|
#define CAST_MOD(name) static_cast<name*>(this)
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
using namespace drawtypes;
|
using namespace drawtypes;
|
||||||
@ -153,14 +153,13 @@ namespace modules {
|
|||||||
virtual void setup() = 0;
|
virtual void setup() = 0;
|
||||||
virtual void start() = 0;
|
virtual void start() = 0;
|
||||||
virtual void stop() = 0;
|
virtual void stop() = 0;
|
||||||
virtual void refresh() = 0;
|
|
||||||
virtual string contents() = 0;
|
virtual string contents() = 0;
|
||||||
|
|
||||||
virtual bool handle_event(string cmd) = 0;
|
virtual bool handle_event(string cmd) = 0;
|
||||||
virtual bool receive_events() const = 0;
|
virtual bool receive_events() const = 0;
|
||||||
|
|
||||||
delegate::Signal1<string> on_update;
|
virtual void set_writer(delegate::Delegate1<string>&& fn) = 0;
|
||||||
delegate::Signal1<string> on_stop;
|
virtual void set_terminator(delegate::Delegate1<string>&& fn) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
@ -178,10 +177,11 @@ namespace modules {
|
|||||||
, m_formatter(make_unique<module_formatter>(m_conf, m_name)) {}
|
, m_formatter(make_unique<module_formatter>(m_conf, m_name)) {}
|
||||||
|
|
||||||
~module() {
|
~module() {
|
||||||
stop();
|
CAST_MOD(Impl)->stop();
|
||||||
|
|
||||||
this->update_lock.unlock();
|
m_updatelock.unlock();
|
||||||
std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
|
|
||||||
|
std::lock_guard<threading_util::spin_lock> lck(m_updatelock);
|
||||||
{
|
{
|
||||||
if (m_broadcast_thread.joinable())
|
if (m_broadcast_thread.joinable())
|
||||||
m_broadcast_thread.join();
|
m_broadcast_thread.join();
|
||||||
@ -190,43 +190,51 @@ namespace modules {
|
|||||||
if (thread_.joinable())
|
if (thread_.joinable())
|
||||||
thread_.join();
|
thread_.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_threads.clear();
|
m_threads.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.trace("%s: Done cleaning up", name());
|
m_log.trace("%s: Done cleaning up", name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_writer(delegate::Delegate1<string>&& fn) {
|
||||||
|
m_writer = forward<decltype(fn)>(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_terminator(delegate::Delegate1<string>&& fn) {
|
||||||
|
m_terminator = forward<decltype(fn)>(fn);
|
||||||
|
}
|
||||||
|
|
||||||
string name() const {
|
string name() const {
|
||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool running() const {
|
bool running() const {
|
||||||
return enabled();
|
return CONST_MOD(Impl).enabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
m_log.trace("%s: Setup", name());
|
m_log.trace("%s: Setup", name());
|
||||||
CAST_MODULE(Impl)->setup();
|
CAST_MOD(Impl)->setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop() {
|
void stop() {
|
||||||
if (!enabled())
|
if (!enabled())
|
||||||
return;
|
return;
|
||||||
std::unique_lock<threading_util::spin_lock> lck(this->update_lock);
|
|
||||||
enable(false);
|
std::unique_lock<threading_util::spin_lock> lck(m_updatelock);
|
||||||
CAST_MODULE(Impl)->teardown();
|
{
|
||||||
lck.unlock();
|
enable(false);
|
||||||
m_log.trace("%s: Stop", name());
|
CAST_MOD(Impl)->teardown();
|
||||||
if (!on_stop.empty())
|
m_log.trace("%s: Stop", name());
|
||||||
on_stop.emit(name());
|
}
|
||||||
|
|
||||||
|
if (m_terminator)
|
||||||
|
m_terminator(name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void teardown() {
|
void teardown() {
|
||||||
wakeup();
|
CAST_MOD(Impl)->wakeup();
|
||||||
}
|
|
||||||
|
|
||||||
void refresh() {
|
|
||||||
m_cache = CAST_MODULE(Impl)->get_output();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string contents() {
|
string contents() {
|
||||||
@ -234,7 +242,7 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool handle_event(string cmd) {
|
bool handle_event(string cmd) {
|
||||||
return CAST_MODULE(Impl)->handle_event(cmd);
|
return CAST_MOD(Impl)->handle_event(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool receive_events() const {
|
bool receive_events() const {
|
||||||
@ -253,15 +261,11 @@ namespace modules {
|
|||||||
void broadcast() {
|
void broadcast() {
|
||||||
if (!enabled())
|
if (!enabled())
|
||||||
return;
|
return;
|
||||||
|
else if (!m_writer)
|
||||||
|
m_log.warn("%s: No attach writer, ignoring broadcast...", name());
|
||||||
|
|
||||||
refresh();
|
m_cache = CAST_MOD(Impl)->get_output();
|
||||||
|
m_writer(name());
|
||||||
if (contents().empty())
|
|
||||||
return;
|
|
||||||
else if (on_update.empty())
|
|
||||||
m_log.warn("%s: No signal handlers connected... ignoring broadcast", name());
|
|
||||||
else
|
|
||||||
on_update.emit(name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void idle() {}
|
void idle() {}
|
||||||
@ -287,7 +291,7 @@ namespace modules {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto format_name = CONST_CAST_MODULE(Impl).get_format();
|
auto format_name = CONST_MOD(Impl).get_format();
|
||||||
auto format = m_formatter->get(format_name);
|
auto format = m_formatter->get(format_name);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -299,7 +303,7 @@ namespace modules {
|
|||||||
if (tag[0] == '<' && tag[tag.length() - 1] == '>') {
|
if (tag[0] == '<' && tag[tag.length() - 1] == '>') {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
m_builder->space(format->spacing);
|
m_builder->space(format->spacing);
|
||||||
if (!(tag_built = CONST_CAST_MODULE(Impl).build(m_builder.get(), tag)) && i > 0)
|
if (!(tag_built = CONST_MOD(Impl).build(m_builder.get(), tag)) && i > 0)
|
||||||
m_builder->remove_trailing_space(format->spacing);
|
m_builder->remove_trailing_space(format->spacing);
|
||||||
if (tag_built)
|
if (tag_built)
|
||||||
i++;
|
i++;
|
||||||
@ -314,19 +318,11 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Called by modules after handling action events
|
delegate::Delegate1<string> m_writer;
|
||||||
void event_handled() {
|
delegate::Delegate1<string> m_terminator;
|
||||||
std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
|
|
||||||
{
|
|
||||||
if (m_broadcast_thread.joinable())
|
|
||||||
m_broadcast_thread.join();
|
|
||||||
m_broadcast_thread = thread(&module::broadcast, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// concurrency::SpinLock output_lock;
|
threading_util::spin_lock m_updatelock;
|
||||||
// concurrency::SpinLock broadcast_lock;
|
// std::timed_mutex m_mutex;
|
||||||
threading_util::spin_lock update_lock;
|
|
||||||
|
|
||||||
const bar_settings m_bar;
|
const bar_settings m_bar;
|
||||||
const logger& m_log;
|
const logger& m_log;
|
||||||
@ -356,9 +352,9 @@ namespace modules {
|
|||||||
using module<Impl>::module;
|
using module<Impl>::module;
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
CAST_MODULE(Impl)->setup();
|
CAST_MOD(Impl)->setup();
|
||||||
CAST_MODULE(Impl)->enable(true);
|
CAST_MOD(Impl)->enable(true);
|
||||||
CAST_MODULE(Impl)->broadcast();
|
CAST_MOD(Impl)->broadcast();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool build(builder*, string) const {
|
bool build(builder*, string) const {
|
||||||
@ -377,8 +373,8 @@ namespace modules {
|
|||||||
using module<Impl>::module;
|
using module<Impl>::module;
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
CAST_MODULE(Impl)->enable(true);
|
CAST_MOD(Impl)->enable(true);
|
||||||
CAST_MODULE(Impl)->m_threads.emplace_back(thread(&timer_module::runner, this));
|
CAST_MOD(Impl)->m_threads.emplace_back(thread(&timer_module::runner, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -386,20 +382,20 @@ namespace modules {
|
|||||||
|
|
||||||
void runner() {
|
void runner() {
|
||||||
try {
|
try {
|
||||||
CAST_MODULE(Impl)->setup();
|
CAST_MOD(Impl)->setup();
|
||||||
|
|
||||||
while (CONST_CAST_MODULE(Impl).enabled()) {
|
while (CONST_MOD(Impl).enabled()) {
|
||||||
{
|
{
|
||||||
std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
|
std::lock_guard<threading_util::spin_lock> lck(this->m_updatelock);
|
||||||
if (CAST_MODULE(Impl)->update())
|
if (CAST_MOD(Impl)->update())
|
||||||
CAST_MODULE(Impl)->broadcast();
|
CAST_MOD(Impl)->broadcast();
|
||||||
}
|
}
|
||||||
CAST_MODULE(Impl)->sleep(m_interval);
|
CAST_MOD(Impl)->sleep(m_interval);
|
||||||
}
|
}
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
this->m_log.err("%s: %s", this->name(), err.what());
|
this->m_log.err("%s: %s", CONST_MOD(Impl).name(), err.what());
|
||||||
this->m_log.warn("Stopping '%s'...", this->name());
|
this->m_log.warn("Stopping '%s'...", CONST_MOD(Impl).name());
|
||||||
CAST_MODULE(Impl)->stop();
|
CAST_MOD(Impl)->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -413,33 +409,33 @@ namespace modules {
|
|||||||
using module<Impl>::module;
|
using module<Impl>::module;
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
CAST_MODULE(Impl)->enable(true);
|
CAST_MOD(Impl)->enable(true);
|
||||||
CAST_MODULE(Impl)->m_threads.emplace_back(thread(&event_module::runner, this));
|
CAST_MOD(Impl)->m_threads.emplace_back(thread(&event_module::runner, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void runner() {
|
void runner() {
|
||||||
try {
|
try {
|
||||||
CAST_MODULE(Impl)->setup();
|
CAST_MOD(Impl)->setup();
|
||||||
|
|
||||||
// warmup
|
// warmup
|
||||||
CAST_MODULE(Impl)->update();
|
CAST_MOD(Impl)->update();
|
||||||
CAST_MODULE(Impl)->broadcast();
|
CAST_MOD(Impl)->broadcast();
|
||||||
|
|
||||||
while (CONST_CAST_MODULE(Impl).enabled()) {
|
while (CONST_MOD(Impl).enabled()) {
|
||||||
std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
|
std::lock_guard<threading_util::spin_lock> lck(this->m_updatelock);
|
||||||
|
|
||||||
if (!CAST_MODULE(Impl)->has_event())
|
if (!CAST_MOD(Impl)->has_event())
|
||||||
CAST_MODULE(Impl)->idle();
|
CAST_MOD(Impl)->idle();
|
||||||
else if (!CAST_MODULE(Impl)->update())
|
else if (!CAST_MOD(Impl)->update())
|
||||||
CAST_MODULE(Impl)->idle();
|
CAST_MOD(Impl)->idle();
|
||||||
else
|
else
|
||||||
CAST_MODULE(Impl)->broadcast();
|
CAST_MOD(Impl)->broadcast();
|
||||||
}
|
}
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
this->m_log.err("%s: %s", this->name(), err.what());
|
this->m_log.err("%s: %s", CONST_MOD(Impl).name(), err.what());
|
||||||
this->m_log.warn("Stopping '%s'...", this->name());
|
this->m_log.warn("Stopping '%s'...", CONST_MOD(Impl).name());
|
||||||
CAST_MODULE(Impl)->stop();
|
CAST_MOD(Impl)->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -453,34 +449,34 @@ namespace modules {
|
|||||||
using module<Impl>::module;
|
using module<Impl>::module;
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
CAST_MODULE(Impl)->enable(true);
|
CAST_MOD(Impl)->enable(true);
|
||||||
CAST_MODULE(Impl)->m_threads.emplace_back(thread(&inotify_module::runner, this));
|
CAST_MOD(Impl)->m_threads.emplace_back(thread(&inotify_module::runner, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void runner() {
|
void runner() {
|
||||||
try {
|
try {
|
||||||
CAST_MODULE(Impl)->setup();
|
CAST_MOD(Impl)->setup();
|
||||||
CAST_MODULE(Impl)->on_event(nullptr); // warmup
|
CAST_MOD(Impl)->on_event(nullptr); // warmup
|
||||||
CAST_MODULE(Impl)->broadcast();
|
CAST_MOD(Impl)->broadcast();
|
||||||
|
|
||||||
while (CAST_MODULE(Impl)->enabled()) {
|
while (CAST_MOD(Impl)->enabled()) {
|
||||||
CAST_MODULE(Impl)->poll_events();
|
CAST_MOD(Impl)->poll_events();
|
||||||
}
|
}
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
this->m_log.err("%s: %s", this->name(), err.what());
|
this->m_log.err("%s: %s", CONST_MOD(Impl).name(), err.what());
|
||||||
this->m_log.warn("Stopping '%s'...", this->name());
|
this->m_log.warn("Stopping '%s'...", CONST_MOD(Impl).name());
|
||||||
CAST_MODULE(Impl)->stop();
|
CAST_MOD(Impl)->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch(string path, int mask = IN_ALL_EVENTS) {
|
void watch(string path, int mask = IN_ALL_EVENTS) {
|
||||||
this->m_log.trace("%s: Attach inotify at %s", this->name(), path);
|
this->m_log.trace("%s: Attach inotify at %s", CONST_MOD(Impl).name(), path);
|
||||||
m_watchlist.insert(make_pair(path, mask));
|
m_watchlist.insert(make_pair(path, mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
void idle() {
|
void idle() {
|
||||||
CAST_MODULE(Impl)->sleep(200ms);
|
CAST_MOD(Impl)->sleep(200ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void poll_events() {
|
void poll_events() {
|
||||||
@ -494,28 +490,28 @@ namespace modules {
|
|||||||
} catch (const system_error& e) {
|
} catch (const system_error& e) {
|
||||||
watches.clear();
|
watches.clear();
|
||||||
this->m_log.err(
|
this->m_log.err(
|
||||||
"%s: Error while creating inotify watch (what: %s)", this->name(), e.what());
|
"%s: Error while creating inotify watch (what: %s)", CONST_MOD(Impl).name(), e.what());
|
||||||
CAST_MODULE(Impl)->sleep(0.1s);
|
CAST_MOD(Impl)->sleep(0.1s);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (CONST_CAST_MODULE(Impl).enabled()) {
|
while (CONST_MOD(Impl).enabled()) {
|
||||||
for (auto&& w : watches) {
|
for (auto&& w : watches) {
|
||||||
this->m_log.trace("%s: Poll inotify watch %s", this->name(), w->path());
|
this->m_log.trace("%s: Poll inotify watch %s", CONST_MOD(Impl).name(), w->path());
|
||||||
std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
|
std::lock_guard<threading_util::spin_lock> lck(this->m_updatelock);
|
||||||
|
|
||||||
if (w->poll(1000 / watches.size())) {
|
if (w->poll(1000 / watches.size())) {
|
||||||
auto event = w->get_event();
|
auto event = w->get_event();
|
||||||
|
|
||||||
w->remove();
|
w->remove();
|
||||||
|
|
||||||
if (CAST_MODULE(Impl)->on_event(event.get()))
|
if (CAST_MOD(Impl)->on_event(event.get()))
|
||||||
CAST_MODULE(Impl)->broadcast();
|
CAST_MOD(Impl)->broadcast();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CAST_MODULE(Impl)->idle();
|
CAST_MOD(Impl)->idle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ namespace modules {
|
|||||||
wakeup();
|
wakeup();
|
||||||
enable(false);
|
enable(false);
|
||||||
m_command.reset();
|
m_command.reset();
|
||||||
std::lock_guard<threading_util::spin_lock> lck(this->update_lock);
|
std::lock_guard<threading_util::spin_lock> lck(m_updatelock);
|
||||||
wakeup();
|
wakeup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,8 +94,8 @@ namespace modules {
|
|||||||
|
|
||||||
m_log.trace("%s: Executing '%s'", name(), exec);
|
m_log.trace("%s: Executing '%s'", name(), exec);
|
||||||
|
|
||||||
cmd->exec();
|
cmd->exec(true);
|
||||||
cmd->tail([this](string contents) { m_output = contents; });
|
cmd->tail([&](string output) { m_output = output; });
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
m_log.err("%s: %s", name(), err.what());
|
m_log.err("%s: %s", name(), err.what());
|
||||||
throw module_error("Failed to execute command, stopping module...");
|
throw module_error("Failed to execute command, stopping module...");
|
||||||
@ -130,10 +130,12 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool build(builder* builder, string tag) const {
|
bool build(builder* builder, string tag) const {
|
||||||
if (tag != TAG_OUTPUT)
|
if (tag == TAG_OUTPUT) {
|
||||||
|
builder->node(m_output);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
builder->node(string_util::replace_all(m_output, "\n", ""));
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -195,6 +195,7 @@ namespace modules {
|
|||||||
m_builder->cmd(mousebtn::SCROLL_DOWN, EVENT_VOLUME_DOWN);
|
m_builder->cmd(mousebtn::SCROLL_DOWN, EVENT_VOLUME_DOWN);
|
||||||
|
|
||||||
m_builder->node(module::get_output());
|
m_builder->node(module::get_output());
|
||||||
|
|
||||||
return m_builder->flush();
|
return m_builder->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,8 +252,6 @@ namespace modules {
|
|||||||
// sending the broadcast related to this event
|
// sending the broadcast related to this event
|
||||||
m_muted = !m_muted;
|
m_muted = !m_muted;
|
||||||
|
|
||||||
event_handled();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ namespace command_util {
|
|||||||
if (WIFEXITED(m_forkstatus) && m_forkstatus > 0)
|
if (WIFEXITED(m_forkstatus) && m_forkstatus > 0)
|
||||||
m_log.warn("command: Exited with failed status %d", WEXITSTATUS(m_forkstatus));
|
m_log.warn("command: Exited with failed status %d", WEXITSTATUS(m_forkstatus));
|
||||||
else if (WIFEXITED(m_forkstatus))
|
else if (WIFEXITED(m_forkstatus))
|
||||||
m_log.warn("command: Exited with status %d", WEXITSTATUS(m_forkstatus));
|
m_log.trace("command: Exited with status %d", WEXITSTATUS(m_forkstatus));
|
||||||
else if (WIFSIGNALED(m_forkstatus))
|
else if (WIFSIGNALED(m_forkstatus))
|
||||||
m_log.trace("command: killed by signal %d", WTERMSIG(m_forkstatus));
|
m_log.trace("command: killed by signal %d", WTERMSIG(m_forkstatus));
|
||||||
else if (WIFSTOPPED(m_forkstatus))
|
else if (WIFSTOPPED(m_forkstatus))
|
||||||
|
@ -101,8 +101,10 @@ namespace throttle_util {
|
|||||||
timewindow m_timewindow;
|
timewindow m_timewindow;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using throttle_t = unique_ptr<event_throttler>;
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
auto make_throttler(Args&&... args) {
|
throttle_t make_throttler(Args&&... args) {
|
||||||
return make_unique<event_throttler>(forward<Args>(args)...);
|
return make_unique<event_throttler>(forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user