diff third_party/boost/process/detail/status_impl.hpp @ 0:add35537fdbb tip

Initial import
author irh <ian.r.hobson@gmail.com>
date Thu, 25 Aug 2011 11:05:55 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/third_party/boost/process/detail/status_impl.hpp	Thu Aug 25 11:05:55 2011 +0100
@@ -0,0 +1,189 @@
+//
+// Boost.Process
+// ~~~~~~~~~~~~~
+//
+// 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
+//
+// 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/detail/status_impl.hpp
+ *
+ * Includes the declaration of the status implementation class.
+ */
+
+#ifndef BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP
+#define BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP
+
+#include <boost/process/config.hpp>
+
+#if defined(BOOST_POSIX_API)
+#   include <sys/types.h>
+#   include <signal.h>
+#   include <sys/wait.h>
+#   include <errno.h>
+#elif defined(BOOST_WINDOWS_API)
+#   include <windows.h>
+#else
+#   error "Unsupported platform."
+#endif
+
+#include <boost/process/pid_type.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/ptr_container/ptr_unordered_map.hpp>
+#include <algorithm>
+
+namespace boost {
+namespace process {
+namespace detail {
+
+#if defined(BOOST_POSIX_API)
+typedef pid_t phandle;
+#elif defined(BOOST_WINDOWS_API)
+typedef HANDLE phandle;
+#endif
+
+struct operation
+{
+    virtual void operator()(int exit_code)
+    {
+#if defined(BOOST_MSVC)
+        exit_code;
+#endif
+    }
+};
+
+template <typename Handler>
+class wrapped_handler : public operation
+{
+public:
+    wrapped_handler(Handler handler)
+    : handler_(handler)
+    {
+    }
+
+    void operator()(int exit_code)
+    {
+        handler_(boost::system::error_code(), exit_code);
+    }
+
+private:
+    Handler handler_;
+};
+
+/**
+ * The status_impl class saves internal data of every status I/O object.
+ */
+class status_impl
+{
+public:
+#if defined(BOOST_WINDOWS_API)
+    template <typename Container>
+    void clear(Container &handles)
+    {
+        for (operations_type::iterator it = ops_.begin(); it != ops_.end();
+            ++it)
+        {
+            for (typename Container::iterator it2 = handles.begin(); it2 !=
+                handles.end(); ++it2)
+            {
+                if (*it2 == it->first)
+                {
+                    handles.erase(it2);
+                    break;
+                }
+            }
+            CloseHandle(it->first);
+        }
+    }
+#endif
+
+    int wait(pid_type pid, boost::system::error_code &ec)
+    {
+#if defined(BOOST_POSIX_API)
+        pid_t p;
+        int status;
+        do
+        {
+            p = waitpid(pid, &status, 0);
+        } while (p == -1 && errno == EINTR);
+        if (p == -1)
+        {
+            ec = boost::system::error_code(errno,
+                    boost::system::get_system_category());
+            return -1;
+        }
+        return status;
+#elif defined(BOOST_WINDOWS_API)
+        HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE,
+            pid);
+        if (h == NULL)
+        {
+            ec = boost::system::error_code(GetLastError(),
+                    boost::system::get_system_category());
+            return -1;
+        }
+
+        if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED)
+        {
+            CloseHandle(h);
+            ec = boost::system::error_code(GetLastError(),
+                    boost::system::get_system_category());
+            return -1;
+        }
+
+        DWORD exit_code;
+        if (!GetExitCodeProcess(h, &exit_code))
+        {
+            CloseHandle(h);
+            ec = boost::system::error_code(GetLastError(),
+                    boost::system::get_system_category());
+            return -1;
+        }
+        if (!CloseHandle(h))
+        {
+            ec = boost::system::error_code(GetLastError(),
+                    boost::system::get_system_category());
+            return -1;
+        }
+        return exit_code;
+#endif
+    }
+
+    template <typename Handler>
+    void async_wait(phandle ph, Handler handler)
+    {
+        ops_.insert(ph, new wrapped_handler<Handler>(handler));
+    }
+
+    bool complete(phandle ph, int exit_code)
+    {
+        boost::iterator_range<operations_type::iterator> r =
+            ops_.equal_range(ph);
+        if (r.empty())
+            return false;
+        for (operations_type::iterator it = r.begin(); it != r.end(); ++it)
+            (*it->second)(exit_code);
+        ops_.erase(r.begin(), r.end());
+#if defined(BOOST_WINDOWS_API)
+        if (!CloseHandle(ph))
+            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
+#endif
+        return true;
+    }
+
+private:
+    typedef boost::ptr_unordered_multimap<phandle, operation> operations_type;
+    operations_type ops_;
+};
+
+}
+}
+}
+
+#endif