]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/process/group.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / process / group.hpp
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 /**
7 * \file boost/process/group.hpp
8 *
9 * Defines a group process class.
10 * For additional information see the platform specific implementations:
11 *
12 * - [windows - job object](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684161.aspx)
13 * - [posix - process group](http://pubs.opengroup.org/onlinepubs/009695399/functions/setpgid.html)
14 *
15 */
16
17 #ifndef BOOST_PROCESS_GROUP_HPP
18 #define BOOST_PROCESS_GROUP_HPP
19
20 #include <boost/process/detail/config.hpp>
21 #include <boost/process/child.hpp>
22 #include <chrono>
23 #include <memory>
24
25 #include <boost/none.hpp>
26 #include <atomic>
27
28
29 #if defined(BOOST_POSIX_API)
30 #include <boost/process/detail/posix/group_handle.hpp>
31 #include <boost/process/detail/posix/group_ref.hpp>
32 #include <boost/process/detail/posix/wait_group.hpp>
33 #elif defined(BOOST_WINDOWS_API)
34 #include <boost/process/detail/windows/group_handle.hpp>
35 #include <boost/process/detail/windows/group_ref.hpp>
36 #include <boost/process/detail/windows/wait_group.hpp>
37 #endif
38
39 namespace boost {
40
41 namespace process {
42
43 namespace detail {
44 struct group_builder;
45 }
46
47 /**
48 * Represents a process group.
49 *
50 * Groups are movable but non-copyable. The destructor
51 * automatically closes handles to the group process.
52 *
53 * The group will have the same interface as std::thread.
54 *
55 * \note If the destructor is called without a previous detach or wait, the group will be terminated.
56 *
57 * \attention If a default-constructed group is used before being used in a process launch, the behaviour is undefined.
58 *
59 * \attention Waiting for groups is currently broken on windows and will most likely result in a dead-lock.
60 */
61 class group
62 {
63 ::boost::process::detail::api::group_handle _group_handle;
64 bool _attached = true;
65 public:
66 typedef ::boost::process::detail::api::group_handle group_handle;
67 ///Native representation of the handle.
68 typedef group_handle::handle_t native_handle_t;
69 explicit group(group_handle &&ch) : _group_handle(std::move(ch)) {}
70 ///Construct the group from a native_handle
71 explicit group(native_handle_t & handle) : _group_handle(handle) {};
72 group(const group&) = delete;
73 ///Move constructor
74 group(group && lhs)
75 : _group_handle(std::move(lhs._group_handle)),
76 _attached (lhs._attached)
77 {
78 lhs._attached = false;
79 }
80 ///Default constructor
81 group() = default;
82 group& operator=(const group&) = delete;
83 ///Move assign
84 group& operator=(group && lhs)
85 {
86 _group_handle= std::move(lhs._group_handle);
87 _attached = lhs._attached;
88
89 return *this;
90 };
91
92 ///Detach the group
93 void detach() {_attached = false; }
94
95 /** Join the child. This just calls wait, but that way the naming is similar to std::thread */
96 void join() {wait();}
97 /** Check if the child is joinable. */
98 bool joinable() {return _attached;}
99
100 /** Destructor
101 *
102 * \note If the destructor is called without a previous detach or wait, the group will be terminated.
103 *
104 */
105 ~group()
106 {
107 std::error_code ec;
108 if ( _attached && valid())
109 terminate(ec);
110 }
111
112 ///Obtain the native handle of the group.
113 native_handle_t native_handle() const { return _group_handle.handle(); }
114
115 ///Wait for the process group to exit.
116 void wait()
117 {
118 boost::process::detail::api::wait(_group_handle);
119 }
120 ///\overload void wait()
121 void wait(std::error_code & ec) noexcept
122 {
123 boost::process::detail::api::wait(_group_handle, ec);
124 }
125 /** Wait for the process group to exit for period of time.
126 * \return True if all child processes exited while waiting.*/
127 template< class Rep, class Period >
128 bool wait_for (const std::chrono::duration<Rep, Period>& rel_time)
129 {
130 return boost::process::detail::api::wait_for(_group_handle, rel_time);
131 }
132
133 /** \overload bool wait_for(const std::chrono::duration<Rep, Period>& timeout_time ) */
134 template< class Rep, class Period >
135 bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept
136 {
137 return boost::process::detail::api::wait_for(_group_handle, rel_time, ec);
138 }
139
140 /** Wait for the process group to exit until a point in time.
141 * \return True if all child processes exited while waiting.*/
142 template< class Clock, class Duration >
143 bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time )
144 {
145 return boost::process::detail::api::wait_until(_group_handle, timeout_time);
146 }
147 /** \overload bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time ) */
148 template< class Clock, class Duration >
149 bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, std::error_code & ec) noexcept
150 {
151 return boost::process::detail::api::wait_until(_group_handle, timeout_time, ec);
152 }
153
154 ///Check if the group has a valid handle.
155 bool valid() const
156 {
157 return _group_handle.valid();
158 }
159 ///Convenience to call valid.
160 explicit operator bool() const {return valid();}
161
162 ///Terminate the process group, i.e. all processes in the group
163 void terminate()
164 {
165 ::boost::process::detail::api::terminate(_group_handle);
166 }
167 ///\overload void terminate()
168 void terminate(std::error_code & ec) noexcept
169 {
170 ::boost::process::detail::api::terminate(_group_handle, ec);
171 }
172
173 ///Assign a child process to the group
174 void add(const child &c)
175 {
176 _group_handle.add(c.native_handle());
177 }
178 ///\overload void assign(const child & c)
179 void add(const child &c, std::error_code & ec) noexcept
180 {
181 _group_handle.add(c.native_handle(), ec);
182 }
183
184 ///Check if the child process is in the group
185 bool has(const child &c)
186 {
187 return _group_handle.has(c.native_handle());
188 }
189 ///\overload bool has(const child &)
190 bool has(const child &c, std::error_code & ec) noexcept
191 {
192 return _group_handle.has(c.native_handle(), ec);
193
194 }
195
196 friend struct detail::group_builder;
197 };
198
199 namespace detail
200 {
201
202 struct group_tag;
203 struct group_builder
204 {
205 group * group_p;
206
207 void operator()(group & grp) {this->group_p = &grp;};
208
209 typedef api::group_ref result_type;
210 api::group_ref get_initializer() {return api::group_ref (group_p->_group_handle);};
211 };
212
213 template<>
214 struct initializer_tag<group>
215 {
216 typedef group_tag type;
217 };
218
219 template<>
220 struct initializer_builder<group_tag>
221 {
222 typedef group_builder type;
223 };
224
225 }
226 }}
227 #endif
228