using namespace dcpomatic;
-static
-void
-ignore_progress (float)
-{
-
-}
-
-
/** @param j Job to report progress to, or 0.
* @param text_only true to enable only the text (subtitle/ccap) parts of the writer.
*/
Writer::thread ()
try
{
+ start_of_thread ("Writer");
+
while (true)
{
boost::mutex::scoped_lock lock (_state_mutex);
}
-/** @param output_dcp Path to DCP folder to write */
void
-Writer::finish (boost::filesystem::path output_dcp)
+Writer::calculate_digests ()
{
- if (_thread.joinable()) {
- LOG_GENERAL_NC ("Terminating writer thread");
- terminate_thread (true);
- }
-
- LOG_GENERAL_NC ("Finishing ReelWriters");
-
- for (auto& i: _reels) {
- write_hanging_text (i);
- i.finish (output_dcp);
- }
-
- LOG_GENERAL_NC ("Writing XML");
-
- dcp::DCP dcp (output_dcp);
-
- auto cpl = make_shared<dcp::CPL>(
- film()->dcp_name(),
- film()->dcp_content_type()->libdcp_kind()
- );
-
- dcp.add (cpl);
-
- /* Calculate digests for each reel in parallel */
-
auto job = _job.lock ();
if (job) {
job->sub (_("Computing digests"));
auto work = make_shared<boost::asio::io_service::work>(service);
- int const threads = max (1, Config::instance()->master_encoding_threads ());
+ int const threads = max (1, Config::instance()->master_encoding_threads());
for (int i = 0; i < threads; ++i) {
pool.create_thread (boost::bind (&boost::asio::io_service::run, &service));
}
- boost::function<void (float)> set_progress;
+ std::function<void (float)> set_progress;
if (job) {
set_progress = boost::bind (&Writer::set_digest_progress, this, job.get(), _1);
} else {
- set_progress = &ignore_progress;
+ set_progress = [](float) {
+ boost::this_thread::interruption_point();
+ };
}
for (auto& i: _reels) {
service.post (boost::bind (&Writer::calculate_referenced_digests, this, set_progress));
work.reset ();
- pool.join_all ();
+
+ try {
+ pool.join_all ();
+ } catch (boost::thread_interrupted) {
+ /* join_all was interrupted, so we need to interrupt the threads
+ * in our pool then try again to join them.
+ */
+ pool.interrupt_all ();
+ pool.join_all ();
+ }
+
service.stop ();
+}
+
+
+/** @param output_dcp Path to DCP folder to write */
+void
+Writer::finish (boost::filesystem::path output_dcp)
+{
+ if (_thread.joinable()) {
+ LOG_GENERAL_NC ("Terminating writer thread");
+ terminate_thread (true);
+ }
+
+ LOG_GENERAL_NC ("Finishing ReelWriters");
+
+ for (auto& i: _reels) {
+ write_hanging_text (i);
+ i.finish (output_dcp);
+ }
+
+ LOG_GENERAL_NC ("Writing XML");
+
+ dcp::DCP dcp (output_dcp);
+
+ auto cpl = make_shared<dcp::CPL>(
+ film()->dcp_name(),
+ film()->dcp_content_type()->libdcp_kind(),
+ film()->interop() ? dcp::Standard::INTEROP : dcp::Standard::SMPTE
+ );
+
+ dcp.add (cpl);
+
+ calculate_digests ();
/* Add reels */
}
dcp.write_xml (
- film()->interop() ? dcp::Standard::INTEROP : dcp::Standard::SMPTE,
issuer,
creator,
dcp::LocalTime().as_string(),
Waker waker;
waker.nudge ();
+
+ boost::this_thread::interruption_point();
}
/** Calculate hashes for any referenced MXF assets which do not already have one */
void
-Writer::calculate_referenced_digests (boost::function<void (float)> set_progress)
+Writer::calculate_referenced_digests (std::function<void (float)> set_progress)
+try
{
for (auto const& i: _reel_assets) {
auto file = dynamic_pointer_cast<dcp::ReelFileAsset>(i.asset);
file->set_hash (file->asset_ref().asset()->hash());
}
}
+} catch (boost::thread_interrupted) {
+ /* set_progress contains an interruption_point, so any of these methods
+ * may throw thread_interrupted, at which point we just give up.
+ */
}