mirror of
https://github.com/boostorg/process.git
synced 2026-01-30 08:02:37 +00:00
added coroutine
This commit is contained in:
@@ -76,6 +76,41 @@ struct has_async_handler<T>
|
||||
typedef typename is_async_handler<T>::type type;
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct is_yield_context
|
||||
{
|
||||
typedef std::false_type type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_yield_context<::boost::asio::basic_yield_context<T>>
|
||||
{
|
||||
typedef std::true_type type;
|
||||
};
|
||||
|
||||
template<typename ...Args>
|
||||
struct has_yield_context;
|
||||
|
||||
template<typename T, typename ...Args>
|
||||
struct has_yield_context<T, Args...>
|
||||
{
|
||||
typedef typename has_yield_context<Args...>::type next;
|
||||
typedef typename is_yield_context<
|
||||
typename std::remove_reference<T>::type>::type is_ios;
|
||||
typedef typename std::conditional<is_ios::value,
|
||||
std::true_type,
|
||||
next>::type type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct has_yield_context<T>
|
||||
{
|
||||
typedef typename is_yield_context<
|
||||
typename std::remove_reference<T>::type>::type type;
|
||||
};
|
||||
|
||||
|
||||
template<typename ...Args>
|
||||
boost::asio::io_service &get_io_service_var(boost::asio::io_service & f, Args&...args)
|
||||
{
|
||||
|
||||
@@ -29,7 +29,8 @@ template <typename SignalSetService>
|
||||
class basic_signal_set;
|
||||
typedef basic_signal_set<signal_set_service> signal_set;
|
||||
|
||||
|
||||
template <typename Handler>
|
||||
class basic_yield_context;
|
||||
|
||||
namespace posix {
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@ class basic_streambuf;
|
||||
typedef basic_streambuf<std::allocator<char>> streambuf;
|
||||
class io_service;
|
||||
|
||||
template <typename Handler>
|
||||
class basic_yield_context;
|
||||
|
||||
namespace windows {
|
||||
|
||||
class stream_handle_service;
|
||||
|
||||
@@ -41,6 +41,7 @@ template<typename IoService, typename ...Args>
|
||||
inline int system_impl(
|
||||
std::true_type, /*has async */
|
||||
std::true_type, /*has io_service*/
|
||||
std::false_type, /* has_yield */
|
||||
Args && ...args)
|
||||
{
|
||||
IoService & ios = ::boost::process::detail::get_io_service_var(args...);
|
||||
@@ -84,6 +85,7 @@ template<typename IoService, typename ...Args>
|
||||
inline int system_impl(
|
||||
std::true_type, /*has async */
|
||||
std::false_type, /*has io_service*/
|
||||
std::false_type, /* has_yield */
|
||||
Args && ...args)
|
||||
{
|
||||
IoService ios;
|
||||
@@ -100,6 +102,7 @@ template<typename IoService, typename ...Args>
|
||||
inline int system_impl(
|
||||
std::false_type, /*has async */
|
||||
std::true_type, /*has io_service*/
|
||||
std::false_type, /* has_yield */
|
||||
Args && ...args)
|
||||
{
|
||||
child c(std::forward<Args>(args)...);
|
||||
@@ -113,6 +116,7 @@ template<typename IoService, typename ...Args>
|
||||
inline int system_impl(
|
||||
std::false_type, /*has async */
|
||||
std::false_type, /*has io_service*/
|
||||
std::false_type, /* has_yield */
|
||||
Args && ...args)
|
||||
{
|
||||
child c(std::forward<Args>(args)...);
|
||||
@@ -122,6 +126,127 @@ inline int system_impl(
|
||||
return c.exit_code();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T& remove_yield(T& t) noexcept
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T&& remove_yield(T&& t) noexcept
|
||||
{
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template<typename Handler>
|
||||
constexpr ::boost::process::detail::handler
|
||||
remove_yield(::boost::asio::basic_yield_context<Handler> & yield_) noexcept
|
||||
{
|
||||
return {}; //essentially nop.
|
||||
}
|
||||
|
||||
template<typename Handler>
|
||||
constexpr ::boost::process::detail::handler
|
||||
remove_yield(::boost::asio::basic_yield_context<Handler> && yield_) noexcept
|
||||
{
|
||||
return {}; //essentially nop.
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
struct get_yield_t;
|
||||
|
||||
template<typename First, typename ... Args>
|
||||
struct get_yield_t<First, Args...>
|
||||
{
|
||||
typedef typename get_yield_t<Args...>::type type;
|
||||
};
|
||||
|
||||
template<typename First, typename ... Args>
|
||||
struct get_yield_t<boost::asio::basic_yield_context<First>, Args...>
|
||||
{
|
||||
typedef boost::asio::basic_yield_context<First> type;
|
||||
};
|
||||
|
||||
template<typename First>
|
||||
struct get_yield_t<boost::asio::basic_yield_context<First>>
|
||||
{
|
||||
typedef boost::asio::basic_yield_context<First> type;
|
||||
};
|
||||
|
||||
template<typename Handler, typename ...Args>
|
||||
auto get_yield(boost::asio::basic_yield_context<Handler> &&yield_) ->
|
||||
boost::asio::basic_yield_context<Handler> &
|
||||
{
|
||||
return yield_;
|
||||
}
|
||||
|
||||
template<typename Handler, typename ...Args>
|
||||
auto get_yield(boost::asio::basic_yield_context<Handler> &yield_) ->
|
||||
boost::asio::basic_yield_context<Handler> &
|
||||
{
|
||||
return yield_;
|
||||
}
|
||||
|
||||
|
||||
template<typename First, typename ...Args>
|
||||
auto get_yield(First &&f, Args&&...args) ->
|
||||
typename get_yield_t<typename std::remove_reference<Args>::type...>::type &
|
||||
{
|
||||
return get_yield(args...);
|
||||
}
|
||||
|
||||
template<typename Handler, typename ...Args>
|
||||
auto get_yield(boost::asio::basic_yield_context<Handler> &&yield_, Args&&...args) ->
|
||||
typename get_yield_t<typename std::remove_reference<Args>::type...>::type &
|
||||
{
|
||||
return yield_;
|
||||
}
|
||||
|
||||
template<typename Handler, typename ...Args>
|
||||
auto get_yield(boost::asio::basic_yield_context<Handler> &yield_, Args&&...args) ->
|
||||
typename get_yield_t<typename std::remove_reference<Args>::type...>::type &
|
||||
{
|
||||
return yield_;
|
||||
}
|
||||
|
||||
|
||||
template<typename IoService, typename T1, typename T2, typename ...Args>
|
||||
inline int system_impl(
|
||||
T1, /*has async */
|
||||
T2, /*has io_service*/
|
||||
std::true_type, /* has_yield */
|
||||
Args && ...args)
|
||||
{
|
||||
|
||||
auto &yield_ = get_yield(args...);
|
||||
auto coro = yield_.coro_.lock();
|
||||
auto & ios = yield_.handler_.dispatcher_.get_io_service();
|
||||
BOOST_ASSERT(coro);
|
||||
|
||||
int ret = -1;
|
||||
auto l = [coro, &ret, &ios](int ret_, const std::error_code& ec_)
|
||||
{
|
||||
ret = ret_;
|
||||
ios.post(
|
||||
[coro]
|
||||
{
|
||||
auto & c = *coro;
|
||||
if (c)
|
||||
c();
|
||||
});
|
||||
};
|
||||
|
||||
child c(remove_yield(std::forward<Args>(args))...,
|
||||
ios,
|
||||
boost::process::on_exit=l);
|
||||
if (!c.valid())
|
||||
return -1;
|
||||
|
||||
yield_.ca_();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Launches a process and waits for its exit. Similar to std::system. */
|
||||
@@ -132,9 +257,11 @@ inline int system(Args && ...args)
|
||||
has_async;
|
||||
typedef typename ::boost::process::detail::has_io_service<Args...>::type
|
||||
has_ios;
|
||||
typedef typename ::boost::process::detail::has_yield_context<Args...>::type
|
||||
has_yield;
|
||||
|
||||
return ::boost::process::detail::system_impl<boost::asio::io_service>(
|
||||
has_async(), has_ios(),
|
||||
has_async(), has_ios(), has_yield(),
|
||||
#if defined(BOOST_POSIX_API)
|
||||
::boost::process::posix::sig.dfl(),
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user