| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 | // 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/child.hpp * * Defines a child process class. */#ifndef BOOST_PROCESS_CHILD_DECL_HPP#define BOOST_PROCESS_CHILD_DECL_HPP#include <boost/process/detail/config.hpp>#include <chrono>#include <memory>#include <boost/none.hpp>#include <atomic>#if defined(BOOST_POSIX_API)#include <boost/process/detail/posix/child_handle.hpp>#include <boost/process/detail/posix/terminate.hpp>#include <boost/process/detail/posix/wait_for_exit.hpp>#include <boost/process/detail/posix/is_running.hpp>#elif defined(BOOST_WINDOWS_API)#include <boost/process/detail/windows/child_handle.hpp>#include <boost/process/detail/windows/terminate.hpp>#include <boost/process/detail/windows/wait_for_exit.hpp>#include <boost/process/detail/windows/is_running.hpp>#endifnamespace boost {namespace process {using ::boost::process::detail::api::pid_t;class child{    ::boost::process::detail::api::child_handle _child_handle;    std::shared_ptr<std::atomic<int>> _exit_status = std::make_shared<std::atomic<int>>(::boost::process::detail::api::still_active);    bool _attached = true;    bool _terminated = false;    bool _exited()    {        return _terminated || !::boost::process::detail::api::is_running(_exit_status->load());    };public:    typedef ::boost::process::detail::api::child_handle child_handle;    typedef child_handle::process_handle_t native_handle_t;    explicit child(child_handle &&ch, std::shared_ptr<std::atomic<int>> &ptr) : _child_handle(std::move(ch)), _exit_status(ptr) {}    explicit child(child_handle &&ch, const std::shared_ptr<std::atomic<int>> &ptr) : _child_handle(std::move(ch)), _exit_status(ptr) {}    explicit child(child_handle &&ch) : _child_handle(std::move(ch)) {}    explicit child(pid_t & pid) : _child_handle(pid), _attached(false) {};    child(const child&) = delete;    child(child && lhs) noexcept        : _child_handle(std::move(lhs._child_handle)),          _exit_status(std::move(lhs._exit_status)),          _attached (lhs._attached),          _terminated (lhs._terminated)    {        lhs._attached = false;    }    template<typename ...Args>    explicit child(Args&&...args);    child() {}    child& operator=(const child&) = delete;    child& operator=(child && lhs)    {        _child_handle= std::move(lhs._child_handle);        _exit_status = std::move(lhs._exit_status);        _attached    = lhs._attached;        _terminated  = lhs._terminated;        lhs._attached = false;        return *this;    };    void detach() {_attached = false; }    void join() {wait();}    bool joinable() { return _attached;}    ~child()    {        std::error_code ec;        if (_attached && !_exited() && running(ec))            terminate(ec);    }    native_handle_t native_handle() const { return _child_handle.process_handle(); }    int exit_code() const {return ::boost::process::detail::api::eval_exit_status(_exit_status->load());}    pid_t id()      const {return _child_handle.id(); }    int native_exit_code() const {return _exit_status->load();}    bool running()    {        std::error_code ec;        bool b = running(ec);        boost::process::detail::throw_error(ec, "running error");        return b;    }    void terminate()    {        std::error_code ec;        terminate(ec);        boost::process::detail::throw_error(ec, "terminate error");    }    void wait()    {        std::error_code ec;        wait(ec);        boost::process::detail::throw_error(ec, "wait error");    }    template< class Rep, class Period >    bool wait_for (const std::chrono::duration<Rep, Period>& rel_time)    {        std::error_code ec;        bool b = wait_for(rel_time, ec);        boost::process::detail::throw_error(ec, "wait_for error");        return b;    }    template< class Clock, class Duration >    bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time )    {        std::error_code ec;        bool b = wait_until(timeout_time, ec);        boost::process::detail::throw_error(ec, "wait_until error");        return b;    }    bool running(std::error_code & ec) noexcept    {        ec.clear();        if (valid() && !_exited() && !ec)        {            int exit_code = 0;            auto res = boost::process::detail::api::is_running(_child_handle, exit_code, ec);            if (!ec && !res && !_exited())                _exit_status->store(exit_code);            return res;        }        return false;    }    void terminate(std::error_code & ec) noexcept    {        if (valid() && running(ec) && !ec)            boost::process::detail::api::terminate(_child_handle, ec);        if (!ec)            _terminated = true;    }    void wait(std::error_code & ec) noexcept    {        if (!_exited() && valid())        {            int exit_code = 0;            boost::process::detail::api::wait(_child_handle, exit_code, ec);            if (!ec)                _exit_status->store(exit_code);        }    }    template< class Rep, class Period >    bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept    {        return wait_until(std::chrono::steady_clock::now() + rel_time, ec);    }    template< class Clock, class Duration >    bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, std::error_code & ec) noexcept    {        if (!_exited())        {            int exit_code = 0;            auto b = boost::process::detail::api::wait_until(_child_handle, exit_code, timeout_time, ec);            if (!b || ec)                return false;            _exit_status->store(exit_code);        }        return true;    }    bool valid() const    {        return _child_handle.valid();    }    operator bool() const {return valid();}    bool in_group() const    {        return _child_handle.in_group();    }    bool in_group(std::error_code &ec) const noexcept    {        return _child_handle.in_group(ec);    }};}}#endif
 |