annotate 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
rev   line source
ian@0 1 //
ian@0 2 // Boost.Process
ian@0 3 // ~~~~~~~~~~~~~
ian@0 4 //
ian@0 5 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
ian@0 6 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
ian@0 7 // Copyright (c) 2009 Boris Schaeling
ian@0 8 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
ian@0 9 //
ian@0 10 // Distributed under the Boost Software License, Version 1.0. (See accompanying
ian@0 11 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
ian@0 12 //
ian@0 13
ian@0 14 /**
ian@0 15 * \file boost/process/detail/status_impl.hpp
ian@0 16 *
ian@0 17 * Includes the declaration of the status implementation class.
ian@0 18 */
ian@0 19
ian@0 20 #ifndef BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP
ian@0 21 #define BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP
ian@0 22
ian@0 23 #include <boost/process/config.hpp>
ian@0 24
ian@0 25 #if defined(BOOST_POSIX_API)
ian@0 26 # include <sys/types.h>
ian@0 27 # include <signal.h>
ian@0 28 # include <sys/wait.h>
ian@0 29 # include <errno.h>
ian@0 30 #elif defined(BOOST_WINDOWS_API)
ian@0 31 # include <windows.h>
ian@0 32 #else
ian@0 33 # error "Unsupported platform."
ian@0 34 #endif
ian@0 35
ian@0 36 #include <boost/process/pid_type.hpp>
ian@0 37 #include <boost/system/error_code.hpp>
ian@0 38 #include <boost/ptr_container/ptr_unordered_map.hpp>
ian@0 39 #include <algorithm>
ian@0 40
ian@0 41 namespace boost {
ian@0 42 namespace process {
ian@0 43 namespace detail {
ian@0 44
ian@0 45 #if defined(BOOST_POSIX_API)
ian@0 46 typedef pid_t phandle;
ian@0 47 #elif defined(BOOST_WINDOWS_API)
ian@0 48 typedef HANDLE phandle;
ian@0 49 #endif
ian@0 50
ian@0 51 struct operation
ian@0 52 {
ian@0 53 virtual void operator()(int exit_code)
ian@0 54 {
ian@0 55 #if defined(BOOST_MSVC)
ian@0 56 exit_code;
ian@0 57 #endif
ian@0 58 }
ian@0 59 };
ian@0 60
ian@0 61 template <typename Handler>
ian@0 62 class wrapped_handler : public operation
ian@0 63 {
ian@0 64 public:
ian@0 65 wrapped_handler(Handler handler)
ian@0 66 : handler_(handler)
ian@0 67 {
ian@0 68 }
ian@0 69
ian@0 70 void operator()(int exit_code)
ian@0 71 {
ian@0 72 handler_(boost::system::error_code(), exit_code);
ian@0 73 }
ian@0 74
ian@0 75 private:
ian@0 76 Handler handler_;
ian@0 77 };
ian@0 78
ian@0 79 /**
ian@0 80 * The status_impl class saves internal data of every status I/O object.
ian@0 81 */
ian@0 82 class status_impl
ian@0 83 {
ian@0 84 public:
ian@0 85 #if defined(BOOST_WINDOWS_API)
ian@0 86 template <typename Container>
ian@0 87 void clear(Container &handles)
ian@0 88 {
ian@0 89 for (operations_type::iterator it = ops_.begin(); it != ops_.end();
ian@0 90 ++it)
ian@0 91 {
ian@0 92 for (typename Container::iterator it2 = handles.begin(); it2 !=
ian@0 93 handles.end(); ++it2)
ian@0 94 {
ian@0 95 if (*it2 == it->first)
ian@0 96 {
ian@0 97 handles.erase(it2);
ian@0 98 break;
ian@0 99 }
ian@0 100 }
ian@0 101 CloseHandle(it->first);
ian@0 102 }
ian@0 103 }
ian@0 104 #endif
ian@0 105
ian@0 106 int wait(pid_type pid, boost::system::error_code &ec)
ian@0 107 {
ian@0 108 #if defined(BOOST_POSIX_API)
ian@0 109 pid_t p;
ian@0 110 int status;
ian@0 111 do
ian@0 112 {
ian@0 113 p = waitpid(pid, &status, 0);
ian@0 114 } while (p == -1 && errno == EINTR);
ian@0 115 if (p == -1)
ian@0 116 {
ian@0 117 ec = boost::system::error_code(errno,
ian@0 118 boost::system::get_system_category());
ian@0 119 return -1;
ian@0 120 }
ian@0 121 return status;
ian@0 122 #elif defined(BOOST_WINDOWS_API)
ian@0 123 HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE,
ian@0 124 pid);
ian@0 125 if (h == NULL)
ian@0 126 {
ian@0 127 ec = boost::system::error_code(GetLastError(),
ian@0 128 boost::system::get_system_category());
ian@0 129 return -1;
ian@0 130 }
ian@0 131
ian@0 132 if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED)
ian@0 133 {
ian@0 134 CloseHandle(h);
ian@0 135 ec = boost::system::error_code(GetLastError(),
ian@0 136 boost::system::get_system_category());
ian@0 137 return -1;
ian@0 138 }
ian@0 139
ian@0 140 DWORD exit_code;
ian@0 141 if (!GetExitCodeProcess(h, &exit_code))
ian@0 142 {
ian@0 143 CloseHandle(h);
ian@0 144 ec = boost::system::error_code(GetLastError(),
ian@0 145 boost::system::get_system_category());
ian@0 146 return -1;
ian@0 147 }
ian@0 148 if (!CloseHandle(h))
ian@0 149 {
ian@0 150 ec = boost::system::error_code(GetLastError(),
ian@0 151 boost::system::get_system_category());
ian@0 152 return -1;
ian@0 153 }
ian@0 154 return exit_code;
ian@0 155 #endif
ian@0 156 }
ian@0 157
ian@0 158 template <typename Handler>
ian@0 159 void async_wait(phandle ph, Handler handler)
ian@0 160 {
ian@0 161 ops_.insert(ph, new wrapped_handler<Handler>(handler));
ian@0 162 }
ian@0 163
ian@0 164 bool complete(phandle ph, int exit_code)
ian@0 165 {
ian@0 166 boost::iterator_range<operations_type::iterator> r =
ian@0 167 ops_.equal_range(ph);
ian@0 168 if (r.empty())
ian@0 169 return false;
ian@0 170 for (operations_type::iterator it = r.begin(); it != r.end(); ++it)
ian@0 171 (*it->second)(exit_code);
ian@0 172 ops_.erase(r.begin(), r.end());
ian@0 173 #if defined(BOOST_WINDOWS_API)
ian@0 174 if (!CloseHandle(ph))
ian@0 175 BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
ian@0 176 #endif
ian@0 177 return true;
ian@0 178 }
ian@0 179
ian@0 180 private:
ian@0 181 typedef boost::ptr_unordered_multimap<phandle, operation> operations_type;
ian@0 182 operations_type ops_;
ian@0 183 };
ian@0 184
ian@0 185 }
ian@0 186 }
ian@0 187 }
ian@0 188
ian@0 189 #endif