diff options
Diffstat (limited to 'boost/process/async_system.hpp')
-rw-r--r-- | boost/process/async_system.hpp | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/boost/process/async_system.hpp b/boost/process/async_system.hpp new file mode 100644 index 0000000000..f92b417d2e --- /dev/null +++ b/boost/process/async_system.hpp @@ -0,0 +1,142 @@ +// 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/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_service & ios; + boost::asio::detail::async_result_init< + 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_service & ios, + ExitHandler_ && exit_handler) : ios(ios), init(std::forward<ExitHandler_>(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.handler; + ios.post( + [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 exit_code, const std::error_code & ec){}; +#endif + auto & h = init.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_service](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_service & 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_service & 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 + |