2
0
mirror of https://github.com/boostorg/process.git synced 2026-01-30 08:02:37 +00:00

added coroutine

This commit is contained in:
klemens-morgenstern
2016-07-10 02:17:54 +02:00
parent 5105c7c647
commit 2aa084e4aa
9 changed files with 468 additions and 10 deletions

View File

@@ -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)
{

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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