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