From 866b78cbd00ec3160caf52fea0123f49250c2d9e Mon Sep 17 00:00:00 2001 From: Steve Gates Date: Tue, 8 Jul 2014 16:40:55 -0700 Subject: [PATCH] Addressing more feedback: Reverting disabling thread attributes for WinRT. Created common GetSystemInfo/GetNativeSystemInfo function. Fix this_thread get_id() bug on WinRT. Enabled initializing the Windows Runtime in each test for execution. This is not when using in Windows store/phone applications, just if a desktop app. --- include/boost/thread/detail/thread.hpp | 4 -- include/boost/thread/win32/once.hpp | 5 -- .../boost/thread/win32/thread_primitives.hpp | 24 ++++++-- src/win32/thread.cpp | 60 ++++++++----------- test/Jamfile.v2 | 7 +++ test/test_2741.cpp | 7 --- test/winrt_init.cpp | 17 ++++++ 7 files changed, 66 insertions(+), 58 deletions(-) create mode 100644 test/winrt_init.cpp diff --git a/include/boost/thread/detail/thread.hpp b/include/boost/thread/detail/thread.hpp index 73f3cc5c..3f922e5f 100644 --- a/include/boost/thread/detail/thread.hpp +++ b/include/boost/thread/detail/thread.hpp @@ -172,9 +172,7 @@ namespace boost private: bool start_thread_noexcept(); -#if !BOOST_PLAT_WINDOWS_RUNTIME bool start_thread_noexcept(const attributes& attr); -#endif //public: void start_thread() { @@ -183,7 +181,6 @@ namespace boost boost::throw_exception(thread_resource_error()); } } -#if !BOOST_PLAT_WINDOWS_RUNTIME void start_thread(const attributes& attr) { if (!start_thread_noexcept(attr)) @@ -191,7 +188,6 @@ namespace boost boost::throw_exception(thread_resource_error()); } } -#endif explicit thread(detail::thread_data_ptr data); diff --git a/include/boost/thread/win32/once.hpp b/include/boost/thread/win32/once.hpp index 19aa563a..24eb0f29 100644 --- a/include/boost/thread/win32/once.hpp +++ b/include/boost/thread/win32/once.hpp @@ -660,13 +660,8 @@ namespace boost continue; } } -# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP - BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( - ctx.event_handle,::boost::detail::win32::infinite)); -# else BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( ctx.event_handle,::boost::detail::win32::infinite,0)); -# endif } } template diff --git a/include/boost/thread/win32/thread_primitives.hpp b/include/boost/thread/win32/thread_primitives.hpp index ced1bdc3..0d86f97c 100644 --- a/include/boost/thread/win32/thread_primitives.hpp +++ b/include/boost/thread/win32/thread_primitives.hpp @@ -19,6 +19,10 @@ //#include #include +#if BOOST_PLAT_WINDOWS_RUNTIME +#include +#endif + //#ifndef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64 //#if _WIN32_WINNT >= 0x0600 && ! defined _WIN32_WINNT_WS08 //#define BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64 @@ -41,6 +45,7 @@ namespace boost //#endif typedef ULONG_PTR ulong_ptr; typedef HANDLE handle; + typedef SYSTEM_INFO system_info; unsigned const infinite=INFINITE; unsigned const timeout=WAIT_TIMEOUT; handle const invalid_handle_value=INVALID_HANDLE_VALUE; @@ -51,6 +56,7 @@ namespace boost unsigned const create_event_manual_reset = CREATE_EVENT_MANUAL_RESET; unsigned const event_all_access = EVENT_ALL_ACCESS; unsigned const semaphore_all_access = SEMAPHORE_ALL_ACCESS; + # ifdef BOOST_NO_ANSI_APIS # if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA @@ -117,13 +123,19 @@ extern "C" { typedef int BOOL; typedef unsigned long DWORD; typedef void* HANDLE; - # include # ifdef __cplusplus } # endif # endif +# ifdef __cplusplus +extern "C" { +# endif +struct _SYSTEM_INFO; +# ifdef __cplusplus +} +#endif namespace boost { @@ -142,6 +154,7 @@ namespace boost typedef unsigned long ulong_ptr; # endif typedef void* handle; + typedef _SYSTEM_INFO system_info; unsigned const infinite=~0U; unsigned const timeout=258U; handle const invalid_handle_value=(handle)(-1); @@ -156,7 +169,6 @@ namespace boost extern "C" { struct _SECURITY_ATTRIBUTES; - struct SYSTEM_INFO; # ifdef BOOST_NO_ANSI_APIS # if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA __declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*); @@ -175,9 +187,9 @@ namespace boost __declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*); # endif #if BOOST_PLAT_WINDOWS_RUNTIME - __declspec(dllimport) void __stdcall GetNativeSystemInfo(SYSTEM_INFO*); + __declspec(dllimport) void __stdcall GetNativeSystemInfo(_SYSTEM_INFO*); #else - __declspec(dllimport) void __stdcall GetSystemInfo(SYSTEM_INFO*); + __declspec(dllimport) void __stdcall GetSystemInfo(_SYSTEM_INFO*); #endif __declspec(dllimport) int __stdcall CloseHandle(void*); __declspec(dllimport) int __stdcall ReleaseMutex(void*); @@ -317,7 +329,7 @@ namespace boost BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0); } - inline void get_system_info(SYSTEM_INFO *info) + inline void get_system_info(system_info *info) { #if BOOST_PLAT_WINDOWS_RUNTIME GetNativeSystemInfo(info); @@ -339,7 +351,7 @@ namespace boost else { #if BOOST_PLAT_WINDOWS_RUNTIME - detail::win32::WaitForSingleObjectEx(detail::win32::GetCurrentThread(), milliseconds, FALSE); + detail::win32::WaitForSingleObjectEx(detail::win32::GetCurrentThread(), milliseconds, 0); #else detail::win32::Sleep(milliseconds); #endif diff --git a/src/win32/thread.cpp b/src/win32/thread.cpp index 63c1b04a..1d815f24 100644 --- a/src/win32/thread.cpp +++ b/src/win32/thread.cpp @@ -35,7 +35,6 @@ #include #if BOOST_PLAT_WINDOWS_RUNTIME -#include #include #include #include @@ -198,33 +197,15 @@ namespace boost #if BOOST_PLAT_WINDOWS_RUNTIME namespace detail { - std::once_flag threadPoolInitFlag; std::atomic_uint threadCount; - Microsoft::WRL::ComPtr threadPoolFactory; - - void init_thread_pool_func(bool *succeeded) - { - Microsoft::WRL::ComPtr factory; - const HRESULT hr = ::Windows::Foundation::GetActivationFactory( - Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_System_Threading_ThreadPool).Get(), - &factory); - if (hr != S_OK) - { - *succeeded = false; - } - else - { - factory.As(&threadPoolFactory); - *succeeded = true; - } - } - + bool win32::scoped_winrt_thread::start(thread_func address, void *parameter, unsigned int *thrdId) { - bool initSucceeded = true; - std::call_once(threadPoolInitFlag, init_thread_pool_func, &initSucceeded); - init_thread_pool_func(&initSucceeded); - if (!initSucceeded) + Microsoft::WRL::ComPtr threadPoolFactory; + HRESULT hr = ::Windows::Foundation::GetActivationFactory( + Microsoft::WRL::Wrappers::HStringReference(RuntimeClass_Windows_System_Threading_ThreadPool).Get(), + &threadPoolFactory); + if (hr != S_OK) { return false; } @@ -263,7 +244,7 @@ namespace boost // Schedule work item on the threadpool. Microsoft::WRL::ComPtr asyncAction; - const HRESULT hr = threadPoolFactory->RunWithPriorityAndOptionsAsync( + hr = threadPoolFactory->RunWithPriorityAndOptionsAsync( workItem.Get(), ABI::Windows::System::Threading::WorkItemPriority_Normal, ABI::Windows::System::Threading::WorkItemOptions_TimeSliced, @@ -366,9 +347,13 @@ namespace boost #endif } -#if !BOOST_PLAT_WINDOWS_RUNTIME bool thread::start_thread_noexcept(const attributes& attr) { +#if BOOST_PLAT_WINDOWS_RUNTIME + // Stack size isn't supported with Windows Runtime. + attr; + return start_thread_noexcept(); +#else //uintptr_t const new_thread=_beginthreadex(attr.get_security(),attr.get_stack_size(),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); uintptr_t const new_thread=_beginthreadex(0,static_cast(attr.get_stack_size()),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); if(!new_thread) @@ -380,9 +365,9 @@ namespace boost thread_info->thread_handle=(detail::win32::handle)(new_thread); ResumeThread(thread_info->thread_handle); return true; - } #endif - + } + thread::thread(detail::thread_data_ptr data): thread_info(data) {} @@ -537,8 +522,8 @@ namespace boost unsigned thread::hardware_concurrency() BOOST_NOEXCEPT { - SYSTEM_INFO info; - detail::win32::get_system_info(info); + detail::win32::system_info info; + detail::win32::get_system_info(&info); return info.dwNumberOfProcessors; } @@ -738,7 +723,7 @@ namespace boost } else { - detail::win32::sleep(milliseconds); + detail::win32::sleep(time_left.milliseconds); } if(target_time.relative) { @@ -823,7 +808,7 @@ namespace boost } else { - detail::win32::sleep(milliseconds); + detail::win32::sleep(time_left.milliseconds); } if(target_time.relative) { @@ -839,10 +824,13 @@ namespace boost { #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID #if BOOST_PLAT_WINDOWS_RUNTIME - return get_or_make_current_thread_data()->id; -#else - return detail::win32::GetCurrentThreadId(); + detail::thread_data_base* current_thread_data(detail::get_current_thread_data()); + if (current_thread_data) + { + return current_thread_data->id; + } #endif + return detail::win32::GetCurrentThreadId(); #else return thread::id(get_or_make_current_thread_data()); #endif diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e1d84a8f..bcf29d8f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -100,6 +100,7 @@ project rule thread-run ( sources ) { + sources = $(sources) winrt_init.cpp ; return [ run $(sources) ../build//boost_thread ] [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/static @@ -110,6 +111,7 @@ rule thread-run ( sources ) rule thread-test ( sources ) { + sources = $(sources) winrt_init.cpp ; return [ run $(sources) ../build//boost_thread : : : /boost/test//boost_unit_test_framework/static @@ -124,6 +126,7 @@ rule thread-test ( sources ) rule thread-run2 ( sources : name ) { + sources = $(sources) winrt_init.cpp ; return [ run $(sources) ../build//boost_thread : : : : $(name) ] @@ -135,6 +138,7 @@ rule thread-run2 ( sources : name ) rule thread-run2-noit ( sources : name ) { + sources = $(sources) winrt_init.cpp ; return [ run $(sources) ../build//boost_thread : : : : $(name) ] @@ -149,6 +153,7 @@ rule thread-run2-noit ( sources : name ) rule thread-run2-noit-pthread ( sources : name ) { + sources = $(sources) winrt_init.cpp ; return [ run $(sources) ../build//boost_thread : : : win32:no : $(name) ] @@ -163,6 +168,7 @@ rule thread-run2-noit-pthread ( sources : name ) rule thread-run2-h ( sources : name ) { + sources = $(sources) winrt_init.cpp ; return [ run $(sources) : : : /boost/system//boost_system @@ -175,6 +181,7 @@ rule thread-run2-h ( sources : name ) rule thread-run-lib2 ( sources : name ) { + sources = $(sources) winrt_init.cpp ; return [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/static : : : diff --git a/test/test_2741.cpp b/test/test_2741.cpp index 974adacd..409a51f7 100644 --- a/test/test_2741.cpp +++ b/test/test_2741.cpp @@ -5,7 +5,6 @@ #define BOOST_THREAD_VERSION 2 #include -#include #include #include @@ -61,8 +60,6 @@ void test_stack_size() } -// On Windows store thread creation with stack size not supported. -#if BOOST_PLAT_WINDOWS_DESKTOP void do_test_creation_with_attrs() { test_value = 0; @@ -77,7 +74,6 @@ void test_creation_with_attrs() { timed_test(&do_test_creation_with_attrs, 1); } -#endif boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) { @@ -85,10 +81,7 @@ boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) test->add(BOOST_TEST_CASE(test_native_handle)); test->add(BOOST_TEST_CASE(test_stack_size)); - -#if BOOST_PLAT_WINDOWS_DESKTOP test->add(BOOST_TEST_CASE(test_creation_with_attrs)); -#endif return test; } diff --git a/test/winrt_init.cpp b/test/winrt_init.cpp new file mode 100644 index 00000000..99edd8b5 --- /dev/null +++ b/test/winrt_init.cpp @@ -0,0 +1,17 @@ +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +#if BOOST_PLAT_WINDOWS_RUNTIME + +#include +#pragma comment(lib, "runtimeobject.lib") + +// Necessary for the tests which to keep the Windows Runtime active, +// when running in an actual Windows store/phone application initialization +// is handled automatically by the CRT. +// This is easier than calling in the main function for each test case. +Microsoft::WRL::Wrappers::RoInitializeWrapper runtime(RO_INIT_MULTITHREADED); + +#endif