0002-remove-use-of-aligned-union.patch 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. From 65267c6e83e7e29ed3bdddde13d2c4bbb10e1bff Mon Sep 17 00:00:00 2001
  2. From: Billy O'Neal <billy.oneal@gmail.com>
  3. Date: Thu, 6 Dec 2018 23:57:00 -0800
  4. Subject: [PATCH] Remove use of aligned_union that broke CentOS 7. (#987)
  5. Signed-off-by: Billy O'Neal <billy.oneal@gmail.com>
  6. [Backport from upstream commit 65267c6e83e7e29ed3bdddde13d2c4bbb10e1bff]
  7. Signed-off-by: Adam Duskett <aduskett@gmail.com>
  8. ---
  9. Release/src/pplx/threadpool.cpp | 127 +++++++++++++++-----------------
  10. 1 file changed, 61 insertions(+), 66 deletions(-)
  11. diff --git a/Release/src/pplx/threadpool.cpp b/Release/src/pplx/threadpool.cpp
  12. index 1c28cca8f..58920c025 100644
  13. --- a/Release/src/pplx/threadpool.cpp
  14. +++ b/Release/src/pplx/threadpool.cpp
  15. @@ -1,9 +1,7 @@
  16. /***
  17. -* Copyright (C) Microsoft. All rights reserved.
  18. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  19. -*
  20. -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  21. -**/
  22. + * Copyright (C) Microsoft. All rights reserved.
  23. + * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  24. + **/
  25. #include "stdafx.h"
  26. #if !defined(CPPREST_EXCLUDE_WEBSOCKETS) || !defined(_WIN32)
  27. @@ -11,8 +9,9 @@
  28. #include <boost/asio/detail/thread.hpp>
  29. #include <new>
  30. -#include <vector>
  31. #include <type_traits>
  32. +#include <utility>
  33. +#include <vector>
  34. #if defined(__ANDROID__)
  35. #include <android/log.h>
  36. @@ -29,9 +28,11 @@ static void abort_if_no_jvm()
  37. {
  38. if (JVM == nullptr)
  39. {
  40. - __android_log_print(ANDROID_LOG_ERROR, "CPPRESTSDK", "%s",
  41. - "The CppREST SDK must be initialized before first use on android: "
  42. - "https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-Android");
  43. + __android_log_print(ANDROID_LOG_ERROR,
  44. + "CPPRESTSDK",
  45. + "%s",
  46. + "The CppREST SDK must be initialized before first use on android: "
  47. + "https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-Android");
  48. std::abort();
  49. }
  50. }
  51. @@ -52,9 +53,7 @@ JNIEnv* get_jvm_env()
  52. struct threadpool_impl final : crossplat::threadpool
  53. {
  54. - threadpool_impl(size_t n)
  55. - : crossplat::threadpool(n)
  56. - , m_work(m_service)
  57. + threadpool_impl(size_t n) : crossplat::threadpool(n), m_work(m_service)
  58. {
  59. for (size_t i = 0; i < n; i++)
  60. add_thread();
  61. @@ -69,26 +68,20 @@ struct threadpool_impl final : crossplat::threadpool
  62. }
  63. }
  64. - threadpool_impl& get_shared()
  65. - {
  66. - return *this;
  67. - }
  68. + threadpool_impl& get_shared() { return *this; }
  69. private:
  70. void add_thread()
  71. {
  72. - m_threads.push_back(std::unique_ptr<boost::asio::detail::thread>(
  73. - new boost::asio::detail::thread([&]{ thread_start(this); })));
  74. + m_threads.push_back(
  75. + std::unique_ptr<boost::asio::detail::thread>(new boost::asio::detail::thread([&] { thread_start(this); })));
  76. }
  77. #if defined(__ANDROID__)
  78. - static void detach_from_java(void*)
  79. - {
  80. - JVM.load()->DetachCurrentThread();
  81. - }
  82. + static void detach_from_java(void*) { JVM.load()->DetachCurrentThread(); }
  83. #endif // __ANDROID__
  84. - static void* thread_start(void *arg) CPPREST_NOEXCEPT
  85. + static void* thread_start(void* arg) CPPREST_NOEXCEPT
  86. {
  87. #if defined(__ANDROID__)
  88. // Calling get_jvm_env() here forces the thread to be attached.
  89. @@ -110,17 +103,14 @@ struct threadpool_impl final : crossplat::threadpool
  90. #if defined(_WIN32)
  91. struct shared_threadpool
  92. {
  93. - std::aligned_union<0, threadpool_impl>::type shared_storage;
  94. + union {
  95. + threadpool_impl shared_storage;
  96. + };
  97. - threadpool_impl& get_shared()
  98. - {
  99. - return reinterpret_cast<threadpool_impl&>(shared_storage);
  100. - }
  101. + threadpool_impl& get_shared() { return shared_storage; }
  102. +
  103. + shared_threadpool(size_t n) : shared_storage(n) {}
  104. - shared_threadpool(size_t n)
  105. - {
  106. - ::new (static_cast<void*>(&get_shared())) threadpool_impl(n);
  107. - }
  108. ~shared_threadpool()
  109. {
  110. // if linked into a DLL, the threadpool shared instance will be
  111. @@ -138,52 +128,59 @@ typedef shared_threadpool platform_shared_threadpool;
  112. typedef threadpool_impl platform_shared_threadpool;
  113. #endif
  114. -std::pair<bool, platform_shared_threadpool*> initialize_shared_threadpool(size_t num_threads)
  115. +namespace
  116. {
  117. - static std::aligned_union<0, platform_shared_threadpool>::type storage;
  118. - platform_shared_threadpool* const ptr =
  119. - &reinterpret_cast<platform_shared_threadpool&>(storage);
  120. - bool initialized_this_time = false;
  121. -#if defined(__ANDROID__)
  122. - // mutex based implementation due to paranoia about (lack of) call_once support on Android
  123. - // remove this if/when call_once is supported
  124. - static std::mutex mtx;
  125. - static std::atomic<bool> initialized;
  126. - abort_if_no_jvm();
  127. - if (!initialized.load())
  128. +template<class T>
  129. +struct uninitialized
  130. +{
  131. + union {
  132. + T storage;
  133. + };
  134. +
  135. + bool initialized;
  136. +
  137. + uninitialized() CPPREST_NOEXCEPT : initialized(false) {}
  138. + uninitialized(const uninitialized&) = delete;
  139. + uninitialized& operator=(const uninitialized&) = delete;
  140. + ~uninitialized()
  141. {
  142. - std::lock_guard<std::mutex> guard(mtx);
  143. - if (!initialized.load())
  144. + if (initialized)
  145. {
  146. - ::new (static_cast<void*>(ptr)) platform_shared_threadpool(num_threads);
  147. - initialized.store(true);
  148. - initialized_this_time = true;
  149. + storage.~T();
  150. }
  151. - } // also unlock
  152. + }
  153. +
  154. + template<class... Args>
  155. + void construct(Args&&... vals)
  156. + {
  157. + ::new (static_cast<void*>(&storage)) T(std::forward<Args>(vals)...);
  158. + initialized = true;
  159. + }
  160. +};
  161. +} // unnamed namespace
  162. -#else // ^^^ __ANDROID__ ^^^ // vvv !__ANDROID___ vvv //
  163. +std::pair<bool, platform_shared_threadpool*> initialize_shared_threadpool(size_t num_threads)
  164. +{
  165. + static uninitialized<platform_shared_threadpool> uninit_threadpool;
  166. + bool initialized_this_time = false;
  167. static std::once_flag of;
  168. -// #if defined(__ANDROID__) // if call_once can be used for android
  169. -// abort_if_no_jvm();
  170. -// #endif // __ANDROID__
  171. - std::call_once(of, [num_threads, ptr, &initialized_this_time] {
  172. - ::new (static_cast<void*>(ptr)) platform_shared_threadpool(num_threads);
  173. + #if defined(__ANDROID__)
  174. + abort_if_no_jvm();
  175. + #endif // __ANDROID__
  176. +
  177. + std::call_once(of, [num_threads, &initialized_this_time] {
  178. + uninit_threadpool.construct(num_threads);
  179. initialized_this_time = true;
  180. });
  181. -#endif // __ANDROID__
  182. - return {initialized_this_time, ptr};
  183. + return {initialized_this_time, &uninit_threadpool.storage};
  184. }
  185. }
  186. namespace crossplat
  187. {
  188. -threadpool& threadpool::shared_instance()
  189. -{
  190. - return initialize_shared_threadpool(40).second->get_shared();
  191. -}
  192. -
  193. +threadpool& threadpool::shared_instance() { return initialize_shared_threadpool(40).second->get_shared(); }
  194. void threadpool::initialize_with_threads(size_t num_threads)
  195. {
  196. @@ -196,9 +193,7 @@ void threadpool::initialize_with_threads(size_t num_threads)
  197. }
  198. #if defined(__ANDROID__)
  199. -void cpprest_init(JavaVM* vm) {
  200. - JVM = vm;
  201. -}
  202. +void cpprest_init(JavaVM* vm) { JVM = vm; }
  203. #endif
  204. std::unique_ptr<crossplat::threadpool> crossplat::threadpool::construct(size_t num_threads)