]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/process/detail/child_decl.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / process / detail / child_decl.hpp
1 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
2 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
3 // Copyright (c) 2009 Boris Schaeling
4 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
5 // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
6 // Copyright (c) 2016 Klemens D. Morgenstern
7 //
8 // Distributed under the Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10
11 /**
12 * \file boost/process/child.hpp
13 *
14 * Defines a child process class.
15 */
16
17 #ifndef BOOST_PROCESS_CHILD_DECL_HPP
18 #define BOOST_PROCESS_CHILD_DECL_HPP
19
20 #include <boost/process/detail/config.hpp>
21 #include <chrono>
22 #include <memory>
23
24 #include <boost/none.hpp>
25 #include <atomic>
26
27 #if defined(BOOST_POSIX_API)
28 #include <boost/process/detail/posix/child_handle.hpp>
29 #include <boost/process/detail/posix/terminate.hpp>
30 #include <boost/process/detail/posix/wait_for_exit.hpp>
31 #include <boost/process/detail/posix/is_running.hpp>
32 #elif defined(BOOST_WINDOWS_API)
33 #include <boost/process/detail/windows/child_handle.hpp>
34 #include <boost/process/detail/windows/terminate.hpp>
35 #include <boost/process/detail/windows/wait_for_exit.hpp>
36 #include <boost/process/detail/windows/is_running.hpp>
37
38 #endif
39 namespace boost {
40
41 namespace process {
42
43 using ::boost::process::detail::api::pid_t;
44
45 class child
46 {
47 ::boost::process::detail::api::child_handle _child_handle;
48 std::shared_ptr<std::atomic<int>> _exit_status = std::make_shared<std::atomic<int>>(::boost::process::detail::api::still_active);
49 bool _attached = true;
50 bool _terminated = false;
51
52 bool _exited()
53 {
54 return _terminated || !::boost::process::detail::api::is_running(_exit_status->load());
55 };
56 public:
57 typedef ::boost::process::detail::api::child_handle child_handle;
58 typedef child_handle::process_handle_t native_handle_t;
59 explicit child(child_handle &&ch, std::shared_ptr<std::atomic<int>> &ptr) : _child_handle(std::move(ch)), _exit_status(ptr) {}
60 explicit child(child_handle &&ch, const std::shared_ptr<std::atomic<int>> &ptr) : _child_handle(std::move(ch)), _exit_status(ptr) {}
61 explicit child(child_handle &&ch) : _child_handle(std::move(ch)) {}
62
63 explicit child(pid_t & pid) : _child_handle(pid), _attached(false) {};
64 child(const child&) = delete;
65 child(child && lhs) noexcept
66 : _child_handle(std::move(lhs._child_handle)),
67 _exit_status(std::move(lhs._exit_status)),
68 _attached (lhs._attached),
69 _terminated (lhs._terminated)
70 {
71 lhs._attached = false;
72 }
73
74 template<typename ...Args>
75 explicit child(Args&&...args);
76 child() {}
77 child& operator=(const child&) = delete;
78 child& operator=(child && lhs)
79 {
80 _child_handle= std::move(lhs._child_handle);
81 _exit_status = std::move(lhs._exit_status);
82 _attached = lhs._attached;
83 _terminated = lhs._terminated;
84 lhs._attached = false;
85 return *this;
86 };
87
88 void detach() {_attached = false; }
89 void join() {wait();}
90 bool joinable() { return _attached;}
91
92 ~child()
93 {
94 std::error_code ec;
95 if (_attached && !_exited() && running(ec))
96 terminate(ec);
97 }
98 native_handle_t native_handle() const { return _child_handle.process_handle(); }
99
100
101 int exit_code() const {return ::boost::process::detail::api::eval_exit_status(_exit_status->load());}
102 pid_t id() const {return _child_handle.id(); }
103
104 bool running()
105 {
106 if (valid() && !_exited())
107 {
108 int code = -1;
109 auto res = boost::process::detail::api::is_running(_child_handle, code);
110 if (!res && !_exited())
111 _exit_status->store(code);
112
113 return res;
114 }
115 return false;
116 }
117
118 void terminate()
119 {
120 if (valid() && running())
121 boost::process::detail::api::terminate(_child_handle);
122
123 _terminated = true;
124 }
125
126 void wait()
127 {
128 if (!_exited() && valid())
129 {
130 int exit_code = 0;
131 boost::process::detail::api::wait(_child_handle, exit_code);
132 _exit_status->store(exit_code);
133 }
134 }
135
136 template< class Rep, class Period >
137 bool wait_for (const std::chrono::duration<Rep, Period>& rel_time)
138 {
139 if (!_exited())
140 {
141 int exit_code = 0;
142 auto b = boost::process::detail::api::wait_for(_child_handle, exit_code, rel_time);
143 if (!b)
144 return false;
145 _exit_status->store(exit_code);
146 }
147 return true;
148 }
149
150 template< class Clock, class Duration >
151 bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time )
152 {
153 if (!_exited())
154 {
155 int exit_code = 0;
156 auto b = boost::process::detail::api::wait_until(_child_handle, exit_code, timeout_time);
157 if (!b)
158 return false;
159 _exit_status->store(exit_code);
160 }
161 return true;
162 }
163
164 bool running(std::error_code & ec) noexcept
165 {
166 if (valid() && !_exited())
167 {
168 int code;
169 auto res = boost::process::detail::api::is_running(_child_handle, code, ec);
170 if (!res && !_exited())
171 _exit_status->store(code);
172
173 return res;
174 }
175 return false;
176 }
177
178 void terminate(std::error_code & ec) noexcept
179 {
180 if (valid() && running(ec))
181 boost::process::detail::api::terminate(_child_handle, ec);
182
183 _terminated = true;
184 }
185
186 void wait(std::error_code & ec) noexcept
187 {
188 if (!_exited() && valid())
189 {
190 int exit_code = 0;
191 boost::process::detail::api::wait(_child_handle, exit_code, ec);
192 _exit_status->store(exit_code);
193 }
194 }
195
196 template< class Rep, class Period >
197 bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept
198 {
199 if (!_exited())
200 {
201 int exit_code = 0;
202 auto b = boost::process::detail::api::wait_for(_child_handle, exit_code, rel_time, ec);
203 if (!b)
204 return false;
205 _exit_status->store(exit_code);
206 }
207 return true;
208 }
209
210 template< class Clock, class Duration >
211 bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, std::error_code & ec) noexcept
212 {
213 if (!_exited())
214 {
215 int exit_code = 0;
216 auto b = boost::process::detail::api::wait_until(_child_handle, exit_code, timeout_time, ec);
217 if (!b)
218 return false;
219 _exit_status->store(exit_code);
220 }
221 return true;
222 }
223
224
225 bool valid() const
226 {
227 return _child_handle.valid();
228 }
229 operator bool() const {return valid();}
230
231 bool in_group() const
232 {
233 return _child_handle.in_group();
234 }
235 bool in_group(std::error_code &ec) const noexcept
236 {
237 return _child_handle.in_group(ec);
238 }
239 };
240
241
242
243 }}
244 #endif
245