Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:07

0001 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
0002 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
0003 // Copyright (c) 2009 Boris Schaeling
0004 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
0005 // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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