group.hpp 6.8 KB

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