Remove use of aligned_union that broke CentOS 7. (#987)
This commit is contained in:
Родитель
744f33baec
Коммит
65267c6e83
|
@ -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,9 @@
|
|||
|
||||
#include <boost/asio/detail/thread.hpp>
|
||||
#include <new>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/log.h>
|
||||
|
@ -29,9 +28,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 +53,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 +68,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<boost::asio::detail::thread>(
|
||||
new boost::asio::detail::thread([&]{ thread_start(this); })));
|
||||
m_threads.push_back(
|
||||
std::unique_ptr<boost::asio::detail::thread>(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 +103,14 @@ private:
|
|||
#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<threadpool_impl&>(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<void*>(&get_shared())) threadpool_impl(n);
|
||||
}
|
||||
~shared_threadpool()
|
||||
{
|
||||
// if linked into a DLL, the threadpool shared instance will be
|
||||
|
@ -138,52 +128,59 @@ typedef shared_threadpool platform_shared_threadpool;
|
|||
typedef threadpool_impl platform_shared_threadpool;
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
template<class T>
|
||||
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<class... Args>
|
||||
void construct(Args&&... vals)
|
||||
{
|
||||
::new (static_cast<void*>(&storage)) T(std::forward<Args>(vals)...);
|
||||
initialized = true;
|
||||
}
|
||||
};
|
||||
} // unnamed namespace
|
||||
|
||||
std::pair<bool, platform_shared_threadpool*> initialize_shared_threadpool(size_t num_threads)
|
||||
{
|
||||
static std::aligned_union<0, platform_shared_threadpool>::type storage;
|
||||
platform_shared_threadpool* const ptr =
|
||||
&reinterpret_cast<platform_shared_threadpool&>(storage);
|
||||
static uninitialized<platform_shared_threadpool> 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<bool> initialized;
|
||||
abort_if_no_jvm();
|
||||
if (!initialized.load())
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mtx);
|
||||
if (!initialized.load())
|
||||
{
|
||||
::new (static_cast<void*>(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__
|
||||
std::call_once(of, [num_threads, ptr, &initialized_this_time] {
|
||||
::new (static_cast<void*>(ptr)) platform_shared_threadpool(num_threads);
|
||||
#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, ptr};
|
||||
return {initialized_this_time, &uninit_threadpool.storage};
|
||||
}
|
||||
}
|
||||
|
||||
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 +193,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> crossplat::threadpool::construct(size_t num_threads)
|
||||
|
|
Загрузка…
Ссылка в новой задаче