145 lines
4.4 KiB
C++
145 lines
4.4 KiB
C++
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
// Copyright (c) 2009 Boris Schaeling
|
|
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
|
|
// Copyright (c) 2016 Klemens D. Morgenstern
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
/**
|
|
* \file boost/process/async_system.hpp
|
|
*
|
|
* Defines the asynchrounous version of the system function.
|
|
*/
|
|
|
|
#ifndef BOOST_PROCESS_ASYNC_SYSTEM_HPP
|
|
#define BOOST_PROCESS_ASYNC_SYSTEM_HPP
|
|
|
|
#include <boost/process/detail/config.hpp>
|
|
#include <boost/process/async.hpp>
|
|
#include <boost/process/child.hpp>
|
|
#include <boost/process/detail/async_handler.hpp>
|
|
#include <boost/process/detail/execute_impl.hpp>
|
|
#include <type_traits>
|
|
#include <memory>
|
|
#include <boost/asio/async_result.hpp>
|
|
#include <boost/asio/post.hpp>
|
|
#include <boost/system/error_code.hpp>
|
|
#include <tuple>
|
|
|
|
#if defined(BOOST_POSIX_API)
|
|
#include <boost/process/posix.hpp>
|
|
#endif
|
|
|
|
namespace boost {
|
|
namespace process {
|
|
namespace detail
|
|
{
|
|
|
|
template<typename ExitHandler>
|
|
struct async_system_handler : ::boost::process::detail::api::async_handler
|
|
{
|
|
boost::asio::io_context & ios;
|
|
boost::asio::async_completion<
|
|
ExitHandler, void(boost::system::error_code, int)> init;
|
|
|
|
#if defined(BOOST_POSIX_API)
|
|
bool errored = false;
|
|
#endif
|
|
|
|
template<typename ExitHandler_>
|
|
async_system_handler(
|
|
boost::asio::io_context & ios,
|
|
ExitHandler_ && exit_handler) : ios(ios), init(exit_handler)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
template<typename Exec>
|
|
void on_error(Exec&, const std::error_code & ec)
|
|
{
|
|
#if defined(BOOST_POSIX_API)
|
|
errored = true;
|
|
#endif
|
|
auto & h = init.completion_handler;
|
|
boost::asio::post(
|
|
ios.get_executor(),
|
|
[h, ec]() mutable
|
|
{
|
|
h(boost::system::error_code(ec.value(), boost::system::system_category()), -1);
|
|
});
|
|
}
|
|
|
|
BOOST_ASIO_INITFN_RESULT_TYPE(ExitHandler, void (boost::system::error_code, int))
|
|
get_result()
|
|
{
|
|
return init.result.get();
|
|
}
|
|
|
|
template<typename Executor>
|
|
std::function<void(int, const std::error_code&)> on_exit_handler(Executor&)
|
|
{
|
|
#if defined(BOOST_POSIX_API)
|
|
if (errored)
|
|
return [](int , const std::error_code &){};
|
|
#endif
|
|
auto & h = init.completion_handler;
|
|
return [h](int exit_code, const std::error_code & ec) mutable
|
|
{
|
|
h(boost::system::error_code(ec.value(), boost::system::system_category()), exit_code);
|
|
};
|
|
}
|
|
};
|
|
|
|
|
|
template<typename ExitHandler>
|
|
struct is_error_handler<async_system_handler<ExitHandler>> : std::true_type {};
|
|
|
|
}
|
|
|
|
/** This function provides an asynchronous interface to process launching.
|
|
|
|
It uses the same properties and parameters as the other launching function,
|
|
but is similar to the asynchronous functions in [boost.asio](http://www.boost.org/doc/libs/release/doc/html/boost_asio.html)
|
|
|
|
It uses [asio::async_result](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/async_result.html) to determine
|
|
the return value (from the second parameter, `exit_handler`).
|
|
|
|
\param ios A reference to an [io_context](http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference.html)
|
|
\param exit_handler The exit-handler for the signature `void(boost::system::error_code, int)`
|
|
|
|
\note This function does not allow custom error handling, since those are done through the `exit_handler`.
|
|
|
|
*/
|
|
#if defined(BOOST_PROCESS_DOXYGEN)
|
|
template<typename ExitHandler, typename ...Args>
|
|
inline boost::process::detail::dummy
|
|
async_system(boost::asio::io_context & ios, ExitHandler && exit_handler, Args && ...args);
|
|
#endif
|
|
|
|
template<typename ExitHandler, typename ...Args>
|
|
inline BOOST_ASIO_INITFN_RESULT_TYPE(ExitHandler, void (boost::system::error_code, int))
|
|
async_system(boost::asio::io_context & ios, ExitHandler && exit_handler, Args && ...args)
|
|
{
|
|
detail::async_system_handler<ExitHandler> async_h{ios, std::forward<ExitHandler>(exit_handler)};
|
|
|
|
typedef typename ::boost::process::detail::has_error_handler<boost::fusion::tuple<Args...>>::type
|
|
has_err_handling;
|
|
|
|
static_assert(!has_err_handling::value, "async_system cannot have custom error handling");
|
|
|
|
|
|
child(ios, std::forward<Args>(args)..., async_h ).detach();
|
|
|
|
return async_h.get_result();
|
|
}
|
|
|
|
|
|
|
|
}}
|
|
#endif
|
|
|