From ec92ac91ab80e87ec56ab50d58fcc21a6b7967ae Mon Sep 17 00:00:00 2001 From: Michael Carlberg Date: Mon, 20 Jun 2016 22:11:58 +0200 Subject: [PATCH] feat(core): Custom thread sleep Makes it possible to manually wake up sleeping threads --- include/modules/base.hpp | 40 +++++++++++++++++++++++++++++++++------- src/modules/battery.cpp | 2 +- src/modules/mpd.cpp | 2 +- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/include/modules/base.hpp b/include/modules/base.hpp index de830b72..67e922c2 100644 --- a/include/modules/base.hpp +++ b/include/modules/base.hpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -166,6 +165,9 @@ namespace modules concurrency::SpinLock output_lock; concurrency::SpinLock broadcast_lock; + std::mutex sleep_lock; + std::condition_variable sleep_handler; + std::string name_; std::unique_ptr builder; std::unique_ptr formatter; @@ -201,8 +203,10 @@ namespace modules return name_; } - void stop() { + void stop() + { log_trace(name()); + this->wakeup(); std::lock_guard lck(this->broadcast_lock); this->enable(false); } @@ -228,11 +232,32 @@ namespace modules this->enabled_flag = state; } - void broadcast() { + void broadcast() + { std::lock_guard lck(this->broadcast_lock); broadcast_module_update(ConstCastModule(ModuleImpl).name()); } + void sleep(std::chrono::duration sleep_duration) + { + std::unique_lock lck(this->sleep_lock); + std::thread sleep_thread([&]{ + auto start = std::chrono::system_clock::now(); + while ((std::chrono::system_clock::now() - start) < sleep_duration) { + std::this_thread::sleep_for(50ms); + } + this->wakeup(); + }); + sleep_thread.detach(); + this->sleep_handler.wait(lck); + } + + void wakeup() + { + log_trace("Releasing sleep lock for "+ this->name_); + this->sleep_handler.notify_one(); + } + std::string get_format() { return DEFAULT_FORMAT; } @@ -301,10 +326,11 @@ namespace modules void runner() { while (this->enabled()) { - std::lock_guard lck(this->update_lock); - if (CastModule(ModuleImpl)->update()) - CastModule(ModuleImpl)->broadcast(); - std::this_thread::sleep_for(this->interval); + { std::lock_guard lck(this->update_lock); + if (CastModule(ModuleImpl)->update()) + CastModule(ModuleImpl)->broadcast(); + } + this->sleep(this->interval); } } diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 759fc891..eeea1cb9 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -98,7 +98,7 @@ void BatteryModule::subthread_routine() if (this->state == STATE_CHARGING) this->broadcast(); - std::this_thread::sleep_for(dur); + this->sleep(dur); } log_debug("Reached end of battery subthread"); diff --git a/src/modules/mpd.cpp b/src/modules/mpd.cpp index 734186a4..c30e6d6e 100644 --- a/src/modules/mpd.cpp +++ b/src/modules/mpd.cpp @@ -104,7 +104,7 @@ bool MpdModule::has_event() } if (!this->mpd->connected()) { - std::this_thread::sleep_for(3s); + this->sleep(3s); return false; } }