| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 | // 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/group.hpp * * Defines a group process class. * For additional information see the platform specific implementations: * *   - [windows - job object](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684161.aspx) *   - [posix - process group](http://pubs.opengroup.org/onlinepubs/009695399/functions/setpgid.html) * */#ifndef BOOST_PROCESS_GROUP_HPP#define BOOST_PROCESS_GROUP_HPP#include <boost/process/detail/config.hpp>#include <boost/process/child.hpp>#include <chrono>#include <memory>#include <boost/none.hpp>#include <atomic>#if defined(BOOST_POSIX_API)#include <boost/process/detail/posix/group_handle.hpp>#include <boost/process/detail/posix/group_ref.hpp>#include <boost/process/detail/posix/wait_group.hpp>#elif defined(BOOST_WINDOWS_API)#include <boost/process/detail/windows/group_handle.hpp>#include <boost/process/detail/windows/group_ref.hpp>#include <boost/process/detail/windows/wait_group.hpp>#endifnamespace boost {namespace process {namespace detail {    struct group_builder;}/** * Represents a process group. * * Groups are movable but non-copyable. The destructor * automatically closes handles to the group process. * * The group will have the same interface as std::thread. * * \note If the destructor is called without a previous detach or wait, the group will be terminated. * * \attention If a default-constructed group is used before being used in a process launch, the behaviour is undefined. * * \attention Waiting for groups is currently broken on windows and will most likely result in a dead-lock. */class group{    ::boost::process::detail::api::group_handle _group_handle;    bool _attached = true;public:    typedef ::boost::process::detail::api::group_handle group_handle;    ///Native representation of the handle.    typedef group_handle::handle_t native_handle_t;    explicit group(group_handle &&ch) : _group_handle(std::move(ch)) {}    ///Construct the group from a native_handle    explicit group(native_handle_t & handle) : _group_handle(handle) {};    group(const group&) = delete;    ///Move constructor    group(group && lhs)        : _group_handle(std::move(lhs._group_handle)),          _attached (lhs._attached)    {        lhs._attached = false;    }    ///Default constructor    group() = default;    group& operator=(const group&) = delete;    ///Move assign    group& operator=(group && lhs)    {        _group_handle= std::move(lhs._group_handle);        _attached    = lhs._attached;        return *this;    };    ///Detach the group    void detach() {_attached = false; }    /** Join the child. This just calls wait, but that way the naming is similar to std::thread */    void join() {wait();}    /** Check if the child is joinable. */    bool joinable() {return _attached;}    /** Destructor     *     * \note If the destructor is called without a previous detach or wait, the group will be terminated.     *     */    ~group()    {        std::error_code ec;        if ( _attached && valid())            terminate(ec);    }    ///Obtain the native handle of the group.    native_handle_t native_handle() const { return _group_handle.handle(); }    ///Wait for the process group to exit.    void wait()    {        boost::process::detail::api::wait(_group_handle);    }    ///\overload void wait()    void wait(std::error_code & ec) noexcept    {        boost::process::detail::api::wait(_group_handle, ec);    }    /** Wait for the process group to exit for period of time.      *  \return True if all child processes exited while waiting.*/    template< class Rep, class Period >    bool wait_for  (const std::chrono::duration<Rep, Period>& rel_time)    {        return boost::process::detail::api::wait_for(_group_handle, rel_time);    }    /** \overload bool wait_for(const std::chrono::duration<Rep, Period>& timeout_time ) */    template< class Rep, class Period >    bool wait_for  (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept    {        return boost::process::detail::api::wait_for(_group_handle, rel_time, ec);    }    /** Wait for the process group to exit until a point in time.      *  \return True if all child processes exited while waiting.*/    template< class Clock, class Duration >    bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time )    {        return boost::process::detail::api::wait_until(_group_handle, timeout_time);    }    /** \overload bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time ) */    template< class Clock, class Duration >    bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, std::error_code & ec) noexcept    {        return boost::process::detail::api::wait_until(_group_handle, timeout_time, ec);    }    ///Check if the group has a valid handle.    bool valid() const    {        return _group_handle.valid();    }    ///Convenience to call valid.    explicit operator bool() const {return valid();}    ///Terminate the process group, i.e. all processes in the group    void terminate()    {        ::boost::process::detail::api::terminate(_group_handle);    }    ///\overload void terminate()    void terminate(std::error_code & ec) noexcept    {        ::boost::process::detail::api::terminate(_group_handle, ec);    }    ///Assign a child process to the group    void add(const child &c)    {        _group_handle.add(c.native_handle());    }    ///\overload void assign(const child & c)    void add(const child &c, std::error_code & ec) noexcept    {        _group_handle.add(c.native_handle(), ec);    }    ///Check if the child process is in the group    bool has(const child &c)    {        return _group_handle.has(c.native_handle());    }    ///\overload bool has(const child &)    bool has(const child &c, std::error_code & ec) noexcept    {        return _group_handle.has(c.native_handle(), ec);    }    friend struct detail::group_builder;};namespace detail{struct group_tag;struct group_builder{    group * group_p;    void operator()(group & grp) {this->group_p = &grp;};    typedef api::group_ref result_type;    api::group_ref get_initializer() {return api::group_ref (group_p->_group_handle);};};template<>struct initializer_tag<group>{    typedef group_tag type;};template<>struct initializer_builder<group_tag>{    typedef group_builder type;};}}}#endif
 |