PageRenderTime 35ms CodeModel.GetById 32ms app.highlight 1ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/asio/detail/impl/win_thread.ipp

http://hadesmem.googlecode.com/
C++ Header | 141 lines | 100 code | 24 blank | 17 comment | 10 complexity | 64be2217c0fb00c37b047de6d23fc0a5 MD5 | raw file
  1//
  2// detail/impl/win_thread.ipp
  3// ~~~~~~~~~~~~~~~~~~~~~~~~~~
  4//
  5// Copyright (c) 2003-2011 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_IMPL_WIN_THREAD_IPP
 12#define BOOST_ASIO_DETAIL_IMPL_WIN_THREAD_IPP
 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_WINDOWS) && !defined(UNDER_CE)
 21
 22#include <process.h>
 23#include <boost/asio/detail/throw_error.hpp>
 24#include <boost/asio/detail/win_thread.hpp>
 25#include <boost/asio/error.hpp>
 26
 27#include <boost/asio/detail/push_options.hpp>
 28
 29namespace boost {
 30namespace asio {
 31namespace detail {
 32
 33win_thread::~win_thread()
 34{
 35  ::CloseHandle(thread_);
 36
 37  // The exit_event_ handle is deliberately allowed to leak here since it
 38  // is an error for the owner of an internal thread not to join() it.
 39}
 40
 41void win_thread::join()
 42{
 43  HANDLE handles[2] = { exit_event_, thread_ };
 44  ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
 45  ::CloseHandle(exit_event_);
 46  if (terminate_threads())
 47  {
 48    ::TerminateThread(thread_, 0);
 49  }
 50  else
 51  {
 52    ::QueueUserAPC(apc_function, thread_, 0);
 53    ::WaitForSingleObject(thread_, INFINITE);
 54  }
 55}
 56
 57void win_thread::start_thread(func_base* arg, unsigned int stack_size)
 58{
 59  ::HANDLE entry_event = 0;
 60  arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
 61  if (!entry_event)
 62  {
 63    DWORD last_error = ::GetLastError();
 64    delete arg;
 65    boost::system::error_code ec(last_error,
 66        boost::asio::error::get_system_category());
 67    boost::asio::detail::throw_error(ec, "thread.entry_event");
 68  }
 69
 70  arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
 71  if (!exit_event_)
 72  {
 73    DWORD last_error = ::GetLastError();
 74    delete arg;
 75    boost::system::error_code ec(last_error,
 76        boost::asio::error::get_system_category());
 77    boost::asio::detail::throw_error(ec, "thread.exit_event");
 78  }
 79
 80  unsigned int thread_id = 0;
 81  thread_ = reinterpret_cast<HANDLE>(::_beginthreadex(0,
 82        stack_size, win_thread_function, arg, 0, &thread_id));
 83  if (!thread_)
 84  {
 85    DWORD last_error = ::GetLastError();
 86    delete arg;
 87    if (entry_event)
 88      ::CloseHandle(entry_event);
 89    if (exit_event_)
 90      ::CloseHandle(exit_event_);
 91    boost::system::error_code ec(last_error,
 92        boost::asio::error::get_system_category());
 93    boost::asio::detail::throw_error(ec, "thread");
 94  }
 95
 96  if (entry_event)
 97  {
 98    ::WaitForSingleObject(entry_event, INFINITE);
 99    ::CloseHandle(entry_event);
100  }
101}
102
103unsigned int __stdcall win_thread_function(void* arg)
104{
105  win_thread::auto_func_base_ptr func = {
106      static_cast<win_thread::func_base*>(arg) };
107
108  ::SetEvent(func.ptr->entry_event_);
109
110  func.ptr->run();
111
112  // Signal that the thread has finished its work, but rather than returning go
113  // to sleep to put the thread into a well known state. If the thread is being
114  // joined during global object destruction then it may be killed using
115  // TerminateThread (to avoid a deadlock in DllMain). Otherwise, the SleepEx
116  // call will be interrupted using QueueUserAPC and the thread will shut down
117  // cleanly.
118  HANDLE exit_event = func.ptr->exit_event_;
119  delete func.ptr;
120  func.ptr = 0;
121  ::SetEvent(exit_event);
122  ::SleepEx(INFINITE, TRUE);
123
124  return 0;
125}
126
127#if defined(WINVER) && (WINVER < 0x0500)
128void __stdcall apc_function(ULONG) {}
129#else
130void __stdcall apc_function(ULONG_PTR) {}
131#endif
132
133} // namespace detail
134} // namespace asio
135} // namespace boost
136
137#include <boost/asio/detail/pop_options.hpp>
138
139#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
140
141#endif // BOOST_ASIO_DETAIL_IMPL_WIN_THREAD_IPP