summaryrefslogtreecommitdiff
path: root/src/lib/signal.h
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2025-06-12 00:27:33 +0200
committerCarl Hetherington <cth@carlh.net>2025-06-14 23:43:13 +0200
commita12a943c99ba4aba122f91c93b078d2e87146b32 (patch)
tree93e149bc2d6f9c2ff98aa05c5d51e096dd0c6598 /src/lib/signal.h
parent6d2d4973ccd5d4c78414d28988a74dfa7287f001 (diff)
Use a new UISignal which checks thread safety slightly.3052-hang
This adds a wrapper around signals2::signal which checks that emission happens from the GUI thread, for signals whose handlers must be called in the UI thread. I'm not sure how helpful it really is but maybe it catches some bad situations.
Diffstat (limited to 'src/lib/signal.h')
-rw-r--r--src/lib/signal.h70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/lib/signal.h b/src/lib/signal.h
new file mode 100644
index 000000000..03b440e79
--- /dev/null
+++ b/src/lib/signal.h
@@ -0,0 +1,70 @@
+/*
+ Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#ifndef DCPOMATIC_SIGNAL_H
+#define DCPOMATIC_SIGNAL_H
+
+
+#include "signaller.h"
+#include "util.h"
+#include <boost/signals2.hpp>
+#include <utility>
+
+
+/** Wrapper for a boost::signals2::signal that asserts that emissions are made from the
+ * UI thead, so anything connected to it will be guaranteed to be called from there.
+ */
+template <typename T>
+class UISignal
+{
+public:
+ template <typename... Args>
+ void emit_ui(Signaller* signaller, Args&&... args) const
+ {
+ signaller->emit(boost::bind(boost::ref(_wrapped), std::forward<Args>(args)...));
+ }
+
+ template <typename... Args>
+ void emit(Args&&... args) const
+ {
+ ensure_ui_thread();
+ _wrapped(std::forward<Args>(args)...);
+ }
+
+ template <typename... Args>
+ boost::signals2::connection connect(Args&&... args)
+ {
+ return _wrapped.connect(std::forward<Args>(args)...);
+ }
+
+ template <typename... Args>
+ void operator()(Args&&... args) const
+ {
+ emit(std::forward<Args>(args)...);
+ }
+
+private:
+ boost::signals2::signal<T> _wrapped;
+};
+
+
+#endif
+