Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

151 lines
3.8KB

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