// Copyright (c) 2022 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) #ifndef BOOST_PROCESS_V2_EXECUTE_HPP #define BOOST_PROCESS_V2_EXECUTE_HPP #include #if defined(BOOST_PROCESS_V2_STANDALONE) #include #else #include #endif BOOST_PROCESS_V2_BEGIN_NAMESPACE /** * @brief Run a process and wait for it to complete. * * @tparam Executor The asio executor of the process handle * @param proc The process to be run. * @return int The exit code of the process * @exception system_error An error that might have occured during the wait. */ template inline int execute(basic_process proc) { return proc.wait(); } /** \overload int execute(const basic_process proc) */ template inline int execute(basic_process proc, error_code & ec) { return proc.wait(ec); } namespace detail { template struct execute_op { std::unique_ptr> proc; struct cancel { using cancellation_type = BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_type; basic_process * proc; cancel(basic_process * proc) : proc(proc) {} void operator()(cancellation_type tp) { error_code ign; if ((tp & cancellation_type::total) != cancellation_type::none) proc->interrupt(ign); else if ((tp & cancellation_type::partial) != cancellation_type::none) proc->request_exit(ign); else if ((tp & cancellation_type::terminal) != cancellation_type::none) proc->terminate(ign); } }; template void operator()(Self && self) { self.reset_cancellation_state(); BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_slot s = self.get_cancellation_state().slot(); if (s.is_connected()) s.emplace(proc.get()); auto pro_ = proc.get(); pro_->async_wait( BOOST_PROCESS_V2_ASIO_NAMESPACE::bind_cancellation_slot( BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_slot(), std::move(self))); } template void operator()(Self && self, error_code ec, int res) { self.get_cancellation_state().slot().clear(); self.complete(ec, res); } }; } /// Execute a process asynchronously /** This function asynchronously for a process to complete. * * Cancelling the execution will signal the child process to exit * with the following intepretations: * * - cancellation_type::total -> interrupt * - cancellation_type::partial -> request_exit * - cancellation_type::terminal -> terminate * * It is to note that `async_execute` will us the lowest seelected cancellation * type. A subprocess might ignore anything not terminal. */ template inline BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (error_code, int)) async_execute(basic_process proc, WaitHandler && handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor)) { std::unique_ptr> pro_(new basic_process(std::move(proc))); auto exec = proc.get_executor(); return BOOST_PROCESS_V2_ASIO_NAMESPACE::async_compose( detail::execute_op{std::move(pro_)}, handler, exec); } BOOST_PROCESS_V2_END_NAMESPACE #endif //BOOST_PROCESS_V2_EXECUTE_HPP