X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fchange_signaller.h;h=8612cf42672b2c8ca42ae270bb896925a6cd20d4;hb=HEAD;hp=55a5f2dc57f90b5d8307fbd882db9894d02714ae;hpb=8fedaaa75c4586a4cc7ffb393bd71d1fdb091dc8;p=dcpomatic.git diff --git a/src/lib/change_signaller.h b/src/lib/change_signaller.h index 55a5f2dc5..1d7d482df 100644 --- a/src/lib/change_signaller.h +++ b/src/lib/change_signaller.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Carl Hetherington + Copyright (C) 2018-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,30 +18,119 @@ */ + #ifndef DCPOMATIC_CHANGE_SIGNALLER_H #define DCPOMATIC_CHANGE_SIGNALLER_H -#include -template -class ChangeSignaller : public boost::noncopyable +#include +#include + + +enum class ChangeType +{ + PENDING, + DONE, + CANCELLED +}; + + +template +class ChangeSignal { public: - ChangeSignaller (T* t, int p) - : _thing (t) - , _property (p) - , _done (true) + ChangeSignal(T* thing_, P property_, ChangeType type_) + : thing(thing_) + , property(property_) + , type(type_) + {} + + T* thing; + P property; + ChangeType type; +}; + + +class ChangeSignalDespatcherBase +{ +protected: + static boost::mutex _instance_mutex; +}; + + +template +class ChangeSignalDespatcher : public ChangeSignalDespatcherBase +{ +public: + ChangeSignalDespatcher() = default; + + ChangeSignalDespatcher(ChangeSignalDespatcher const&) = delete; + ChangeSignalDespatcher& operator=(ChangeSignalDespatcher const&) = delete; + + void signal_change(ChangeSignal const& signal) { - _thing->signal_change (ChangeType::PENDING, _property); + if (_suspended) { + boost::mutex::scoped_lock lm(_mutex); + _pending.push_back(signal); + } else { + signal.thing->signal_change(signal.type, signal.property); + } } - ~ChangeSignaller () + void suspend() { - if (_done) { - _thing->signal_change (ChangeType::DONE, _property); - } else { - _thing->signal_change (ChangeType::CANCELLED, _property); + boost::mutex::scoped_lock lm(_mutex); + _suspended = true; + } + + void resume() + { + boost::mutex::scoped_lock lm(_mutex); + auto pending = _pending; + lm.unlock(); + + for (auto signal: pending) { + signal.thing->signal_change(signal.type, signal.property); + } + + lm.lock(); + _pending.clear(); + _suspended = false; + } + + static ChangeSignalDespatcher* instance() + { + static boost::mutex _instance_mutex; + static boost::mutex::scoped_lock lm(_instance_mutex); + static ChangeSignalDespatcher* _instance; + if (!_instance) { + _instance = new ChangeSignalDespatcher(); } + return _instance; + } + +private: + std::vector> _pending; + bool _suspended = false; + boost::mutex _mutex; +}; + + +template +class ChangeSignaller +{ +public: + ChangeSignaller (T* t, P p) + : _thing(t) + , _property(p) + , _done(true) + { + ChangeSignalDespatcher::instance()->signal_change({_thing, _property, ChangeType::PENDING}); + } + + ~ChangeSignaller () + { + ChangeSignalDespatcher::instance()->signal_change({_thing, _property, _done ? ChangeType::DONE : ChangeType::CANCELLED}); } void abort () @@ -51,8 +140,9 @@ public: private: T* _thing; - int _property; + P _property; bool _done; }; + #endif