diff options
| author | Carl Hetherington <cth@carlh.net> | 2025-06-12 00:27:33 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2025-06-14 23:43:13 +0200 |
| commit | a12a943c99ba4aba122f91c93b078d2e87146b32 (patch) | |
| tree | 93e149bc2d6f9c2ff98aa05c5d51e096dd0c6598 /src/lib/signal.h | |
| parent | 6d2d4973ccd5d4c78414d28988a74dfa7287f001 (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.h | 70 |
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 + |
