From fb8d6d603a60035571585b8d297899f71813b4bc Mon Sep 17 00:00:00 2001 From: "Billy O'Neal (VC LIBS)" Date: Fri, 30 Nov 2018 13:44:38 -0800 Subject: [PATCH 1/3] Remove use of aligned_union that broke CentOS 7. --- Release/src/pplx/threadpool.cpp | 78 +++++++++++++-------------------- 1 file changed, 30 insertions(+), 48 deletions(-) diff --git a/Release/src/pplx/threadpool.cpp b/Release/src/pplx/threadpool.cpp index 1c28cca8f7..84acb31f0a 100644 --- a/Release/src/pplx/threadpool.cpp +++ b/Release/src/pplx/threadpool.cpp @@ -1,9 +1,7 @@ /*** -* Copyright (C) Microsoft. All rights reserved. -* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -* -* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -**/ + * Copyright (C) Microsoft. All rights reserved. + * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. + **/ #include "stdafx.h" #if !defined(CPPREST_EXCLUDE_WEBSOCKETS) || !defined(_WIN32) @@ -11,8 +9,8 @@ #include #include -#include #include +#include #if defined(__ANDROID__) #include @@ -29,9 +27,11 @@ static void abort_if_no_jvm() { if (JVM == nullptr) { - __android_log_print(ANDROID_LOG_ERROR, "CPPRESTSDK", "%s", - "The CppREST SDK must be initialized before first use on android: " - "https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-Android"); + __android_log_print(ANDROID_LOG_ERROR, + "CPPRESTSDK", + "%s", + "The CppREST SDK must be initialized before first use on android: " + "https://github.com/Microsoft/cpprestsdk/wiki/How-to-build-for-Android"); std::abort(); } } @@ -52,9 +52,7 @@ JNIEnv* get_jvm_env() struct threadpool_impl final : crossplat::threadpool { - threadpool_impl(size_t n) - : crossplat::threadpool(n) - , m_work(m_service) + threadpool_impl(size_t n) : crossplat::threadpool(n), m_work(m_service) { for (size_t i = 0; i < n; i++) add_thread(); @@ -69,26 +67,20 @@ struct threadpool_impl final : crossplat::threadpool } } - threadpool_impl& get_shared() - { - return *this; - } + threadpool_impl& get_shared() { return *this; } private: void add_thread() { - m_threads.push_back(std::unique_ptr( - new boost::asio::detail::thread([&]{ thread_start(this); }))); + m_threads.push_back( + std::unique_ptr(new boost::asio::detail::thread([&] { thread_start(this); }))); } #if defined(__ANDROID__) - static void detach_from_java(void*) - { - JVM.load()->DetachCurrentThread(); - } + static void detach_from_java(void*) { JVM.load()->DetachCurrentThread(); } #endif // __ANDROID__ - static void* thread_start(void *arg) CPPREST_NOEXCEPT + static void* thread_start(void* arg) CPPREST_NOEXCEPT { #if defined(__ANDROID__) // Calling get_jvm_env() here forces the thread to be attached. @@ -110,17 +102,14 @@ struct threadpool_impl final : crossplat::threadpool #if defined(_WIN32) struct shared_threadpool { - std::aligned_union<0, threadpool_impl>::type shared_storage; + union { + threadpool_impl shared_storage; + }; - threadpool_impl& get_shared() - { - return reinterpret_cast(shared_storage); - } + threadpool_impl& get_shared() { return shared_storage; } + + shared_threadpool(size_t n) : shared_storage(n) {} - shared_threadpool(size_t n) - { - ::new (static_cast(&get_shared())) threadpool_impl(n); - } ~shared_threadpool() { // if linked into a DLL, the threadpool shared instance will be @@ -140,9 +129,8 @@ typedef threadpool_impl platform_shared_threadpool; std::pair initialize_shared_threadpool(size_t num_threads) { - static std::aligned_union<0, platform_shared_threadpool>::type storage; - platform_shared_threadpool* const ptr = - &reinterpret_cast(storage); + static alignas(platform_shared_threadpool) unsigned char storage[sizeof(platform_shared_threadpool)]; + platform_shared_threadpool* const ptr = &reinterpret_cast(storage); bool initialized_this_time = false; #if defined(__ANDROID__) // mutex based implementation due to paranoia about (lack of) call_once support on Android @@ -159,14 +147,14 @@ std::pair initialize_shared_threadpool(size_t initialized.store(true); initialized_this_time = true; } - } // also unlock + } // also unlock -#else // ^^^ __ANDROID__ ^^^ // vvv !__ANDROID___ vvv // +#else // ^^^ __ANDROID__ ^^^ // vvv !__ANDROID___ vvv // static std::once_flag of; -// #if defined(__ANDROID__) // if call_once can be used for android -// abort_if_no_jvm(); -// #endif // __ANDROID__ + // #if defined(__ANDROID__) // if call_once can be used for android + // abort_if_no_jvm(); + // #endif // __ANDROID__ std::call_once(of, [num_threads, ptr, &initialized_this_time] { ::new (static_cast(ptr)) platform_shared_threadpool(num_threads); initialized_this_time = true; @@ -179,11 +167,7 @@ std::pair initialize_shared_threadpool(size_t namespace crossplat { -threadpool& threadpool::shared_instance() -{ - return initialize_shared_threadpool(40).second->get_shared(); -} - +threadpool& threadpool::shared_instance() { return initialize_shared_threadpool(40).second->get_shared(); } void threadpool::initialize_with_threads(size_t num_threads) { @@ -196,9 +180,7 @@ void threadpool::initialize_with_threads(size_t num_threads) } #if defined(__ANDROID__) -void cpprest_init(JavaVM* vm) { - JVM = vm; -} +void cpprest_init(JavaVM* vm) { JVM = vm; } #endif std::unique_ptr crossplat::threadpool::construct(size_t num_threads) From 3d9582b9e8bd6ad4fdecece3136ac8d4e384c644 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Fri, 30 Nov 2018 15:14:06 -0800 Subject: [PATCH 2/3] Fix destruction and build on Linux. --- Release/src/pplx/threadpool.cpp | 41 +++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/Release/src/pplx/threadpool.cpp b/Release/src/pplx/threadpool.cpp index 84acb31f0a..26c4642d9e 100644 --- a/Release/src/pplx/threadpool.cpp +++ b/Release/src/pplx/threadpool.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #if defined(__ANDROID__) @@ -127,10 +128,40 @@ typedef shared_threadpool platform_shared_threadpool; typedef threadpool_impl platform_shared_threadpool; #endif +namespace +{ +template +struct uninitialized +{ + union { + T storage; + }; + + bool initialized; + + uninitialized() CPPREST_NOEXCEPT : initialized(false) {} + uninitialized(const uninitialized&) = delete; + uninitialized& operator=(const uninitialized&) = delete; + ~uninitialized() + { + if (initialized) + { + storage.~T(); + } + } + + template + void construct(Args&&... vals) + { + ::new (static_cast(&storage)) T(std::forward(vals)...); + initialized = true; + } +}; +} // unnamed namespace + std::pair initialize_shared_threadpool(size_t num_threads) { - static alignas(platform_shared_threadpool) unsigned char storage[sizeof(platform_shared_threadpool)]; - platform_shared_threadpool* const ptr = &reinterpret_cast(storage); + static uninitialized uninit_threadpool; bool initialized_this_time = false; #if defined(__ANDROID__) // mutex based implementation due to paranoia about (lack of) call_once support on Android @@ -155,13 +186,13 @@ std::pair initialize_shared_threadpool(size_t // #if defined(__ANDROID__) // if call_once can be used for android // abort_if_no_jvm(); // #endif // __ANDROID__ - std::call_once(of, [num_threads, ptr, &initialized_this_time] { - ::new (static_cast(ptr)) platform_shared_threadpool(num_threads); + std::call_once(of, [num_threads, &initialized_this_time] { + uninit_threadpool.construct(num_threads); initialized_this_time = true; }); #endif // __ANDROID__ - return {initialized_this_time, ptr}; + return {initialized_this_time, &uninit_threadpool.storage}; } } From e44f5be0485b7c212a5110024c9da0d334b65f40 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 4 Dec 2018 14:10:57 -0800 Subject: [PATCH 3/3] Remove once_flag avoiding path for Android. --- Release/src/pplx/threadpool.cpp | 26 ++++---------------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/Release/src/pplx/threadpool.cpp b/Release/src/pplx/threadpool.cpp index 26c4642d9e..58920c0253 100644 --- a/Release/src/pplx/threadpool.cpp +++ b/Release/src/pplx/threadpool.cpp @@ -163,34 +163,16 @@ std::pair initialize_shared_threadpool(size_t { static uninitialized uninit_threadpool; bool initialized_this_time = false; -#if defined(__ANDROID__) - // mutex based implementation due to paranoia about (lack of) call_once support on Android - // remove this if/when call_once is supported - static std::mutex mtx; - static std::atomic initialized; - abort_if_no_jvm(); - if (!initialized.load()) - { - std::lock_guard guard(mtx); - if (!initialized.load()) - { - ::new (static_cast(ptr)) platform_shared_threadpool(num_threads); - initialized.store(true); - initialized_this_time = true; - } - } // also unlock - -#else // ^^^ __ANDROID__ ^^^ // vvv !__ANDROID___ vvv // static std::once_flag of; - // #if defined(__ANDROID__) // if call_once can be used for android - // abort_if_no_jvm(); - // #endif // __ANDROID__ + #if defined(__ANDROID__) + abort_if_no_jvm(); + #endif // __ANDROID__ + std::call_once(of, [num_threads, &initialized_this_time] { uninit_threadpool.construct(num_threads); initialized_this_time = true; }); -#endif // __ANDROID__ return {initialized_this_time, &uninit_threadpool.storage}; }