)
: _film (film)
, _player (player)
- , _prepare_work (new boost::asio::io_service::work(_prepare_service))
+ , _prepare_work(dcpomatic::make_work_guard(_prepare_context))
, _pending_seek_accurate (false)
, _suspended (0)
, _finished (false)
LOG_TIMING("start-prepare-threads %1", boost::thread::hardware_concurrency() * 2);
for (size_t i = 0; i < boost::thread::hardware_concurrency() * 2; ++i) {
- _prepare_pool.create_thread (bind (&boost::asio::io_service::run, &_prepare_service));
+ _prepare_pool.create_thread(bind(&dcpomatic::io_context::run, &_prepare_context));
}
}
_prepare_work.reset ();
_prepare_pool.join_all ();
- _prepare_service.stop ();
+ _prepare_context.stop();
_thread.interrupt ();
try {
return;
}
- _prepare_service.post (bind(&Butler::prepare, this, weak_ptr<PlayerVideo>(video)));
+ dcpomatic::post(_prepare_context, bind(&Butler::prepare, this, weak_ptr<PlayerVideo>(video)));
_video.put (video, time);
}
#include "audio_ring_buffers.h"
#include "change_signaller.h"
#include "exception_store.h"
+#include "io_context.h"
#include "text_ring_buffers.h"
#include "text_type.h"
#include "video_ring_buffers.h"
TextRingBuffers _closed_caption;
boost::thread_group _prepare_pool;
- boost::asio::io_service _prepare_service;
- std::shared_ptr<boost::asio::io_service::work> _prepare_work;
+ dcpomatic::io_context _prepare_context;
+ boost::optional<dcpomatic::work_guard> _prepare_work;
/** mutex to protect _pending_seek_position, _pending_seek_accurate, _finished, _died, _stop_thread */
boost::mutex _mutex;
/** @param timeout Timeout in seconds */
Socket::Socket (int timeout)
- : _deadline (_io_service)
- , _socket (_io_service)
+ : _deadline(_io_context)
+ , _socket(_io_context)
, _timeout (timeout)
{
_deadline.expires_at (boost::posix_time::pos_infin);
boost::system::error_code ec = boost::asio::error::would_block;
_socket.async_connect (endpoint, boost::lambda::var(ec) = boost::lambda::_1);
do {
- _io_service.run_one();
+ _io_context.run_one();
} while (ec == boost::asio::error::would_block);
if (ec) {
void
Socket::connect(string host_name, int port)
{
- boost::asio::ip::tcp::resolver resolver(_io_service);
+ boost::asio::ip::tcp::resolver resolver(_io_context);
boost::asio::ip::tcp::resolver::query query(host_name, fmt::to_string(port));
connect(*resolver.resolve(query));
}
boost::asio::async_write (_socket, boost::asio::buffer (data, size), boost::lambda::var(ec) = boost::lambda::_1);
do {
- _io_service.run_one ();
+ _io_context.run_one();
} while (ec == boost::asio::error::would_block);
if (ec) {
boost::asio::async_read (_socket, boost::asio::buffer (data, size), boost::lambda::var(ec) = boost::lambda::_1);
do {
- _io_service.run_one ();
+ _io_context.run_one();
} while (ec == boost::asio::error::would_block);
if (ec) {
void
Socket::run()
{
- _io_service.run_one();
+ _io_context.run_one();
}
void
*/
+
#include "digester.h"
+#include "io_context.h"
#include <boost/asio.hpp>
#include <boost/scoped_ptr.hpp>
+
/** @class Socket
* @brief A class to wrap a boost::asio::ip::tcp::socket with some things
* that are useful for DCP-o-matic.
void finish_write_digest ();
void connect(boost::asio::ip::tcp::endpoint);
- boost::asio::io_service _io_service;
+ dcpomatic::io_context _io_context;
boost::asio::deadline_timer _deadline;
boost::asio::ip::tcp::socket _socket;
int _timeout;
}
}
- _broadcast.io_service.stop ();
+ _broadcast.io_context.stop();
try {
_broadcast.thread.join ();
} catch (...) {}
{
boost::asio::ip::udp::endpoint listen_endpoint(boost::asio::ip::udp::v4(), HELLO_PORT);
- _broadcast.socket = new boost::asio::ip::udp::socket(_broadcast.io_service, listen_endpoint);
+ _broadcast.socket = new boost::asio::ip::udp::socket(_broadcast.io_context, listen_endpoint);
_broadcast.socket->async_receive_from (
boost::asio::buffer (_broadcast.buffer, sizeof (_broadcast.buffer)),
boost::bind (&EncodeServer::broadcast_received, this)
);
- _broadcast.io_service.run ();
+ _broadcast.io_context.run();
}
catch (...)
{
boost::asio::ip::udp::socket* socket;
char buffer[64];
boost::asio::ip::udp::endpoint send_endpoint;
- boost::asio::io_service io_service;
+ dcpomatic::io_context io_context;
} _broadcast;
};
_search_thread.join();
} catch (...) {}
- _listen_io_service.stop ();
+ _listen_io_context.stop();
try {
_listen_thread.join ();
} catch (...) {}
start_of_thread ("EncodeServerFinder-search");
boost::system::error_code error;
- boost::asio::io_service io_service;
- boost::asio::ip::udp::socket socket (io_service);
+ dcpomatic::io_context io_context;
+ boost::asio::ip::udp::socket socket(io_context);
socket.open (boost::asio::ip::udp::v4(), error);
if (error) {
throw NetworkError ("failed to set up broadcast socket");
/* Query our `definite' servers (if there are any) */
for (auto const& i: Config::instance()->servers()) {
try {
- boost::asio::ip::udp::resolver resolver (io_service);
+ boost::asio::ip::udp::resolver resolver(io_context);
boost::asio::ip::udp::resolver::query query(i, fmt::to_string(HELLO_PORT));
boost::asio::ip::udp::endpoint end_point (*resolver.resolve(query));
socket.send_to (boost::asio::buffer(data.c_str(), data.size() + 1), end_point);
try {
_listen_acceptor.reset (
- new tcp::acceptor (_listen_io_service, tcp::endpoint(tcp::v4(), is_batch_converter ? BATCH_SERVER_PRESENCE_PORT : MAIN_SERVER_PRESENCE_PORT))
+ new tcp::acceptor(_listen_io_context, tcp::endpoint(tcp::v4(), is_batch_converter ? BATCH_SERVER_PRESENCE_PORT : MAIN_SERVER_PRESENCE_PORT))
);
} catch (...) {
boost::throw_exception(NetworkError(variant::insert_dcpomatic(_("Could not listen for remote encode servers. Perhaps another instance of %1 is running."))));
}
start_accept ();
- _listen_io_service.run ();
+ _listen_io_context.run();
}
catch (...)
{
/** Mutex for _servers */
mutable boost::mutex _servers_mutex;
- boost::asio::io_service _listen_io_service;
+ dcpomatic::io_context _listen_io_context;
std::shared_ptr<boost::asio::ip::tcp::acceptor> _listen_acceptor;
bool _stop;
--- /dev/null
+/*
+ Copyright (C) 2025 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 "io_context.h"
+
+
+dcpomatic::work_guard
+dcpomatic::make_work_guard(io_context& context)
+{
+#ifdef DCPOMATIC_HAVE_BOOST_ASIO_IO_CONTEXT
+ return boost::asio::make_work_guard(context);
+#else
+ return boost::asio::io_service::work(context);
+#endif
+}
--- /dev/null
+/*
+ Copyright (C) 2025 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_IO_CONTEXT_H
+#define DCPOMATIC_IO_CONTEXT_H
+
+
+#include <boost/asio.hpp>
+
+
+namespace dcpomatic {
+
+#ifdef DCPOMATIC_HAVE_BOOST_ASIO_IO_CONTEXT
+
+using io_context = boost::asio::io_context;
+using work_guard = boost::asio::executor_work_guard<boost::asio::io_context::executor_type>;
+
+template <typename T>
+void post(io_context& context, T handler)
+{
+ boost::asio::post(context, handler);
+}
+
+work_guard
+make_work_guard(io_context& context);
+
+#else
+
+using io_context = boost::asio::io_service;
+using work_guard = boost::asio::io_service::work;
+
+template <typename T>
+void post(io_context& context, T handler)
+{
+ context.post(handler);
+}
+
+work_guard
+make_work_guard(io_context& context);
+
+#endif
+
+}
+
+
+#endif
+
JSONServer::run (int port)
try
{
- boost::asio::io_service io_service;
- tcp::acceptor a (io_service, tcp::endpoint (tcp::v4 (), port));
+ dcpomatic::io_context io_context;
+ tcp::acceptor a(io_context, tcp::endpoint(tcp::v4(), port));
while (true) {
try {
- auto s = make_shared<tcp::socket>(io_service);
+ auto s = make_shared<tcp::socket>(io_context);
a.accept (*s);
handle (s);
}
Server::Server (int port, int timeout)
: _terminate (false)
- , _acceptor (_io_service, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port))
+ , _acceptor(_io_context, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port))
, _timeout (timeout)
{
Server::run ()
{
start_accept ();
- _io_service.run ();
+ _io_context.run();
}
if (auto s = _socket.lock()) {
s->close();
}
- _io_service.stop ();
+ _io_context.stop();
}
#define DCPOMATIC_SERVER_H
-#include <boost/thread.hpp>
+#include "io_context.h"
#include <boost/asio.hpp>
+#include <boost/thread.hpp>
#include <boost/thread/condition.hpp>
#include <string>
void start_accept ();
void handle_accept (std::shared_ptr<Socket>, boost::system::error_code const &);
- boost::asio::io_service _io_service;
+ dcpomatic::io_context _io_context;
boost::asio::ip::tcp::acceptor _acceptor;
int _timeout;
std::weak_ptr<Socket> _socket;
#include "exception_store.h"
+#include "io_context.h"
#include <boost/asio.hpp>
#include <boost/thread.hpp>
public:
/** Create a SignalManager. Must be called from the UI thread */
SignalManager ()
- : _work (_service)
+ : _work(dcpomatic::make_work_guard(_context))
{
_ui_thread = boost::this_thread::get_id ();
}
/* Do something next time the UI is idle */
template <typename T>
void when_idle (T f) {
- _service.post (f);
+ dcpomatic::post(_context, f);
}
/** Call this in the UI when it is idle.
* @return Number of idle handlers that were executed.
*/
size_t ui_idle () {
- /* This executes one of the functors that has been post()ed to _service */
- return _service.poll_one ();
+ /* This executes one of the functors that has been post()ed to _context */
+ return _context.poll_one();
}
/** This should wake the UI and make it call ui_idle() */
store_current ();
}
} else {
- /* non-UI thread; post to the service and wake up the UI */
- _service.post (f);
+ /* non-UI thread; post to the context and wake up the UI */
+ dcpomatic::post(_context, f);
wake_ui ();
}
}
friend class Signaller;
- /** A io_service which is used as the conduit for messages */
- boost::asio::io_service _service;
- /** Object required to keep io_service from stopping when it has nothing to do */
- boost::asio::io_service::work _work;
+ /** A io_context which is used as the conduit for messages */
+ dcpomatic::io_context _context;
+ /** Object required to keep io_context from stopping when it has nothing to do */
+ dcpomatic::work_guard _work;
/** The UI thread's ID */
boost::thread::id _ui_thread;
};
job->sub (_("Computing digests"));
}
- boost::asio::io_service service;
+ dcpomatic::io_context context;
boost::thread_group pool;
- auto work = make_shared<boost::asio::io_service::work>(service);
+ {
+ auto work = dcpomatic::make_work_guard(context);
- 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));
- }
+ for (int i = 0; i < threads; ++i) {
+ pool.create_thread(boost::bind(&dcpomatic::io_context::run, &context));
+ }
- std::function<void (int, int64_t, int64_t)> set_progress;
- if (job) {
- set_progress = boost::bind(&Writer::set_digest_progress, this, job.get(), _1, _2, _3);
- } else {
- set_progress = [](int, int64_t, int64_t) {
- boost::this_thread::interruption_point();
- };
- }
+ std::function<void (int, int64_t, int64_t)> set_progress;
+ if (job) {
+ set_progress = boost::bind(&Writer::set_digest_progress, this, job.get(), _1, _2, _3);
+ } else {
+ set_progress = [](int, int64_t, int64_t) {
+ boost::this_thread::interruption_point();
+ };
+ }
- int index = 0;
+ int index = 0;
- for (auto& i: _reels) {
- service.post(
- boost::bind(
- &ReelWriter::calculate_digests,
- &i,
+ for (auto& i: _reels) {
+ dcpomatic::post(context, boost::bind(
+ &ReelWriter::calculate_digests,
+ &i,
+ std::function<void (int64_t, int64_t)>(boost::bind(set_progress, index, _1, _2))
+ ));
+ ++index;
+ }
+ dcpomatic::post(context, boost::bind(
+ &Writer::calculate_referenced_digests,
+ this,
std::function<void (int64_t, int64_t)>(boost::bind(set_progress, index, _1, _2))
));
- ++index;
}
- service.post(
- boost::bind(
- &Writer::calculate_referenced_digests,
- this,
- std::function<void (int64_t, int64_t)>(boost::bind(set_progress, index, _1, _2))
- ));
-
- work.reset ();
try {
pool.join_all ();
pool.join_all ();
}
- service.stop ();
+ context.stop();
}
image_proxy.cc
image_store.cc
internal_player_server.cc
+ io_context.cc
j2k_image_proxy.cc
job.cc
job_manager.cc
#include "lib/cross.h"
#include "lib/ext.h"
+#include "lib/io_context.h"
#include "test.h"
#include <boost/algorithm/string.hpp>
#include <boost/asio.hpp>
{
using namespace boost::process;
- boost::asio::io_service ios;
+ dcpomatic::io_context ios;
future<string> data;
child ch (search_path("e2ls"), arguments, std_in.close(), std_out > data, ios);
ios.run();
BOOST_CHECK_EQUAL (system("/sbin/e2fsck -fn build/test/disk_writer_test1.partition"), 0);
{
- boost::asio::io_service ios;
+ dcpomatic::io_context ios;
future<string> data;
child ch ("/sbin/tune2fs", args({"-l", partition.string()}), std_in.close(), std_out > data, ios);
ios.run();
#include "lib/dcpomatic_socket.h"
+#include "lib/io_context.h"
#include "lib/server.h"
#include <fmt/format.h>
#include <boost/test/unit_test.hpp>
lib=deps,
uselib_store='BOOST_PROCESS')
+ conf.check_cxx(fragment="""
+ #include <boost/asio.hpp>
+ int main() { boost::asio::io_context context; }
+ """,
+ msg='Checking for boost::asio::io_context',
+ define_name='DCPOMATIC_HAVE_BOOST_ASIO_IO_CONTEXT',
+ mandatory=False)
+
# sqlite3
conf.check_cfg(package="sqlite3", args='--cflags --libs', uselib_store='SQLITE3', mandatory=True)
conf.check_cxx(fragment="""