]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // detail/winapi_thread.hpp | |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~ | |
4 | // | |
5 | // Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) | |
6 | // | |
7 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | // | |
10 | ||
11 | #ifndef BOOST_ASIO_DETAIL_WINAPI_THREAD_HPP | |
12 | #define BOOST_ASIO_DETAIL_WINAPI_THREAD_HPP | |
13 | ||
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) | |
15 | # pragma once | |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | |
17 | ||
18 | #include <boost/asio/detail/config.hpp> | |
19 | ||
20 | #if defined(BOOST_ASIO_WINDOWS) | |
21 | #if defined(BOOST_ASIO_WINDOWS_APP) || defined(UNDER_CE) | |
22 | ||
23 | #include <memory> | |
24 | #include <boost/asio/detail/noncopyable.hpp> | |
25 | #include <boost/asio/detail/socket_types.hpp> | |
26 | #include <boost/asio/detail/throw_error.hpp> | |
27 | #include <boost/asio/error.hpp> | |
28 | ||
29 | #include <boost/asio/detail/push_options.hpp> | |
30 | ||
31 | namespace boost { | |
32 | namespace asio { | |
33 | namespace detail { | |
34 | ||
35 | DWORD WINAPI winapi_thread_function(LPVOID arg); | |
36 | ||
37 | class winapi_thread | |
38 | : private noncopyable | |
39 | { | |
40 | public: | |
41 | // Constructor. | |
42 | template <typename Function> | |
43 | winapi_thread(Function f, unsigned int = 0) | |
44 | { | |
45 | std::auto_ptr<func_base> arg(new func<Function>(f)); | |
46 | DWORD thread_id = 0; | |
47 | thread_ = ::CreateThread(0, 0, winapi_thread_function, | |
48 | arg.get(), 0, &thread_id); | |
49 | if (!thread_) | |
50 | { | |
51 | DWORD last_error = ::GetLastError(); | |
52 | boost::system::error_code ec(last_error, | |
53 | boost::asio::error::get_system_category()); | |
54 | boost::asio::detail::throw_error(ec, "thread"); | |
55 | } | |
56 | arg.release(); | |
57 | } | |
58 | ||
59 | // Destructor. | |
60 | ~winapi_thread() | |
61 | { | |
62 | ::CloseHandle(thread_); | |
63 | } | |
64 | ||
65 | // Wait for the thread to exit. | |
66 | void join() | |
67 | { | |
68 | #if defined(BOOST_ASIO_WINDOWS_APP) | |
69 | ::WaitForSingleObjectEx(thread_, INFINITE, false); | |
70 | #else // defined(BOOST_ASIO_WINDOWS_APP) | |
71 | ::WaitForSingleObject(thread_, INFINITE); | |
72 | #endif // defined(BOOST_ASIO_WINDOWS_APP) | |
73 | } | |
74 | ||
75 | private: | |
76 | friend DWORD WINAPI winapi_thread_function(LPVOID arg); | |
77 | ||
78 | class func_base | |
79 | { | |
80 | public: | |
81 | virtual ~func_base() {} | |
82 | virtual void run() = 0; | |
83 | }; | |
84 | ||
85 | template <typename Function> | |
86 | class func | |
87 | : public func_base | |
88 | { | |
89 | public: | |
90 | func(Function f) | |
91 | : f_(f) | |
92 | { | |
93 | } | |
94 | ||
95 | virtual void run() | |
96 | { | |
97 | f_(); | |
98 | } | |
99 | ||
100 | private: | |
101 | Function f_; | |
102 | }; | |
103 | ||
104 | ::HANDLE thread_; | |
105 | }; | |
106 | ||
107 | inline DWORD WINAPI winapi_thread_function(LPVOID arg) | |
108 | { | |
109 | std::auto_ptr<winapi_thread::func_base> func( | |
110 | static_cast<winapi_thread::func_base*>(arg)); | |
111 | func->run(); | |
112 | return 0; | |
113 | } | |
114 | ||
115 | } // namespace detail | |
116 | } // namespace asio | |
117 | } // namespace boost | |
118 | ||
119 | #include <boost/asio/detail/pop_options.hpp> | |
120 | ||
121 | #endif // defined(BOOST_ASIO_WINDOWS_APP) || defined(UNDER_CE) | |
122 | #endif // defined(BOOST_ASIO_WINDOWS) | |
123 | ||
124 | #endif // BOOST_ASIO_DETAIL_WINAPI_THREAD_HPP |