File indexing completed on 2025-01-18 09:50:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_OUT_HPP
0011 #define BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_OUT_HPP
0012
0013 #include <boost/winapi/process.hpp>
0014 #include <boost/winapi/handles.hpp>
0015 #include <boost/winapi/handle_info.hpp>
0016 #include <boost/winapi/error_codes.hpp>
0017 #include <boost/asio/read.hpp>
0018 #include <boost/process/detail/handler_base.hpp>
0019 #include <boost/process/detail/used_handles.hpp>
0020 #include <boost/process/detail/windows/asio_fwd.hpp>
0021
0022 #include <istream>
0023 #include <memory>
0024 #include <exception>
0025 #include <future>
0026
0027
0028 namespace boost { namespace process { namespace detail { namespace windows {
0029
0030
0031 template <typename Executor>
0032 inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 1>, std::integral_constant<int, -1>)
0033 {
0034 boost::winapi::SetHandleInformation(handle,
0035 boost::winapi::HANDLE_FLAG_INHERIT_,
0036 boost::winapi::HANDLE_FLAG_INHERIT_);
0037
0038 e.startup_info.hStdOutput = handle;
0039 e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
0040 e.inherit_handles = true;
0041 }
0042
0043 template <typename Executor>
0044 inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 2>, std::integral_constant<int, -1>)
0045 {
0046 boost::winapi::SetHandleInformation(handle,
0047 boost::winapi::HANDLE_FLAG_INHERIT_,
0048 boost::winapi::HANDLE_FLAG_INHERIT_);
0049
0050
0051 e.startup_info.hStdError = handle;
0052 e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
0053 e.inherit_handles = true;
0054 }
0055
0056 template <typename Executor>
0057 inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 1>, std::integral_constant<int, 2>)
0058 {
0059 boost::winapi::SetHandleInformation(handle,
0060 boost::winapi::HANDLE_FLAG_INHERIT_,
0061 boost::winapi::HANDLE_FLAG_INHERIT_);
0062
0063 e.startup_info.hStdOutput = handle;
0064 e.startup_info.hStdError = handle;
0065 e.startup_info.dwFlags |= ::boost::winapi::STARTF_USESTDHANDLES_;
0066 e.inherit_handles = true;
0067 }
0068
0069 template<int p1, int p2, typename Buffer>
0070 struct async_out_buffer : ::boost::process::detail::windows::handler_base_ext,
0071 ::boost::process::detail::windows::require_io_context
0072 {
0073 Buffer & buf;
0074
0075 std::shared_ptr<boost::process::async_pipe> pipe;
0076
0077
0078 async_out_buffer(Buffer & buf) : buf(buf)
0079 {
0080 }
0081 template <typename Executor>
0082 inline void on_success(Executor&)
0083 {
0084 auto pipe_ = this->pipe;
0085 boost::asio::async_read(*pipe_, buf,
0086 [pipe_](const boost::system::error_code&, std::size_t){});
0087 std::move(*pipe_).sink().close();
0088 this->pipe = nullptr;
0089
0090 }
0091
0092 template<typename Executor>
0093 void on_error(Executor &, const std::error_code &) const
0094 {
0095 std::move(*pipe).sink().close();
0096 }
0097
0098 template <typename WindowsExecutor>
0099 void on_setup(WindowsExecutor &exec)
0100 {
0101 if (!pipe)
0102 pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
0103 apply_out_handles(exec, std::move(*pipe).sink().native_handle(),
0104 std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
0105 }
0106 };
0107
0108
0109
0110 template<int p1, int p2, typename Type>
0111 struct async_out_future : ::boost::process::detail::windows::handler_base_ext,
0112 ::boost::process::detail::windows::require_io_context,
0113 ::boost::process::detail::uses_handles
0114 {
0115 std::shared_ptr<boost::process::async_pipe> pipe;
0116 std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>();
0117 std::shared_ptr<boost::asio::streambuf> buffer = std::make_shared<boost::asio::streambuf>();
0118
0119 ::boost::winapi::HANDLE_ get_used_handles() const
0120 {
0121 return std::move(*pipe).sink().native_handle();
0122 }
0123
0124
0125 async_out_future(std::future<Type> & fut)
0126 {
0127 fut = promise->get_future();
0128 }
0129 template <typename Executor>
0130 inline void on_success(Executor&)
0131 {
0132 auto pipe_ = this->pipe;
0133 auto buffer_ = this->buffer;
0134 auto promise_ = this->promise;
0135 std::move(*pipe_).sink().close();
0136 boost::asio::async_read(*pipe_, *buffer_,
0137 [pipe_, buffer_, promise_](const boost::system::error_code& ec, std::size_t)
0138 {
0139 if (ec && (ec.value() != ::boost::winapi::ERROR_BROKEN_PIPE_))
0140 {
0141 std::error_code e(ec.value(), std::system_category());
0142 promise_->set_exception(std::make_exception_ptr(process_error(e)));
0143 }
0144 else
0145 {
0146 std::istream is (buffer_.get());
0147 Type arg;
0148 if (buffer_->size() > 0)
0149 {
0150 arg.resize(buffer_->size());
0151 is.read(&*arg.begin(), buffer_->size());
0152 }
0153
0154 promise_->set_value(std::move(arg));
0155
0156
0157 }
0158 });
0159 this->pipe = nullptr;
0160 this->buffer = nullptr;
0161 this->promise = nullptr;
0162
0163
0164 }
0165
0166 template<typename Executor>
0167 void on_error(Executor &, const std::error_code &) const
0168 {
0169 std::move(*pipe).sink().close();
0170 }
0171
0172 template <typename WindowsExecutor>
0173 void on_setup(WindowsExecutor &exec)
0174 {
0175 if (!pipe)
0176 pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
0177
0178 apply_out_handles(exec, std::move(*pipe).sink().native_handle(),
0179 std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
0180 }
0181 };
0182
0183
0184 }}}}
0185
0186 #endif