Wake all sleeping threads when leaving suspend
std::condition_variable::wait_for does not count time spent in sleep mode, resulting in longer than expected waits.pull/2219/head
parent
c5379fa52d
commit
3c9cbc99d7
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SafeSignal.hpp"
|
||||||
|
|
||||||
|
namespace waybar::util {
|
||||||
|
|
||||||
|
// Get a signal emited with value true when entering sleep, and false when exiting
|
||||||
|
SafeSignal<bool>& prepare_for_sleep();
|
||||||
|
} // namespace waybar::util
|
|
@ -6,6 +6,8 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include "prepare_for_sleep.h"
|
||||||
|
|
||||||
namespace waybar::util {
|
namespace waybar::util {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,7 +35,11 @@ class SleeperThread {
|
||||||
signal_ = false;
|
signal_ = false;
|
||||||
func();
|
func();
|
||||||
}
|
}
|
||||||
}} {}
|
}} {
|
||||||
|
connection_ = prepare_for_sleep().connect([this](bool sleep) {
|
||||||
|
if (not sleep) wake_up();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
SleeperThread& operator=(std::function<void()> func) {
|
SleeperThread& operator=(std::function<void()> func) {
|
||||||
thread_ = std::thread([this, func] {
|
thread_ = std::thread([this, func] {
|
||||||
|
@ -42,6 +48,11 @@ class SleeperThread {
|
||||||
func();
|
func();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (connection_.empty()) {
|
||||||
|
connection_ = prepare_for_sleep().connect([this](bool sleep) {
|
||||||
|
if (not sleep) wake_up();
|
||||||
|
});
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +72,7 @@ class SleeperThread {
|
||||||
return condvar_.wait_until(lk, time_point, [this] { return signal_ || !do_run_; });
|
return condvar_.wait_until(lk, time_point, [this] { return signal_ || !do_run_; });
|
||||||
}
|
}
|
||||||
|
|
||||||
auto wake_up() {
|
void wake_up() {
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lck(mutex_);
|
std::lock_guard<std::mutex> lck(mutex_);
|
||||||
signal_ = true;
|
signal_ = true;
|
||||||
|
@ -96,6 +107,7 @@ class SleeperThread {
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
bool do_run_ = true;
|
bool do_run_ = true;
|
||||||
bool signal_ = false;
|
bool signal_ = false;
|
||||||
|
sigc::connection connection_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::util
|
} // namespace waybar::util
|
||||||
|
|
|
@ -170,6 +170,7 @@ src_files = files(
|
||||||
'src/client.cpp',
|
'src/client.cpp',
|
||||||
'src/config.cpp',
|
'src/config.cpp',
|
||||||
'src/group.cpp',
|
'src/group.cpp',
|
||||||
|
'src/util/prepare_for_sleep.cpp',
|
||||||
'src/util/ustring_clen.cpp',
|
'src/util/ustring_clen.cpp',
|
||||||
'src/util/sanitize_str.cpp',
|
'src/util/sanitize_str.cpp',
|
||||||
'src/util/rewrite_string.cpp'
|
'src/util/rewrite_string.cpp'
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include "util/prepare_for_sleep.h"
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class PrepareForSleep {
|
||||||
|
private:
|
||||||
|
PrepareForSleep() {
|
||||||
|
GError *error = NULL;
|
||||||
|
login1_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||||
|
if (!login1_connection) {
|
||||||
|
throw std::runtime_error("Unable to connect to the SYSTEM Bus!...");
|
||||||
|
} else {
|
||||||
|
login1_id = g_dbus_connection_signal_subscribe(
|
||||||
|
login1_connection, "org.freedesktop.login1", "org.freedesktop.login1.Manager",
|
||||||
|
"PrepareForSleep", "/org/freedesktop/login1", NULL, G_DBUS_SIGNAL_FLAGS_NONE,
|
||||||
|
prepareForSleep_cb, this, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prepareForSleep_cb(GDBusConnection *system_bus, const gchar *sender_name,
|
||||||
|
const gchar *object_path, const gchar *interface_name,
|
||||||
|
const gchar *signal_name, GVariant *parameters,
|
||||||
|
gpointer user_data) {
|
||||||
|
if (g_variant_is_of_type(parameters, G_VARIANT_TYPE("(b)"))) {
|
||||||
|
gboolean sleeping;
|
||||||
|
g_variant_get(parameters, "(b)", &sleeping);
|
||||||
|
|
||||||
|
PrepareForSleep *self = static_cast<PrepareForSleep *>(user_data);
|
||||||
|
self->signal.emit(sleeping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static PrepareForSleep &GetInstance() {
|
||||||
|
static PrepareForSleep instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
waybar::SafeSignal<bool> signal;
|
||||||
|
|
||||||
|
private:
|
||||||
|
guint login1_id;
|
||||||
|
GDBusConnection *login1_connection;
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
waybar::SafeSignal<bool> &waybar::util::prepare_for_sleep() {
|
||||||
|
return PrepareForSleep::GetInstance().signal;
|
||||||
|
}
|
Loading…
Reference in New Issue