summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2023-05-09 01:33:45 +0200
committerCarl Hetherington <cth@carlh.net>2023-05-10 21:35:46 +0200
commit0f11f0c25465464b28db713cccd37d7d8de483e1 (patch)
tree415dc88b05b951f5d590d0c41b52503fd8fd3da5
parentb168d211622f94a5240c945c1df03b0bed48d3bc (diff)
Allow signals to be blocked and resumed, and so make sure that a set
of content changes taken from an examiner are handled at the same time. Should fix DoM #2523.
-rw-r--r--src/lib/change_signaller.cc24
-rw-r--r--src/lib/change_signaller.h102
-rw-r--r--src/lib/content.h3
-rw-r--r--src/lib/dcp_content.cc8
-rw-r--r--src/lib/film.h2
-rw-r--r--src/lib/wscript1
6 files changed, 125 insertions, 15 deletions
diff --git a/src/lib/change_signaller.cc b/src/lib/change_signaller.cc
new file mode 100644
index 000000000..a1f093d14
--- /dev/null
+++ b/src/lib/change_signaller.cc
@@ -0,0 +1,24 @@
+/*
+ Copyright (C) 2018-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/>.
+
+*/
+
+
+#include "change_signaller.h"
+
+
diff --git a/src/lib/change_signaller.h b/src/lib/change_signaller.h
index 8612cf426..1d7d482df 100644
--- a/src/lib/change_signaller.h
+++ b/src/lib/change_signaller.h
@@ -23,6 +23,10 @@
#define DCPOMATIC_CHANGE_SIGNALLER_H
+#include <boost/thread.hpp>
+#include <vector>
+
+
enum class ChangeType
{
PENDING,
@@ -32,29 +36,103 @@ enum class ChangeType
template <class T, class P>
+class ChangeSignal
+{
+public:
+ 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 T, class P>
+class ChangeSignalDespatcher : public ChangeSignalDespatcherBase
+{
+public:
+ ChangeSignalDespatcher() = default;
+
+ ChangeSignalDespatcher(ChangeSignalDespatcher const&) = delete;
+ ChangeSignalDespatcher& operator=(ChangeSignalDespatcher const&) = delete;
+
+ void signal_change(ChangeSignal<T, P> const& signal)
+ {
+ if (_suspended) {
+ boost::mutex::scoped_lock lm(_mutex);
+ _pending.push_back(signal);
+ } else {
+ signal.thing->signal_change(signal.type, signal.property);
+ }
+ }
+
+ void suspend()
+ {
+ 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<T, P>* _instance;
+ if (!_instance) {
+ _instance = new ChangeSignalDespatcher<T, P>();
+ }
+ return _instance;
+ }
+
+private:
+ std::vector<ChangeSignal<T, P>> _pending;
+ bool _suspended = false;
+ boost::mutex _mutex;
+};
+
+
+template <class T, class P>
class ChangeSignaller
{
public:
ChangeSignaller (T* t, P p)
- : _thing (t)
- , _property (p)
- , _done (true)
+ : _thing(t)
+ , _property(p)
+ , _done(true)
{
- _thing->signal_change (ChangeType::PENDING, _property);
+ ChangeSignalDespatcher<T, P>::instance()->signal_change({_thing, _property, ChangeType::PENDING});
}
~ChangeSignaller ()
{
- if (_done) {
- _thing->signal_change (ChangeType::DONE, _property);
- } else {
- _thing->signal_change (ChangeType::CANCELLED, _property);
- }
+ ChangeSignalDespatcher<T, P>::instance()->signal_change({_thing, _property, _done ? ChangeType::DONE : ChangeType::CANCELLED});
}
- ChangeSignaller (ChangeSignaller const&) = delete;
- ChangeSignaller& operator= (ChangeSignaller const&) = delete;
-
void abort ()
{
_done = false;
diff --git a/src/lib/content.h b/src/lib/content.h
index 0ce87ed9b..f2fecddf0 100644
--- a/src/lib/content.h
+++ b/src/lib/content.h
@@ -234,7 +234,7 @@ private:
friend struct best_dcp_frame_rate_test_double;
friend struct audio_sampling_rate_test;
friend struct subtitle_font_id_change_test2;
- template<class, class> friend class ChangeSignaller;
+ template<class, class> friend class ChangeSignalDespatcher;
void signal_change (ChangeType, int);
@@ -256,6 +256,7 @@ private:
typedef ChangeSignaller<Content, int> ContentChangeSignaller;
+typedef ChangeSignalDespatcher<Content, int> ContentChangeSignalDespatcher;
#endif
diff --git a/src/lib/dcp_content.cc b/src/lib/dcp_content.cc
index 231a93bd0..cad775b24 100644
--- a/src/lib/dcp_content.cc
+++ b/src/lib/dcp_content.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2014-2022 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014-2023 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
@@ -31,6 +31,7 @@
#include "job.h"
#include "log.h"
#include "overlaps.h"
+#include "scope_guard.h"
#include "text_content.h"
#include "video_content.h"
#include <dcp/dcp.h>
@@ -213,6 +214,11 @@ DCPContent::examine (shared_ptr<const Film> film, shared_ptr<Job> job)
bool const needed_kdm = needs_kdm ();
string const old_name = name ();
+ ContentChangeSignalDespatcher::instance()->suspend();
+ ScopeGuard sg = []() {
+ ContentChangeSignalDespatcher::instance()->resume();
+ };
+
ContentChangeSignaller cc_texts (this, DCPContentProperty::TEXTS);
ContentChangeSignaller cc_assets (this, DCPContentProperty::NEEDS_ASSETS);
ContentChangeSignaller cc_kdm (this, DCPContentProperty::NEEDS_KDM);
diff --git a/src/lib/film.h b/src/lib/film.h
index b7a9f94ac..958c388b3 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -492,7 +492,7 @@ private:
friend struct ::isdcf_name_with_atmos;
friend struct ::recover_test_2d_encrypted;
friend struct ::atmos_encrypted_passthrough_test;
- template <class, class> friend class ChangeSignaller;
+ template <class, class> friend class ChangeSignalDespatcher;
boost::filesystem::path info_file (dcpomatic::DCPTimePeriod p) const;
diff --git a/src/lib/wscript b/src/lib/wscript
index f8c2d5dc2..de7b947c2 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -51,6 +51,7 @@ sources = """
check_content_job.cc
cinema.cc
cinema_sound_processor.cc
+ change_signaller.cc
collator.cc
colour_conversion.cc
config.cc