File indexing completed on 2025-01-18 09:50:13
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef BOOST_PROCESS_ASYNC_SYSTEM_HPP
0018 #define BOOST_PROCESS_ASYNC_SYSTEM_HPP
0019
0020 #include <boost/process/detail/config.hpp>
0021 #include <boost/process/async.hpp>
0022 #include <boost/process/child.hpp>
0023 #include <boost/process/detail/async_handler.hpp>
0024 #include <boost/process/detail/execute_impl.hpp>
0025 #include <type_traits>
0026 #include <memory>
0027 #include <boost/asio/async_result.hpp>
0028 #include <boost/asio/post.hpp>
0029 #include <boost/system/error_code.hpp>
0030 #include <tuple>
0031
0032 #if defined(BOOST_POSIX_API)
0033 #include <boost/process/posix.hpp>
0034 #endif
0035
0036 namespace boost {
0037 namespace process {
0038 namespace detail
0039 {
0040
0041 template<typename Handler>
0042 struct async_system_handler : ::boost::process::detail::api::async_handler
0043 {
0044 boost::asio::io_context & ios;
0045 Handler handler;
0046
0047 #if defined(BOOST_POSIX_API)
0048 bool errored = false;
0049 #endif
0050
0051 template<typename ExitHandler_>
0052 async_system_handler(
0053 boost::asio::io_context & ios,
0054 ExitHandler_ && exit_handler) : ios(ios), handler(std::forward<ExitHandler_>(exit_handler))
0055 {
0056 }
0057
0058
0059 template<typename Exec>
0060 void on_error(Exec&, const std::error_code & ec)
0061 {
0062 #if defined(BOOST_POSIX_API)
0063 errored = true;
0064 #endif
0065 auto h = std::make_shared<Handler>(std::move(handler));
0066 boost::asio::post(
0067 ios.get_executor(),
0068 [h, ec]() mutable
0069 {
0070 (*h)(boost::system::error_code(ec.value(), boost::system::system_category()), -1);
0071 });
0072 }
0073
0074 template<typename Executor>
0075 std::function<void(int, const std::error_code&)> on_exit_handler(Executor&)
0076 {
0077 #if defined(BOOST_POSIX_API)
0078 if (errored)
0079 return [](int , const std::error_code &){};
0080 #endif
0081 auto h = std::make_shared<Handler>(std::move(handler));
0082 return [h](int exit_code, const std::error_code & ec) mutable
0083 {
0084 (*h)(boost::system::error_code(ec.value(), boost::system::system_category()), exit_code);
0085 };
0086 }
0087 };
0088
0089
0090 template<typename ExitHandler>
0091 struct is_error_handler<async_system_handler<ExitHandler>> : std::true_type {};
0092
0093 }
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 #if defined(BOOST_PROCESS_DOXYGEN)
0110 template<typename ExitHandler, typename ...Args>
0111 inline boost::process::detail::dummy
0112 async_system(boost::asio::io_context & ios, ExitHandler && exit_handler, Args && ...args);
0113 #endif
0114
0115 namespace detail
0116 {
0117 struct async_system_init_op
0118 {
0119
0120 template<typename Handler, typename ... Args>
0121 void operator()(Handler && handler, asio::io_context & ios, Args && ... args)
0122 {
0123 detail::async_system_handler<typename std::decay<Handler>::type> async_h{ios, std::forward<Handler>(handler)};
0124 child(ios, std::forward<Args>(args)..., async_h ).detach();
0125 }
0126 };
0127
0128
0129 }
0130
0131
0132 template<typename ExitHandler, typename ...Args>
0133 inline BOOST_ASIO_INITFN_RESULT_TYPE(ExitHandler, void (boost::system::error_code, int))
0134 async_system(boost::asio::io_context & ios, ExitHandler && exit_handler, Args && ...args)
0135 {
0136
0137 typedef typename ::boost::process::detail::has_error_handler<boost::fusion::tuple<Args...>>::type
0138 has_err_handling;
0139
0140 static_assert(!has_err_handling::value, "async_system cannot have custom error handling");
0141
0142 return boost::asio::async_initiate<ExitHandler, void (boost::system::error_code, int)>(
0143 detail::async_system_init_op{}, exit_handler, ios, std::forward<Args>(args)...
0144 );
0145 }
0146
0147
0148
0149 }}
0150 #endif
0151