整理
This commit is contained in:
158
include/boost/process/v1/system.hpp
Normal file
158
include/boost/process/v1/system.hpp
Normal file
@@ -0,0 +1,158 @@
|
||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
||||
// Copyright (c) 2009 Boris Schaeling
|
||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
||||
// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
|
||||
// Copyright (c) 2016 Klemens D. Morgenstern
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
/**
|
||||
* \file boost/process/system.hpp
|
||||
*
|
||||
* Defines a system function.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_PROCESS_SYSTEM_HPP
|
||||
#define BOOST_PROCESS_SYSTEM_HPP
|
||||
|
||||
#include <boost/process/v1/detail/config.hpp>
|
||||
#include <boost/process/v1/detail/on_exit.hpp>
|
||||
#include <boost/process/v1/child.hpp>
|
||||
#include <boost/process/v1/detail/async_handler.hpp>
|
||||
#include <boost/process/v1/detail/execute_impl.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <type_traits>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
#if defined(BOOST_POSIX_API)
|
||||
#include <boost/process/v1/posix.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace process { BOOST_PROCESS_V1_INLINE namespace v1 {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct system_impl_success_check : handler
|
||||
{
|
||||
bool succeeded = false;
|
||||
|
||||
template<typename Exec>
|
||||
void on_success(Exec &) { succeeded = true; }
|
||||
};
|
||||
|
||||
template<typename IoService, typename ...Args>
|
||||
inline int system_impl(
|
||||
std::true_type, /*needs ios*/
|
||||
std::true_type, /*has io_context*/
|
||||
Args && ...args)
|
||||
{
|
||||
IoService & ios = ::boost::process::v1::detail::get_io_context_var(args...);
|
||||
|
||||
system_impl_success_check check;
|
||||
|
||||
std::atomic_bool exited{false};
|
||||
|
||||
child c(std::forward<Args>(args)...,
|
||||
check,
|
||||
::boost::process::v1::on_exit(
|
||||
[&](int, const std::error_code&)
|
||||
{
|
||||
boost::asio::post(ios.get_executor(), [&]{exited.store(true);});
|
||||
}));
|
||||
if (!c.valid() || !check.succeeded)
|
||||
return -1;
|
||||
|
||||
while (!exited.load())
|
||||
ios.poll();
|
||||
|
||||
return c.exit_code();
|
||||
}
|
||||
|
||||
template<typename IoService, typename ...Args>
|
||||
inline int system_impl(
|
||||
std::true_type, /*needs ios */
|
||||
std::false_type, /*has io_context*/
|
||||
Args && ...args)
|
||||
{
|
||||
IoService ios;
|
||||
child c(ios, std::forward<Args>(args)...);
|
||||
if (!c.valid())
|
||||
return -1;
|
||||
|
||||
ios.run();
|
||||
if (c.running())
|
||||
c.wait();
|
||||
return c.exit_code();
|
||||
}
|
||||
|
||||
|
||||
template<typename IoService, typename ...Args>
|
||||
inline int system_impl(
|
||||
std::false_type, /*needs ios*/
|
||||
std::true_type, /*has io_context*/
|
||||
Args && ...args)
|
||||
{
|
||||
child c(std::forward<Args>(args)...);
|
||||
if (!c.valid())
|
||||
return -1;
|
||||
c.wait();
|
||||
return c.exit_code();
|
||||
}
|
||||
|
||||
template<typename IoService, typename ...Args>
|
||||
inline int system_impl(
|
||||
std::false_type, /*has async */
|
||||
std::false_type, /*has io_context*/
|
||||
Args && ...args)
|
||||
{
|
||||
child c(std::forward<Args>(args)...
|
||||
#if defined(BOOST_POSIX_API)
|
||||
,::boost::process::v1::posix::sig.dfl()
|
||||
#endif
|
||||
);
|
||||
if (!c.valid())
|
||||
return -1;
|
||||
c.wait();
|
||||
return c.exit_code();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Launches a process and waits for its exit.
|
||||
It works as std::system, though it allows
|
||||
all the properties boost.process provides. It will execute the process and wait for it's exit; then return the exit_code.
|
||||
|
||||
\code{.cpp}
|
||||
int ret = system("ls");
|
||||
\endcode
|
||||
|
||||
\attention Using this function with synchronous pipes leads to many potential deadlocks.
|
||||
|
||||
When using this function with an asynchronous properties and NOT passing an io_context object,
|
||||
the system function will create one and run it. When the io_context is passed to the function,
|
||||
the system function will check if it is active, and call the io_context::run function if not.
|
||||
|
||||
*/
|
||||
template<typename ...Args>
|
||||
inline int system(Args && ...args)
|
||||
{
|
||||
typedef typename ::boost::process::v1::detail::needs_io_context<Args...>::type
|
||||
need_ios;
|
||||
typedef typename ::boost::process::v1::detail::has_io_context<Args...>::type
|
||||
has_ios;
|
||||
return ::boost::process::v1::detail::system_impl<boost::asio::io_context>(
|
||||
need_ios(), has_ios(),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user