Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:13

0001 // Copyright (c) 2022 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef BOOST_PROCESS_V2_EXECUTE_HPP
0006 #define BOOST_PROCESS_V2_EXECUTE_HPP
0007 
0008 #include <boost/process/v2/process.hpp>
0009 
0010 #if defined(BOOST_PROCESS_V2_STANDALONE)
0011 #include <asio/bind_cancellation_slot.hpp>
0012 #else
0013 #include <boost/asio/bind_cancellation_slot.hpp>
0014 #endif
0015 
0016 BOOST_PROCESS_V2_BEGIN_NAMESPACE
0017 
0018 
0019 /**
0020  * @brief Run a process and wait for it to complete.
0021  * 
0022  * @tparam Executor The asio executor of the process handle
0023  * @param proc The process to be run.
0024  * @return int The exit code of the process
0025  * @exception system_error An error that might have occurred during the wait.
0026  */
0027 template<typename Executor>
0028 inline int execute(basic_process<Executor> proc)
0029 {
0030     return proc.wait();
0031 }
0032 
0033 /** \overload int execute(const basic_process<Executor> proc) */
0034 template<typename Executor>
0035 inline int execute(basic_process<Executor> proc, error_code & ec)
0036 {
0037     return proc.wait(ec);
0038 }
0039 
0040 namespace detail
0041 {
0042 
0043 template<typename Executor>
0044 struct execute_op
0045 {
0046     std::unique_ptr<basic_process<Executor>> proc;
0047 
0048     struct cancel
0049     {
0050         using cancellation_type = BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_type;
0051         basic_process<Executor> * proc;
0052         cancel(basic_process<Executor> * proc) : proc(proc) {}
0053 
0054         void operator()(cancellation_type tp)
0055         {
0056             error_code ign;
0057             if ((tp & cancellation_type::total) != cancellation_type::none)
0058                 proc->interrupt(ign);
0059             else if ((tp & cancellation_type::partial) != cancellation_type::none)
0060                 proc->request_exit(ign);
0061             else if ((tp & cancellation_type::terminal) != cancellation_type::none)
0062                 proc->terminate(ign);
0063         }
0064     };
0065 
0066     template<typename Self>
0067     void operator()(Self && self)
0068     {
0069         self.reset_cancellation_state(BOOST_PROCESS_V2_ASIO_NAMESPACE::enable_total_cancellation());
0070         BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_slot s = self.get_cancellation_state().slot();
0071         if (s.is_connected())
0072             s.emplace<cancel>(proc.get());
0073 
0074         auto pro_ = proc.get();
0075         pro_->async_wait(
0076                 BOOST_PROCESS_V2_ASIO_NAMESPACE::bind_cancellation_slot(
0077                     BOOST_PROCESS_V2_ASIO_NAMESPACE::cancellation_slot(),
0078                     std::move(self)));
0079     }
0080 
0081     template<typename Self>
0082     void operator()(Self && self, error_code ec, int res)
0083     { 
0084         self.get_cancellation_state().slot().clear();
0085         self.complete(ec, res);
0086     }
0087 };
0088 
0089 }
0090 
0091 /// Execute a process asynchronously
0092 /** This function asynchronously for a process to complete.
0093  * 
0094  * Cancelling the execution will signal the child process to exit
0095  * with the following interpretations:
0096  * 
0097  *  - cancellation_type::total    -> interrupt
0098  *  - cancellation_type::partial  -> request_exit
0099  *  - cancellation_type::terminal -> terminate
0100  * 
0101  * It is to note that `async_execute` will us the lowest selected cancellation
0102  * type. A subprocess might ignore anything not terminal.
0103  */
0104 template<typename Executor = BOOST_PROCESS_V2_ASIO_NAMESPACE::any_io_executor,
0105         BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void (error_code, int))
0106             WaitHandler BOOST_PROCESS_V2_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>
0107 inline
0108 BOOST_PROCESS_V2_INITFN_AUTO_RESULT_TYPE(WaitHandler, void (error_code, int))
0109 async_execute(basic_process<Executor> proc,
0110                          WaitHandler && handler BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(Executor))
0111 {
0112     std::unique_ptr<basic_process<Executor>> pro_(new basic_process<Executor>(std::move(proc)));
0113     auto exec = proc.get_executor();
0114     return BOOST_PROCESS_V2_ASIO_NAMESPACE::async_compose<WaitHandler, void(error_code, int)>(
0115             detail::execute_op<Executor>{std::move(pro_)}, handler, exec);
0116 }
0117 
0118 BOOST_PROCESS_V2_END_NAMESPACE
0119 
0120 #endif //BOOST_PROCESS_V2_EXECUTE_HPP