Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / process / detail / windows / async_out.hpp
1 // Copyright (c) 2006, 2007 Julio M. Merino Vidal\r
2 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling\r
3 // Copyright (c) 2009 Boris Schaeling\r
4 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling\r
5 // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling\r
6 //\r
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying\r
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\r
9
10 #ifndef BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_OUT_HPP\r
11 #define BOOST_PROCESS_WINDOWS_INITIALIZERS_ASYNC_OUT_HPP\r
12
13 #include <boost/detail/winapi/process.hpp>\r
14 #include <boost/detail/winapi/handles.hpp>\r
15 #include <boost/detail/winapi/handle_info.hpp>\r
16 #include <boost/asio/read.hpp>\r
17 #include <boost/process/detail/handler_base.hpp>\r
18 #include <boost/process/detail/windows/asio_fwd.hpp>\r
19 #include <boost/detail/winapi/error_codes.hpp>\r
20
21 #include <istream>\r
22 #include <memory>\r
23 #include <exception>\r
24 #include <future>\r
25
26
27 namespace boost { namespace process { namespace detail { namespace windows {\r
28
29
30 template <typename Executor>\r
31 inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 1>, std::integral_constant<int, -1>)\r
32 {\r
33     boost::detail::winapi::SetHandleInformation(handle,\r
34             boost::detail::winapi::HANDLE_FLAG_INHERIT_,\r
35             boost::detail::winapi::HANDLE_FLAG_INHERIT_);\r
36
37     e.startup_info.hStdOutput = handle;\r
38     e.startup_info.dwFlags   |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;\r
39     e.inherit_handles = true;\r
40 }\r
41
42 template <typename Executor>\r
43 inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 2>, std::integral_constant<int, -1>)\r
44 {\r
45     boost::detail::winapi::SetHandleInformation(handle,\r
46             boost::detail::winapi::HANDLE_FLAG_INHERIT_,\r
47             boost::detail::winapi::HANDLE_FLAG_INHERIT_);\r
48
49
50     e.startup_info.hStdError = handle;\r
51     e.startup_info.dwFlags  |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;\r
52     e.inherit_handles = true;\r
53 }\r
54
55 template <typename Executor>\r
56 inline void apply_out_handles(Executor &e, void* handle, std::integral_constant<int, 1>, std::integral_constant<int, 2>)\r
57 {\r
58     boost::detail::winapi::SetHandleInformation(handle,\r
59             boost::detail::winapi::HANDLE_FLAG_INHERIT_,\r
60             boost::detail::winapi::HANDLE_FLAG_INHERIT_);\r
61
62     e.startup_info.hStdOutput = handle;\r
63     e.startup_info.hStdError  = handle;\r
64     e.startup_info.dwFlags   |= ::boost::detail::winapi::STARTF_USESTDHANDLES_;\r
65     e.inherit_handles = true;\r
66 }\r
67
68 template<int p1, int p2, typename Buffer>\r
69 struct async_out_buffer : ::boost::process::detail::windows::handler_base_ext,\r
70                           ::boost::process::detail::windows::require_io_service\r
71 {\r
72     Buffer & buf;\r
73
74     std::shared_ptr<boost::process::async_pipe> pipe;\r
75
76
77     async_out_buffer(Buffer & buf) : buf(buf)\r
78     {\r
79     }\r
80     template <typename Executor>\r
81     inline void on_success(Executor&)\r
82     {\r
83         auto pipe = this->pipe;\r
84         boost::asio::async_read(*pipe, buf,\r
85                 [pipe](const boost::system::error_code&, std::size_t){});\r
86         std::move(*pipe).sink().close();\r
87         this->pipe       = nullptr;\r
88
89     }\r
90
91     template<typename Executor>\r
92     void on_error(Executor &, const std::error_code &) const\r
93     {\r
94         std::move(*pipe).sink().close();\r
95     }\r
96
97     template <typename WindowsExecutor>\r
98     void on_setup(WindowsExecutor &exec)\r
99     {\r
100         if (!pipe)\r
101             pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));\r
102         apply_out_handles(exec, std::move(*pipe).sink().native_handle(),\r
103                 std::integral_constant<int, p1>(), std::integral_constant<int, p2>());\r
104     }\r
105 };\r
106
107
108
109 template<int p1, int p2, typename Type>\r
110 struct async_out_future : ::boost::process::detail::windows::handler_base_ext,\r
111                           ::boost::process::detail::windows::require_io_service\r
112 {\r
113     std::shared_ptr<boost::process::async_pipe> pipe;\r
114     std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>();\r
115     std::shared_ptr<boost::asio::streambuf> buffer = std::make_shared<boost::asio::streambuf>();\r
116
117
118     async_out_future(std::future<Type> & fut)\r
119     {\r
120         fut = promise->get_future();\r
121     }\r
122     template <typename Executor>\r
123     inline void on_success(Executor&)\r
124     {\r
125         auto pipe    = this->pipe;\r
126         auto buffer  = this->buffer;\r
127         auto promise = this->promise;\r
128         std::move(*pipe).sink().close();\r
129         boost::asio::async_read(*pipe, *buffer,\r
130                 [pipe, buffer, promise](const boost::system::error_code& ec, std::size_t)\r
131                 {\r
132                     if (ec && (ec.value() != ::boost::detail::winapi::ERROR_BROKEN_PIPE_))\r
133                     {\r
134                         std::error_code e(ec.value(), std::system_category());\r
135                         promise->set_exception(std::make_exception_ptr(process_error(e)));\r
136                     }\r
137                     else\r
138                     {\r
139                         std::istream is (buffer.get());\r
140                         Type arg;\r
141                         arg.resize(buffer->size());\r
142                         is.read(&*arg.begin(), buffer->size());\r
143
144                         promise->set_value(std::move(arg));\r
145
146
147                     }\r
148                 });\r
149         this->pipe       = nullptr;\r
150         this->buffer  = nullptr;\r
151         this->promise = nullptr;\r
152
153
154     }\r
155
156     template<typename Executor>\r
157     void on_error(Executor &, const std::error_code &) const\r
158     {\r
159         std::move(*pipe).sink().close();\r
160     }\r
161
162     template <typename WindowsExecutor>\r
163     void on_setup(WindowsExecutor &exec)\r
164     {\r
165         if (!pipe)\r
166             pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));\r
167
168         apply_out_handles(exec, std::move(*pipe).sink().native_handle(),\r
169                 std::integral_constant<int, p1>(), std::integral_constant<int, p2>());\r
170     }\r
171 };\r
172
173
174 }}}}\r
175
176 #endif\r