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