summaryrefslogtreecommitdiff
path: root/boost/process/detail/child_decl.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/process/detail/child_decl.hpp')
-rw-r--r--boost/process/detail/child_decl.hpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/boost/process/detail/child_decl.hpp b/boost/process/detail/child_decl.hpp
new file mode 100644
index 0000000000..3483f7c4b8
--- /dev/null
+++ b/boost/process/detail/child_decl.hpp
@@ -0,0 +1,243 @@
+// 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>
+
+#endif
+namespace 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)
+ {
+ 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;
+ 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(); }
+
+ bool running()
+ {
+ if (valid() && !_exited())
+ {
+ int code;
+ auto res = boost::process::detail::api::is_running(_child_handle, code);
+ if (!res && !_exited())
+ _exit_status->store(code);
+
+ return res;
+ }
+ return false;
+ }
+
+ void terminate()
+ {
+ if (valid() && running())
+ boost::process::detail::api::terminate(_child_handle);
+
+ _terminated = true;
+ }
+
+ void wait()
+ {
+ if (!_exited() && valid())
+ {
+ int exit_code = 0;
+ boost::process::detail::api::wait(_child_handle, exit_code);
+ _exit_status->store(exit_code);
+ }
+ }
+
+ template< class Rep, class Period >
+ bool wait_for (const std::chrono::duration<Rep, Period>& rel_time)
+ {
+ if (!_exited())
+ {
+ int exit_code = 0;
+ auto b = boost::process::detail::api::wait_for(_child_handle, exit_code, rel_time);
+ if (!b)
+ return false;
+ _exit_status->store(exit_code);
+ }
+ return true;
+ }
+
+ template< class Clock, class Duration >
+ bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time )
+ {
+ if (!_exited())
+ {
+ int exit_code = 0;
+ auto b = boost::process::detail::api::wait_until(_child_handle, exit_code, timeout_time);
+ if (!b)
+ return false;
+ _exit_status->store(exit_code);
+ }
+ return true;
+ }
+
+ bool running(std::error_code & ec) noexcept
+ {
+ if (valid() && !_exited())
+ {
+ int code;
+ auto res = boost::process::detail::api::is_running(_child_handle, code, ec);
+ if (!res && !_exited())
+ _exit_status->store(code);
+
+ return res;
+ }
+ return false;
+ }
+
+ void terminate(std::error_code & ec) noexcept
+ {
+ if (valid() && running(ec))
+ boost::process::detail::api::terminate(_child_handle, 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);
+ _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
+ {
+ if (!_exited())
+ {
+ int exit_code = 0;
+ auto b = boost::process::detail::api::wait_for(_child_handle, exit_code, rel_time, ec);
+ if (!b)
+ return false;
+ _exit_status->store(exit_code);
+ }
+ return true;
+ }
+
+ 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)
+ 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
+