bind_launcher.hpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. //
  2. // boost/process/v2/bind_launcher.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_PROCESS_V2_BIND_LAUNCHER_HPP
  11. #define BOOST_PROCESS_V2_BIND_LAUNCHER_HPP
  12. #include <boost/process/v2/detail/config.hpp>
  13. #include <boost/process/v2/default_launcher.hpp>
  14. BOOST_PROCESS_V2_BEGIN_NAMESPACE
  15. namespace detail
  16. {
  17. template<std::size_t ... Idx>
  18. struct index_sequence { };
  19. template<std::size_t Size, typename T>
  20. struct make_index_sequence_impl;
  21. template<std::size_t Size, std::size_t ... Idx>
  22. struct make_index_sequence_impl<Size, index_sequence<Idx...>>
  23. {
  24. constexpr make_index_sequence_impl() {}
  25. using type = typename make_index_sequence_impl<Size - 1u, index_sequence<Size - 1u, Idx...>>::type;
  26. };
  27. template<std::size_t ... Idx>
  28. struct make_index_sequence_impl<0u, index_sequence<Idx...>>
  29. {
  30. constexpr make_index_sequence_impl() {}
  31. using type = index_sequence<Idx...>;
  32. };
  33. template<std::size_t Cnt>
  34. struct make_index_sequence
  35. {
  36. using type = typename make_index_sequence_impl<Cnt, index_sequence<>>::type;
  37. };
  38. template<std::size_t Cnt>
  39. using make_index_sequence_t = typename make_index_sequence<Cnt>::type;
  40. }
  41. /** @brief Utility class to bind initializers to a launcher
  42. * @tparam Launcher The inner launcher to be used
  43. * @tparam ...Init The initializers to be prepended.
  44. *
  45. * This can be used when multiple processes shared some settings,
  46. * e.g.
  47. *
  48. */
  49. template<typename Launcher, typename ... Init>
  50. struct bound_launcher
  51. {
  52. template<typename Launcher_, typename ... Init_>
  53. bound_launcher(Launcher_ && l, Init_ && ... init) :
  54. launcher_(std::forward<Launcher_>(l)), init_(std::forward<Init_>(init)...)
  55. {
  56. }
  57. template<typename ExecutionContext, typename Args, typename ... Inits>
  58. auto operator()(ExecutionContext & context,
  59. const typename std::enable_if<std::is_convertible<
  60. ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
  61. filesystem::path >::type & executable,
  62. Args && args,
  63. Inits && ... inits) -> basic_process<typename ExecutionContext::executor_type>
  64. {
  65. return invoke(detail::make_index_sequence_t<sizeof...(Init)>{},
  66. context,
  67. executable,
  68. std::forward<Args>(args),
  69. std::forward<Inits>(inits)...);
  70. }
  71. template<typename ExecutionContext, typename Args, typename ... Inits>
  72. auto operator()(ExecutionContext & context,
  73. error_code & ec,
  74. const typename std::enable_if<std::is_convertible<
  75. ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
  76. filesystem::path >::type & executable,
  77. Args && args,
  78. Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
  79. {
  80. return invoke(detail::make_index_sequence_t<sizeof...(Init)>{},
  81. context, ec,
  82. executable,
  83. std::forward<Args>(args),
  84. std::forward<Inits>(inits)...);
  85. }
  86. template<typename Executor, typename Args, typename ... Inits>
  87. auto operator()(Executor exec,
  88. const typename std::enable_if<
  89. BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
  90. BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
  91. filesystem::path >::type & executable,
  92. Args && args,
  93. Inits && ... inits ) -> basic_process<Executor>
  94. {
  95. return invoke(detail::make_index_sequence_t<sizeof...(Init)>{},
  96. std::move(exec),
  97. executable,
  98. std::forward<Args>(args),
  99. std::forward<Inits>(inits)...);
  100. }
  101. template<typename Executor, typename Args, typename ... Inits>
  102. auto operator()(Executor exec,
  103. error_code & ec,
  104. const typename std::enable_if<
  105. BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
  106. BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
  107. filesystem::path >::type & executable,
  108. Args && args,
  109. Inits && ... inits ) -> basic_process<Executor>
  110. {
  111. return invoke(detail::make_index_sequence_t<sizeof...(Init)>{},
  112. std::move(exec), ec,
  113. executable,
  114. std::forward<Args>(args),
  115. std::forward<Inits>(inits)...);
  116. }
  117. private:
  118. template<std::size_t ... Idx, typename ExecutionContext, typename Args, typename ... Inits>
  119. auto invoke(detail::index_sequence<Idx...>,
  120. ExecutionContext & context,
  121. const typename std::enable_if<std::is_convertible<
  122. ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
  123. filesystem::path >::type & executable,
  124. Args && args,
  125. Inits && ... inits) -> basic_process<typename ExecutionContext::executor_type>
  126. {
  127. return launcher_(context,
  128. executable,
  129. std::forward<Args>(args),
  130. std::get<Idx>(init_)...,
  131. std::forward<Inits>(inits)...);
  132. }
  133. template<std::size_t ... Idx, typename ExecutionContext, typename Args, typename ... Inits>
  134. auto invoke(detail::index_sequence<Idx...>,
  135. ExecutionContext & context,
  136. error_code & ec,
  137. const typename std::enable_if<std::is_convertible<
  138. ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
  139. filesystem::path >::type & executable,
  140. Args && args,
  141. Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
  142. {
  143. return launcher_(context, ec,
  144. executable,
  145. std::forward<Args>(args),
  146. std::get<Idx>(init_)...,
  147. std::forward<Inits>(inits)...);
  148. }
  149. template<std::size_t ... Idx, typename Executor, typename Args, typename ... Inits>
  150. auto invoke(detail::index_sequence<Idx...>,
  151. Executor exec,
  152. const typename std::enable_if<
  153. BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
  154. BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
  155. filesystem::path >::type & executable,
  156. Args && args,
  157. Inits && ... inits ) -> basic_process<Executor>
  158. {
  159. return launcher_(std::move(exec),
  160. executable,
  161. std::forward<Args>(args),
  162. std::get<Idx>(init_)...,
  163. std::forward<Inits>(inits)...);
  164. }
  165. template<std::size_t ... Idx, typename Executor, typename Args, typename ... Inits>
  166. auto invoke(detail::index_sequence<Idx...>,
  167. Executor exec,
  168. error_code & ec,
  169. const typename std::enable_if<
  170. BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
  171. BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
  172. filesystem::path >::type & executable,
  173. Args && args,
  174. Inits && ... inits ) -> basic_process<Executor>
  175. {
  176. return launcher_(std::move(exec), ec,
  177. executable,
  178. std::forward<Args>(args),
  179. std::get<Idx>(init_)...,
  180. std::forward<Inits>(inits)...);
  181. }
  182. Launcher launcher_;
  183. std::tuple<Init...> init_;
  184. };
  185. template<typename Launcher, typename ... Init>
  186. auto bind_launcher(Launcher && launcher, Init && ... init)
  187. -> bound_launcher<typename std::decay<Launcher>::type,
  188. typename std::decay<Init>::type...>
  189. {
  190. return bound_launcher<typename std::decay<Launcher>::type,
  191. typename std::decay<Init>::type...>(
  192. std::forward<Launcher>(launcher),
  193. std::forward<Init>(init)...);
  194. }
  195. /// @brief @overload bind_launcher(Launcher && launcher, Init && init)
  196. /// @tparam ...Init The initializer types to bind to the default_launcher.
  197. /// @param ...init The initializers types to bind to the default_launcher.
  198. /// @return The new default_launcher.
  199. template<typename ... Init>
  200. auto bind_default_launcher(Init && ... init)
  201. -> bound_launcher<default_process_launcher,
  202. typename std::decay<Init>::type...>
  203. {
  204. return bound_launcher<default_process_launcher,
  205. typename std::decay<Init>::type...>(
  206. default_process_launcher(),
  207. std::forward<Init>(init)...);
  208. }
  209. BOOST_PROCESS_V2_END_NAMESPACE
  210. #endif // BOOST_PROCESS_V2_BIND_LAUNCHER_HPP