1 // Copyright (c) 2016 Klemens D. Morgenstern
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)
7 * \file boost/process/group.hpp
9 * Defines a group process class.
10 * For additional information see the platform specific implementations:
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)
17 #ifndef BOOST_PROCESS_GROUP_HPP
18 #define BOOST_PROCESS_GROUP_HPP
20 #include <boost/process/detail/config.hpp>
21 #include <boost/process/child.hpp>
25 #include <boost/none.hpp>
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>
48 * Represents a process group.
50 * Groups are movable but non-copyable. The destructor
51 * automatically closes handles to the group process.
53 * The group will have the same interface as std::thread.
55 * \note If the destructor is called without a previous detach or wait, the group will be terminated.
57 * \attention If a default-constructed group is used before being used in a process launch, the behaviour is undefined.
59 * \attention Waiting for groups is currently broken on windows and will most likely result in a dead-lock.
63 ::boost::process::detail::api::group_handle _group_handle;
64 bool _attached = true;
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;
75 : _group_handle(std::move(lhs._group_handle)),
76 _attached (lhs._attached)
78 lhs._attached = false;
80 ///Default constructor
82 group& operator=(const group&) = delete;
84 group& operator=(group && lhs)
86 _group_handle= std::move(lhs._group_handle);
87 _attached = lhs._attached;
93 void detach() {_attached = false; }
95 /** Join the child. This just calls wait, but that way the naming is similar to std::thread */
97 /** Check if the child is joinable. */
98 bool joinable() {return _attached;}
102 * \note If the destructor is called without a previous detach or wait, the group will be terminated.
108 if ( _attached && valid())
112 ///Obtain the native handle of the group.
113 native_handle_t native_handle() const { return _group_handle.handle(); }
115 ///Wait for the process group to exit.
118 boost::process::detail::api::wait(_group_handle);
120 ///\overload void wait()
121 void wait(std::error_code & ec) noexcept
123 boost::process::detail::api::wait(_group_handle, ec);
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)
130 return boost::process::detail::api::wait_for(_group_handle, rel_time);
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
137 return boost::process::detail::api::wait_for(_group_handle, rel_time, ec);
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 )
145 return boost::process::detail::api::wait_until(_group_handle, timeout_time);
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
151 return boost::process::detail::api::wait_until(_group_handle, timeout_time, ec);
154 ///Check if the group has a valid handle.
157 return _group_handle.valid();
159 ///Convenience to call valid.
160 explicit operator bool() const {return valid();}
162 ///Terminate the process group, i.e. all processes in the group
165 ::boost::process::detail::api::terminate(_group_handle);
167 ///\overload void terminate()
168 void terminate(std::error_code & ec) noexcept
170 ::boost::process::detail::api::terminate(_group_handle, ec);
173 ///Assign a child process to the group
174 void add(const child &c)
176 _group_handle.add(c.native_handle());
178 ///\overload void assign(const child & c)
179 void add(const child &c, std::error_code & ec) noexcept
181 _group_handle.add(c.native_handle(), ec);
184 ///Check if the child process is in the group
185 bool has(const child &c)
187 return _group_handle.has(c.native_handle());
189 ///\overload bool has(const child &)
190 bool has(const child &c, std::error_code & ec) noexcept
192 return _group_handle.has(c.native_handle(), ec);
196 friend struct detail::group_builder;
207 void operator()(group & grp) {this->group_p = &grp;};
209 typedef api::group_ref result_type;
210 api::group_ref get_initializer() {return api::group_ref (group_p->_group_handle);};
214 struct initializer_tag<group>
216 typedef group_tag type;
220 struct initializer_builder<group_tag>
222 typedef group_builder type;