/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. #ifndef BOOST_ASIO_DETAIL_IMPL_WIN_THREAD_IPP
  11. #define BOOST_ASIO_DETAIL_IMPL_WIN_THREAD_IPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #if defined(BOOST_WINDOWS) && !defined(UNDER_CE)
  17. #include <process.h>
  18. #include <boost/asio/detail/throw_error.hpp>
  19. #include <boost/asio/detail/win_thread.hpp>
  20. #include <boost/asio/error.hpp>
  21. #include <boost/asio/detail/push_options.hpp>
  22. namespace boost {
  23. namespace asio {
  24. namespace detail {
  25. win_thread::~win_thread()
  26. {
  27. ::CloseHandle(thread_);
  28. // The exit_event_ handle is deliberately allowed to leak here since it
  29. // is an error for the owner of an internal thread not to join() it.
  30. }
  31. void win_thread::join()
  32. {
  33. HANDLE handles[2] = { exit_event_, thread_ };
  34. ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
  35. ::CloseHandle(exit_event_);
  36. if (terminate_threads())
  37. {
  38. ::TerminateThread(thread_, 0);
  39. }
  40. else
  41. {
  42. ::QueueUserAPC(apc_function, thread_, 0);
  43. ::WaitForSingleObject(thread_, INFINITE);
  44. }
  45. }
  46. void win_thread::start_thread(func_base* arg, unsigned int stack_size)
  47. {
  48. ::HANDLE entry_event = 0;
  49. arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
  50. if (!entry_event)
  51. {
  52. DWORD last_error = ::GetLastError();
  53. delete arg;
  54. boost::system::error_code ec(last_error,
  55. boost::asio::error::get_system_category());
  56. boost::asio::detail::throw_error(ec, "thread.entry_event");
  57. }
  58. arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
  59. if (!exit_event_)
  60. {
  61. DWORD last_error = ::GetLastError();
  62. delete arg;
  63. boost::system::error_code ec(last_error,
  64. boost::asio::error::get_system_category());
  65. boost::asio::detail::throw_error(ec, "thread.exit_event");
  66. }
  67. unsigned int thread_id = 0;
  68. thread_ = reinterpret_cast<HANDLE>(::_beginthreadex(0,
  69. stack_size, win_thread_function, arg, 0, &thread_id));
  70. if (!thread_)
  71. {
  72. DWORD last_error = ::GetLastError();
  73. delete arg;
  74. if (entry_event)
  75. ::CloseHandle(entry_event);
  76. if (exit_event_)
  77. ::CloseHandle(exit_event_);
  78. boost::system::error_code ec(last_error,
  79. boost::asio::error::get_system_category());
  80. boost::asio::detail::throw_error(ec, "thread");
  81. }
  82. if (entry_event)
  83. {
  84. ::WaitForSingleObject(entry_event, INFINITE);
  85. ::CloseHandle(entry_event);
  86. }
  87. }
  88. unsigned int __stdcall win_thread_function(void* arg)
  89. {
  90. win_thread::auto_func_base_ptr func = {
  91. static_cast<win_thread::func_base*>(arg) };
  92. ::SetEvent(func.ptr->entry_event_);
  93. func.ptr->run();
  94. // Signal that the thread has finished its work, but rather than returning go
  95. // to sleep to put the thread into a well known state. If the thread is being
  96. // joined during global object destruction then it may be killed using
  97. // TerminateThread (to avoid a deadlock in DllMain). Otherwise, the SleepEx
  98. // call will be interrupted using QueueUserAPC and the thread will shut down
  99. // cleanly.
  100. HANDLE exit_event = func.ptr->exit_event_;
  101. delete func.ptr;
  102. func.ptr = 0;
  103. ::SetEvent(exit_event);
  104. ::SleepEx(INFINITE, TRUE);
  105. return 0;
  106. }
  107. #if defined(WINVER) && (WINVER < 0x0500)
  108. void __stdcall apc_function(ULONG) {}
  109. #else
  110. void __stdcall apc_function(ULONG_PTR) {}
  111. #endif
  112. } // namespace detail
  113. } // namespace asio
  114. } // namespace boost
  115. #include <boost/asio/detail/pop_options.hpp>
  116. #endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
  117. #endif // BOOST_ASIO_DETAIL_IMPL_WIN_THREAD_IPP