5
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11
#ifndef ASIO_DETAIL_WIN_THREAD_HPP
12
#define ASIO_DETAIL_WIN_THREAD_HPP
14
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
16
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18
#include "asio/detail/push_options.hpp"
20
#include "asio/detail/push_options.hpp"
21
#include <boost/config.hpp>
22
#include "asio/detail/pop_options.hpp"
24
#if defined(BOOST_WINDOWS) && !defined(UNDER_CE)
26
#include "asio/error.hpp"
27
#include "asio/system_error.hpp"
28
#include "asio/detail/noncopyable.hpp"
29
#include "asio/detail/socket_types.hpp"
31
#include "asio/detail/push_options.hpp"
32
#include <boost/throw_exception.hpp>
35
#include "asio/detail/pop_options.hpp"
40
unsigned int __stdcall win_thread_function(void* arg);
46
// The purpose of the thread.
47
enum purpose { internal, external };
50
template <typename Function>
51
win_thread(Function f, purpose p = internal)
54
std::auto_ptr<func_base> arg(new func<Function>(f));
56
::HANDLE entry_event = 0;
59
arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
62
DWORD last_error = ::GetLastError();
64
asio::error_code(last_error,
65
asio::error::get_system_category()),
66
"thread.entry_event");
67
boost::throw_exception(e);
70
arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
73
DWORD last_error = ::GetLastError();
74
::CloseHandle(entry_event);
76
asio::error_code(last_error,
77
asio::error::get_system_category()),
79
boost::throw_exception(e);
83
unsigned int thread_id = 0;
84
thread_ = reinterpret_cast<HANDLE>(::_beginthreadex(0, 0,
85
win_thread_function, arg.get(), 0, &thread_id));
88
DWORD last_error = ::GetLastError();
90
::CloseHandle(entry_event);
92
::CloseHandle(exit_event_);
94
asio::error_code(last_error,
95
asio::error::get_system_category()),
97
boost::throw_exception(e);
103
::WaitForSingleObject(entry_event, INFINITE);
104
::CloseHandle(entry_event);
111
::CloseHandle(thread_);
113
// The exit_event_ handle is deliberately allowed to leak here since it
114
// is an error for the owner of an internal thread not to join() it.
117
// Wait for the thread to exit.
122
::WaitForSingleObject(exit_event_, INFINITE);
123
::CloseHandle(exit_event_);
124
::TerminateThread(thread_, 0);
128
::WaitForSingleObject(thread_, INFINITE);
133
friend unsigned int __stdcall win_thread_function(void* arg);
138
virtual ~func_base() {}
139
virtual void run() = 0;
140
::HANDLE entry_event_;
141
::HANDLE exit_event_;
144
template <typename Function>
164
::HANDLE exit_event_;
167
inline unsigned int __stdcall win_thread_function(void* arg)
169
std::auto_ptr<win_thread::func_base> func(
170
static_cast<win_thread::func_base*>(arg));
172
if (func->entry_event_)
173
::SetEvent(func->entry_event_);
177
if (HANDLE exit_event = func->exit_event_)
180
::SetEvent(exit_event);
187
} // namespace detail
190
#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
192
#include "asio/detail/pop_options.hpp"
194
#endif // ASIO_DETAIL_WIN_THREAD_HPP