Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef ASIO_DETAIL_WIN_THREAD_HPP
00012 #define ASIO_DETAIL_WIN_THREAD_HPP
00013
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017
00018 #include "asio/detail/push_options.hpp"
00019
00020 #include "asio/detail/push_options.hpp"
00021 #include <boost/config.hpp>
00022 #include "asio/detail/pop_options.hpp"
00023
00024 #if defined(BOOST_WINDOWS) && !defined(UNDER_CE)
00025
00026 #include "asio/error.hpp"
00027 #include "asio/system_error.hpp"
00028 #include "asio/detail/noncopyable.hpp"
00029 #include "asio/detail/socket_types.hpp"
00030
00031 #include "asio/detail/push_options.hpp"
00032 #include <boost/throw_exception.hpp>
00033 #include <memory>
00034 #include <process.h>
00035 #include "asio/detail/pop_options.hpp"
00036
00037 namespace asio {
00038 namespace detail {
00039
00040 unsigned int __stdcall win_thread_function(void* arg);
00041
00042 class win_thread
00043 : private noncopyable
00044 {
00045 public:
00046
00047 enum purpose { internal, external };
00048
00049
00050 template <typename Function>
00051 win_thread(Function f, purpose p = internal)
00052 : exit_event_(0)
00053 {
00054 std::auto_ptr<func_base> arg(new func<Function>(f));
00055
00056 ::HANDLE entry_event = 0;
00057 if (p == internal)
00058 {
00059 arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
00060 if (!entry_event)
00061 {
00062 DWORD last_error = ::GetLastError();
00063 asio::system_error e(
00064 asio::error_code(last_error,
00065 asio::error::get_system_category()),
00066 "thread.entry_event");
00067 boost::throw_exception(e);
00068 }
00069
00070 arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
00071 if (!exit_event_)
00072 {
00073 DWORD last_error = ::GetLastError();
00074 ::CloseHandle(entry_event);
00075 asio::system_error e(
00076 asio::error_code(last_error,
00077 asio::error::get_system_category()),
00078 "thread.exit_event");
00079 boost::throw_exception(e);
00080 }
00081 }
00082
00083 unsigned int thread_id = 0;
00084 thread_ = reinterpret_cast<HANDLE>(::_beginthreadex(0, 0,
00085 win_thread_function, arg.get(), 0, &thread_id));
00086 if (!thread_)
00087 {
00088 DWORD last_error = ::GetLastError();
00089 if (entry_event)
00090 ::CloseHandle(entry_event);
00091 if (exit_event_)
00092 ::CloseHandle(exit_event_);
00093 asio::system_error e(
00094 asio::error_code(last_error,
00095 asio::error::get_system_category()),
00096 "thread");
00097 boost::throw_exception(e);
00098 }
00099 arg.release();
00100
00101 if (entry_event)
00102 {
00103 ::WaitForSingleObject(entry_event, INFINITE);
00104 ::CloseHandle(entry_event);
00105 }
00106 }
00107
00108
00109 ~win_thread()
00110 {
00111 ::CloseHandle(thread_);
00112
00113
00114
00115 }
00116
00117
00118 void join()
00119 {
00120 if (exit_event_)
00121 {
00122 ::WaitForSingleObject(exit_event_, INFINITE);
00123 ::CloseHandle(exit_event_);
00124 ::TerminateThread(thread_, 0);
00125 }
00126 else
00127 {
00128 ::WaitForSingleObject(thread_, INFINITE);
00129 }
00130 }
00131
00132 private:
00133 friend unsigned int __stdcall win_thread_function(void* arg);
00134
00135 class func_base
00136 {
00137 public:
00138 virtual ~func_base() {}
00139 virtual void run() = 0;
00140 ::HANDLE entry_event_;
00141 ::HANDLE exit_event_;
00142 };
00143
00144 template <typename Function>
00145 class func
00146 : public func_base
00147 {
00148 public:
00149 func(Function f)
00150 : f_(f)
00151 {
00152 }
00153
00154 virtual void run()
00155 {
00156 f_();
00157 }
00158
00159 private:
00160 Function f_;
00161 };
00162
00163 ::HANDLE thread_;
00164 ::HANDLE exit_event_;
00165 };
00166
00167 inline unsigned int __stdcall win_thread_function(void* arg)
00168 {
00169 std::auto_ptr<win_thread::func_base> func(
00170 static_cast<win_thread::func_base*>(arg));
00171
00172 if (func->entry_event_)
00173 ::SetEvent(func->entry_event_);
00174
00175 func->run();
00176
00177 if (HANDLE exit_event = func->exit_event_)
00178 {
00179 func.reset();
00180 ::SetEvent(exit_event);
00181 ::Sleep(INFINITE);
00182 }
00183
00184 return 0;
00185 }
00186
00187 }
00188 }
00189
00190 #endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
00191
00192 #include "asio/detail/pop_options.hpp"
00193
00194 #endif // ASIO_DETAIL_WIN_THREAD_HPP