]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/process/detail/posix/async_pipe.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / process / detail / posix / async_pipe.hpp
CommitLineData
b32b8144
FG
1// Copyright (c) 2016 Klemens D. Morgenstern
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_PIPE_HPP_
7#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_PIPE_HPP_
8
9
10#include <boost/process/detail/posix/basic_pipe.hpp>
11#include <boost/asio/posix/stream_descriptor.hpp>
92f5a8d4 12#include <boost/asio/post.hpp>
b32b8144
FG
13#include <system_error>
14#include <string>
15#include <utility>
16
17namespace boost { namespace process { namespace detail { namespace posix {
18
19class async_pipe
20{
21 ::boost::asio::posix::stream_descriptor _source;
22 ::boost::asio::posix::stream_descriptor _sink ;
23public:
24 typedef int native_handle_type;
25 typedef ::boost::asio::posix::stream_descriptor handle_type;
26
27 inline async_pipe(boost::asio::io_context & ios) : async_pipe(ios, ios) {}
28
29 inline async_pipe(boost::asio::io_context & ios_source,
30 boost::asio::io_context & ios_sink) : _source(ios_source), _sink(ios_sink)
31 {
32 int fds[2];
33 if (::pipe(fds) == -1)
34 boost::process::detail::throw_last_error("pipe(2) failed");
35
36 _source.assign(fds[0]);
37 _sink .assign(fds[1]);
38 };
39 inline async_pipe(boost::asio::io_context & ios, const std::string & name)
40 : async_pipe(ios, ios, name) {}
41
42 inline async_pipe(boost::asio::io_context & ios_source,
43 boost::asio::io_context & io_sink, const std::string & name);
44 inline async_pipe(const async_pipe& lhs);
45 async_pipe(async_pipe&& lhs) : _source(std::move(lhs._source)), _sink(std::move(lhs._sink))
46 {
47 lhs._source.assign (-1);
48 lhs._sink .assign (-1);
49 }
50
51 template<class CharT, class Traits = std::char_traits<CharT>>
52 explicit async_pipe(::boost::asio::io_context & ios_source,
53 ::boost::asio::io_context & ios_sink,
54 const basic_pipe<CharT, Traits> & p)
55 : _source(ios_source, p.native_source()), _sink(ios_sink, p.native_sink())
56 {
57 }
58
59 template<class CharT, class Traits = std::char_traits<CharT>>
60 explicit async_pipe(boost::asio::io_context & ios, const basic_pipe<CharT, Traits> & p)
61 : async_pipe(ios, ios, p)
62 {
63 }
64
65 template<class CharT, class Traits = std::char_traits<CharT>>
66 inline async_pipe& operator=(const basic_pipe<CharT, Traits>& p);
67 inline async_pipe& operator=(const async_pipe& rhs);
68
69 inline async_pipe& operator=(async_pipe&& lhs);
70
71 ~async_pipe()
72 {
73 if (_sink .native_handle() != -1)
74 ::close(_sink.native_handle());
75 if (_source.native_handle() != -1)
76 ::close(_source.native_handle());
77 }
78
79 template<class CharT, class Traits = std::char_traits<CharT>>
80 inline explicit operator basic_pipe<CharT, Traits>() const;
81
82 void cancel()
83 {
84 if (_sink.is_open())
85 _sink.cancel();
86 if (_source.is_open())
87 _source.cancel();
88 }
89
90 void close()
91 {
92 if (_sink.is_open())
93 _sink.close();
94 if (_source.is_open())
95 _source.close();
96 }
97 void close(boost::system::error_code & ec)
98 {
99 if (_sink.is_open())
100 _sink.close(ec);
101 if (_source.is_open())
102 _source.close(ec);
103 }
104
105
106 bool is_open() const
107 {
108 return _sink.is_open() || _source.is_open();
109 }
110 void async_close()
111 {
112 if (_sink.is_open())
92f5a8d4 113 boost::asio::post(_sink.get_executor(), [this]{_sink.close();});
b32b8144 114 if (_source.is_open())
92f5a8d4 115 boost::asio::post(_source.get_executor(), [this]{_source.close();});
b32b8144
FG
116 }
117
118 template<typename MutableBufferSequence>
119 std::size_t read_some(const MutableBufferSequence & buffers)
120 {
121 return _source.read_some(buffers);
122 }
123 template<typename MutableBufferSequence>
124 std::size_t write_some(const MutableBufferSequence & buffers)
125 {
126 return _sink.write_some(buffers);
127 }
128
11fdf7f2
TL
129 template<typename MutableBufferSequence>
130 std::size_t read_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
131 {
132 return _source.read_some(buffers, ec);
133 }
134 template<typename MutableBufferSequence>
135 std::size_t write_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept
136 {
137 return _sink.write_some(buffers, ec);
138 }
139
140
b32b8144
FG
141 native_handle_type native_source() const {return const_cast<boost::asio::posix::stream_descriptor&>(_source).native_handle();}
142 native_handle_type native_sink () const {return const_cast<boost::asio::posix::stream_descriptor&>(_sink ).native_handle();}
143
144 template<typename MutableBufferSequence,
145 typename ReadHandler>
146 BOOST_ASIO_INITFN_RESULT_TYPE(
147 ReadHandler, void(boost::system::error_code, std::size_t))
148 async_read_some(
149 const MutableBufferSequence & buffers,
150 ReadHandler &&handler)
151 {
92f5a8d4 152 return _source.async_read_some(buffers, std::forward<ReadHandler>(handler));
b32b8144
FG
153 }
154
155 template<typename ConstBufferSequence,
156 typename WriteHandler>
157 BOOST_ASIO_INITFN_RESULT_TYPE(
158 WriteHandler, void(boost::system::error_code, std::size_t))
159 async_write_some(
160 const ConstBufferSequence & buffers,
161 WriteHandler&& handler)
162 {
92f5a8d4 163 return _sink.async_write_some(buffers, std::forward<WriteHandler>(handler));
b32b8144
FG
164 }
165
166
167 const handle_type & sink () const & {return _sink;}
168 const handle_type & source() const & {return _source;}
169
170 handle_type && sink() && { return std::move(_sink); }
171 handle_type && source()&& { return std::move(_source); }
172
173 handle_type source(::boost::asio::io_context& ios) &&
174 {
175 ::boost::asio::posix::stream_descriptor stolen(ios, _source.release());
176 return stolen;
177 }
178 handle_type sink (::boost::asio::io_context& ios) &&
179 {
180 ::boost::asio::posix::stream_descriptor stolen(ios, _sink.release());
181 return stolen;
182 }
183
184 handle_type source(::boost::asio::io_context& ios) const &
185 {
186 auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle();
187 return ::boost::asio::posix::stream_descriptor(ios, ::dup(source_in));
188 }
189 handle_type sink (::boost::asio::io_context& ios) const &
190 {
191 auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle();
192 return ::boost::asio::posix::stream_descriptor(ios, ::dup(sink_in));
193 }
194};
195
196
197async_pipe::async_pipe(boost::asio::io_context & ios_source,
198 boost::asio::io_context & ios_sink,
199 const std::string & name) : _source(ios_source), _sink(ios_sink)
200{
201 auto fifo = mkfifo(name.c_str(), 0666 );
202
203 if (fifo != 0)
204 boost::process::detail::throw_last_error("mkfifo() failed");
205
206
207 int read_fd = open(name.c_str(), O_RDWR);
208
209 if (read_fd == -1)
210 boost::process::detail::throw_last_error();
211
212 int write_fd = dup(read_fd);
213
214 if (write_fd == -1)
215 boost::process::detail::throw_last_error();
216
217 _source.assign(read_fd);
218 _sink .assign(write_fd);
219}
220
221async_pipe::async_pipe(const async_pipe & p) :
92f5a8d4
TL
222 _source(const_cast<async_pipe&>(p)._source.get_executor()),
223 _sink( const_cast<async_pipe&>(p)._sink.get_executor())
b32b8144
FG
224{
225
226 //cannot get the handle from a const object.
227 auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle();
228 auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle();
229 if (source_in == -1)
230 _source.assign(-1);
231 else
232 {
233 _source.assign(::dup(source_in));
234 if (_source.native_handle()== -1)
235 ::boost::process::detail::throw_last_error("dup()");
236 }
237
238 if (sink_in == -1)
239 _sink.assign(-1);
240 else
241 {
242 _sink.assign(::dup(sink_in));
243 if (_sink.native_handle() == -1)
244 ::boost::process::detail::throw_last_error("dup()");
245 }
246}
247
248async_pipe& async_pipe::operator=(const async_pipe & p)
249{
250 int source;
251 int sink;
252
253 //cannot get the handle from a const object.
92f5a8d4
TL
254 auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(p._source).native_handle();
255 auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(p._sink).native_handle();
b32b8144
FG
256 if (source_in == -1)
257 source = -1;
258 else
259 {
260 source = ::dup(source_in);
261 if (source == -1)
262 ::boost::process::detail::throw_last_error("dup()");
263 }
264
265 if (sink_in == -1)
266 sink = -1;
267 else
268 {
269 sink = ::dup(sink_in);
270 if (sink == -1)
271 ::boost::process::detail::throw_last_error("dup()");
272 }
273 _source.assign(source);
274 _sink. assign(sink);
275
276 return *this;
277}
278
279async_pipe& async_pipe::operator=(async_pipe && lhs)
280{
281 std::swap(_source, lhs._source);
282 std::swap(_sink, lhs._sink);
283 return *this;
284}
285
286template<class CharT, class Traits>
287async_pipe::operator basic_pipe<CharT, Traits>() const
288{
289 int source;
290 int sink;
291
292 //cannot get the handle from a const object.
293 auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle();
294 auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle();
295
296
297 if (source_in == -1)
298 source = -1;
299 else
300 {
301 source = ::dup(source_in);
302 if (source == -1)
303 ::boost::process::detail::throw_last_error("dup()");
304 }
305
306 if (sink_in == -1)
307 sink = -1;
308 else
309 {
310 sink = ::dup(sink_in);
311 if (sink == -1)
312 ::boost::process::detail::throw_last_error("dup()");
313 }
314
315 return basic_pipe<CharT, Traits>{source, sink};
316}
317
318
319inline bool operator==(const async_pipe & lhs, const async_pipe & rhs)
320{
321 return compare_handles(lhs.native_source(), rhs.native_source()) &&
322 compare_handles(lhs.native_sink(), rhs.native_sink());
323}
324
325inline bool operator!=(const async_pipe & lhs, const async_pipe & rhs)
326{
327 return !compare_handles(lhs.native_source(), rhs.native_source()) ||
328 !compare_handles(lhs.native_sink(), rhs.native_sink());
329}
330
331template<class Char, class Traits>
332inline bool operator==(const async_pipe & lhs, const basic_pipe<Char, Traits> & rhs)
333{
334 return compare_handles(lhs.native_source(), rhs.native_source()) &&
335 compare_handles(lhs.native_sink(), rhs.native_sink());
336}
337
338template<class Char, class Traits>
339inline bool operator!=(const async_pipe & lhs, const basic_pipe<Char, Traits> & rhs)
340{
341 return !compare_handles(lhs.native_source(), rhs.native_source()) ||
342 !compare_handles(lhs.native_sink(), rhs.native_sink());
343}
344
345template<class Char, class Traits>
346inline bool operator==(const basic_pipe<Char, Traits> & lhs, const async_pipe & rhs)
347{
348 return compare_handles(lhs.native_source(), rhs.native_source()) &&
349 compare_handles(lhs.native_sink(), rhs.native_sink());
350}
351
352template<class Char, class Traits>
353inline bool operator!=(const basic_pipe<Char, Traits> & lhs, const async_pipe & rhs)
354{
355 return !compare_handles(lhs.native_source(), rhs.native_source()) ||
356 !compare_handles(lhs.native_sink(), rhs.native_sink());
357}
358
359}}}}
360
361#endif /* INCLUDE_BOOST_PIPE_DETAIL_WINDOWS_ASYNC_PIPE_HPP_ */