From 9ceea9822fb7b0145c7077c7fabdac73af2d95a6 Mon Sep 17 00:00:00 2001 From: Steve Gates Date: Wed, 11 Dec 2013 15:04:39 -0800 Subject: [PATCH] Enabling Boost.Thread to be used in the Windows Runtime. This involves basically 3 changes: 1. Using __declspec(thread) instead of the Tls APIs. 2. Using Windows::System::Threading since Win32 Threading APIs aren't allowed. 3. Updating or replacing some banned APIs like WaitForSingleObject with WaitForSingleObjectEx. --- include/boost/thread/detail/thread.hpp | 16 +- .../boost/thread/win32/basic_timed_mutex.hpp | 13 + .../boost/thread/win32/condition_variable.hpp | 16 +- include/boost/thread/win32/once.hpp | 119 ++++++++- include/boost/thread/win32/shared_mutex.hpp | 27 ++ include/boost/thread/win32/thread_data.hpp | 32 ++- .../boost/thread/win32/thread_primitives.hpp | 106 ++++++-- src/win32/gettickcount64.cpp | 11 + src/win32/thread.cpp | 239 +++++++++++++++--- test/Jamfile.v2 | 44 ++-- test/test_2741.cpp | 14 +- test/test_tss.cpp | 28 +- 12 files changed, 565 insertions(+), 100 deletions(-) diff --git a/include/boost/thread/detail/thread.hpp b/include/boost/thread/detail/thread.hpp index 520ca267..8cfb92b1 100644 --- a/include/boost/thread/detail/thread.hpp +++ b/include/boost/thread/detail/thread.hpp @@ -1,12 +1,14 @@ +// (C) Copyright 2007-2010 Anthony Williams +// (C) Copyright 20011-2012 Vicente J. Botet Escriba +// (C) Copyright 2014 Microsoft Corporation +// 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) #ifndef BOOST_THREAD_THREAD_COMMON_HPP #define BOOST_THREAD_THREAD_COMMON_HPP -// 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) -// (C) Copyright 2007-2010 Anthony Williams -// (C) Copyright 2011-2012 Vicente J. Botet Escriba #include +#include #include #ifndef BOOST_NO_IOSTREAM @@ -171,7 +173,9 @@ namespace boost private: bool start_thread_noexcept(); +#if !BOOST_PLAT_WINDOWS_RUNTIME bool start_thread_noexcept(const attributes& attr); +#endif //public: void start_thread() { @@ -180,6 +184,7 @@ namespace boost boost::throw_exception(thread_resource_error()); } } +#if !BOOST_PLAT_WINDOWS_RUNTIME void start_thread(const attributes& attr) { if (!start_thread_noexcept(attr)) @@ -187,6 +192,7 @@ namespace boost boost::throw_exception(thread_resource_error()); } } +#endif explicit thread(detail::thread_data_ptr data); diff --git a/include/boost/thread/win32/basic_timed_mutex.hpp b/include/boost/thread/win32/basic_timed_mutex.hpp index 01db0336..7f599c99 100644 --- a/include/boost/thread/win32/basic_timed_mutex.hpp +++ b/include/boost/thread/win32/basic_timed_mutex.hpp @@ -5,6 +5,7 @@ // // (C) Copyright 2006-8 Anthony Williams // (C) Copyright 2011-2012 Vicente J. Botet Escriba +// (C) Copyright 2014 Microsoft Corporation // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -81,7 +82,11 @@ namespace boost do { +#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP unsigned const retval(win32::WaitForSingleObject(sem, ::boost::detail::win32::infinite)); +#else + unsigned const retval(win32::WaitForSingleObjectEx(sem, ::boost::detail::win32::infinite,0)); +#endif BOOST_VERIFY(0 == retval || ::boost::detail::win32::wait_abandoned == retval); // BOOST_VERIFY(win32::WaitForSingleObject( // sem,::boost::detail::win32::infinite)==0); @@ -142,7 +147,11 @@ namespace boost do { +#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0) +#else + if(win32::WaitForSingleObjectEx(sem,::boost::detail::get_milliseconds_until(wait_until),0)!=0) +#endif { BOOST_INTERLOCKED_DECREMENT(&active_count); return false; @@ -205,7 +214,11 @@ namespace boost { chrono::milliseconds rel_time= chrono::ceil(tp-chrono::system_clock::now()); +#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP if(win32::WaitForSingleObject(sem,static_cast(rel_time.count()))!=0) +#else + if(win32::WaitForSingleObjectEx(sem,static_cast(rel_time.count()),0)!=0) +#endif { BOOST_INTERLOCKED_DECREMENT(&active_count); return false; diff --git a/include/boost/thread/win32/condition_variable.hpp b/include/boost/thread/win32/condition_variable.hpp index 57aaf8c5..a1d58f4a 100644 --- a/include/boost/thread/win32/condition_variable.hpp +++ b/include/boost/thread/win32/condition_variable.hpp @@ -1,10 +1,12 @@ #ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP #define BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP -// 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) -// (C) Copyright 2007-8 Anthony Williams -// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// (C) Copyright 2014 Microsoft Corporation +// 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 #include @@ -96,7 +98,11 @@ namespace boost bool woken() { +#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP unsigned long const woken_result=detail::win32::WaitForSingleObject(wake_sem,0); +#else + unsigned long const woken_result=detail::win32::WaitForSingleObjectEx(wake_sem,0,0); +#endif BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0)); return woken_result==0; } diff --git a/include/boost/thread/win32/once.hpp b/include/boost/thread/win32/once.hpp index cafcfd44..e8ee6940 100644 --- a/include/boost/thread/win32/once.hpp +++ b/include/boost/thread/win32/once.hpp @@ -6,6 +6,7 @@ // (C) Copyright 2005-7 Anthony Williams // (C) Copyright 2005 John Maddock // (C) Copyright 2011-2013 Vicente J. Botet Escriba +// (C) Copyright 2014 Microsoft Corporation // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -152,14 +153,27 @@ namespace boost { name_once_mutex(mutex_name,flag_address); } -#ifdef BOOST_NO_ANSI_APIS - return ::boost::detail::win32::CreateEventW( -#else +#if !defined(BOOST_NO_ANSI_APIS) return ::boost::detail::win32::CreateEventA( -#endif - 0,::boost::detail::win32::manual_reset_event, + 0, + ::boost::detail::win32::manual_reset_event, ::boost::detail::win32::event_initially_reset, mutex_name); +#else +#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA + return ::boost::detail::win32::CreateEventW( + 0, + ::boost::detail::win32::manual_reset_event, + ::boost::detail::win32::event_initially_reset, + mutex_name); +#else + return ::boost::detail::win32::CreateEventExW( + 0, + mutex_name, + ::boost::detail::win32::create_event_manual_reset, + ::boost::detail::win32::event_all_access); +#endif +#endif } struct once_context { @@ -267,8 +281,13 @@ 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 } } //#endif @@ -311,8 +330,13 @@ 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 @@ -358,8 +382,13 @@ 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 } } #else @@ -403,8 +432,13 @@ 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 @@ -446,8 +480,13 @@ 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 @@ -489,8 +528,13 @@ 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 @@ -532,8 +576,13 @@ 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 } } #elif defined BOOST_NO_CXX11_RVALUE_REFERENCES @@ -577,8 +626,13 @@ 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 @@ -620,8 +674,13 @@ 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 @@ -663,8 +722,13 @@ 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 @@ -706,8 +770,13 @@ 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 } } #endif @@ -751,8 +820,13 @@ 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 @@ -796,8 +870,13 @@ 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 @@ -842,8 +921,13 @@ 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 @@ -889,8 +973,13 @@ 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 } } #endif @@ -933,8 +1022,13 @@ 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 } } @@ -980,8 +1074,13 @@ 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 @@ -1027,8 +1126,13 @@ 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 @@ -1076,8 +1180,13 @@ 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 } } diff --git a/include/boost/thread/win32/shared_mutex.hpp b/include/boost/thread/win32/shared_mutex.hpp index 252174f6..26d28054 100644 --- a/include/boost/thread/win32/shared_mutex.hpp +++ b/include/boost/thread/win32/shared_mutex.hpp @@ -3,6 +3,7 @@ // (C) Copyright 2006-8 Anthony Williams // (C) Copyright 2011-2012 Vicente J. Botet Escriba +// (C) Copyright 2014 Microsoft Corporation // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -184,7 +185,11 @@ namespace boost return true; } +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP unsigned long const res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until)); +# else + unsigned long const res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until), 0); +# endif if(res==detail::win32::timeout) { for(;;) @@ -289,8 +294,13 @@ namespace boost unsigned long res; if (tp>n) { chrono::milliseconds rel_time= chrono::ceil(tp-n); +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP res=detail::win32::WaitForSingleObject(semaphores[unlock_sem], static_cast(rel_time.count())); +# else + res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem], + static_cast(rel_time.count()), 0); +# endif } else { res=detail::win32::timeout; } @@ -466,7 +476,11 @@ namespace boost #else const bool wait_all = false; #endif +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WS03 unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until)); +# else + unsigned long const wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until), 0); +# endif if(wait_res==detail::win32::timeout) { for(;;) @@ -578,8 +592,13 @@ namespace boost unsigned long wait_res; if (tp>n) { chrono::milliseconds rel_time= chrono::ceil(tp-chrono::system_clock::now()); +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WS03 wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all, static_cast(rel_time.count())); +# else + wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all, + static_cast(rel_time.count()), 0); +# endif } else { wait_res=detail::win32::timeout; } @@ -690,7 +709,11 @@ namespace boost return; } +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite)); +# else + BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],detail::win32::infinite, 0)); +# endif } } @@ -779,7 +802,11 @@ namespace boost { if(!last_reader) { +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP BOOST_VERIFY(!detail::win32::WaitForSingleObject(upgrade_sem,detail::win32::infinite)); +# else + BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite, 0)); +# endif } break; } diff --git a/include/boost/thread/win32/thread_data.hpp b/include/boost/thread/win32/thread_data.hpp index c0894311..8b8ac209 100644 --- a/include/boost/thread/win32/thread_data.hpp +++ b/include/boost/thread/win32/thread_data.hpp @@ -1,10 +1,12 @@ +// (C) Copyright 2008 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// (C) Copyright 2014 Microsoft Corporation +// 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) + #ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP #define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP -// 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) -// (C) Copyright 2008 Anthony Williams -// (C) Copyright 2011-2012 Vicente J. Botet Escriba #include #include @@ -12,6 +14,8 @@ #include #include +#include + #include #ifdef BOOST_THREAD_USES_CHRONO #include @@ -94,7 +98,15 @@ namespace boost struct BOOST_THREAD_DECL thread_data_base { long count; + + // Win32 threading APIs are not available in store apps so + // use abstraction on top of Windows::System::Threading. +#if BOOST_PLAT_WINDOWS_RUNTIME + detail::win32::scoped_winrt_thread thread_handle; +#else detail::win32::handle_manager thread_handle; +#endif + boost::detail::thread_exit_callback_node* thread_exit_callbacks; std::map tss_data; unsigned id; @@ -114,9 +126,15 @@ namespace boost //#endif thread_data_base(): - count(0),thread_handle(detail::win32::invalid_handle_value), - thread_exit_callbacks(0),tss_data(), + count(0), +#if BOOST_PLAT_WINDOWS_RUNTIME + thread_handle(), +#else + thread_handle(detail::win32::invalid_handle_value), +#endif id(0), + thread_exit_callbacks(0), + tss_data(), notify(), async_states_() //#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS diff --git a/include/boost/thread/win32/thread_primitives.hpp b/include/boost/thread/win32/thread_primitives.hpp index e991a157..761fa1cc 100644 --- a/include/boost/thread/win32/thread_primitives.hpp +++ b/include/boost/thread/win32/thread_primitives.hpp @@ -5,12 +5,14 @@ // // (C) Copyright 2005-7 Anthony Williams // (C) Copyright 2007 David Deakins +// (C) Copyright 2014 Microsoft Corporation // // 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 +#include #include #include #include @@ -46,13 +48,22 @@ namespace boost unsigned const event_modify_state=EVENT_MODIFY_STATE; unsigned const synchronize=SYNCHRONIZE; unsigned const wait_abandoned=WAIT_ABANDONED; - + unsigned const create_event_initial_set = CREATE_EVENT_INITIAL_SET; + 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 using ::CreateMutexW; using ::CreateEventW; - using ::OpenEventW; using ::CreateSemaphoreW; +# else + using ::CreateMutexExW; + using ::CreateEventExW; + using ::CreateSemaphoreExW; +# endif + using ::OpenEventW; # else using ::CreateMutexA; using ::CreateEventA; @@ -64,15 +75,22 @@ namespace boost using ::ReleaseSemaphore; using ::SetEvent; using ::ResetEvent; +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP using ::WaitForMultipleObjects; using ::WaitForSingleObject; +# else + using ::WaitForMultipleObjectsEx; + using ::WaitForSingleObjectEx; +# endif using ::GetCurrentProcessId; using ::GetCurrentThreadId; using ::GetCurrentThread; using ::GetCurrentProcess; using ::DuplicateHandle; +#if !BOOST_PLAT_WINDOWS_RUNTIME using ::SleepEx; using ::Sleep; +#endif using ::QueueUserAPC; // using ::GetTickCount; //#ifdef BOOST_THREAD_WIN32_HAS_GET_TICK_COUNT_64 @@ -131,14 +149,24 @@ namespace boost unsigned const event_modify_state=2; unsigned const synchronize=0x100000u; unsigned const wait_abandoned=0x00000080u; + unsigned const create_event_initial_set = 0x00000002; + unsigned const create_event_manual_reset = 0x00000001; + unsigned const event_all_access = 0x1F0003; + unsigned const semaphore_all_access = 0x1F0003; extern "C" { struct _SECURITY_ATTRIBUTES; # 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*); __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*); __declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*); +# else + __declspec(dllimport) void* __stdcall CreateMutexExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long); + __declspec(dllimport) void* __stdcall CreateEventExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long); + __declspec(dllimport) void* __stdcall CreateSemaphoreExW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*,unsigned long,unsigned long); +# endif __declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*); # else __declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*); @@ -148,12 +176,19 @@ namespace boost # endif __declspec(dllimport) int __stdcall CloseHandle(void*); __declspec(dllimport) int __stdcall ReleaseMutex(void*); +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*,unsigned long); __declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds); +# else + __declspec(dllimport) unsigned long __stdcall WaitForSingleObjectEx(void*,unsigned long,int); + __declspec(dllimport) unsigned long __stdcall WaitForMultipleObjectsEx(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds,int bAlertable); +# endif __declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*); __declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long); +#if !BOOST_PLAT_WINDOWS_RUNTIME __declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int); __declspec(dllimport) void __stdcall Sleep(unsigned long); +#endif typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr); __declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr); @@ -211,8 +246,16 @@ namespace boost { #if !defined(BOOST_NO_ANSI_APIS) handle const res=win32::CreateEventA(0,type,state,0); -#else +#else +#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA handle const res=win32::CreateEventW(0,type,state,0); +#else + handle const res=win32::CreateEventExW( + 0, + 0, + type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0, + event_all_access); +#endif #endif if(!res) { @@ -221,26 +264,27 @@ namespace boost return res; } - inline handle create_anonymous_semaphore(long initial_count,long max_count) - { -#if !defined(BOOST_NO_ANSI_APIS) - handle const res=CreateSemaphoreA(0,initial_count,max_count,0); -#else - handle const res=CreateSemaphoreW(0,initial_count,max_count,0); -#endif - if(!res) - { - boost::throw_exception(thread_resource_error()); - } - return res; - } inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count) { #if !defined(BOOST_NO_ANSI_APIS) handle const res=CreateSemaphoreA(0,initial_count,max_count,0); #else - handle const res=CreateSemaphoreW(0,initial_count,max_count,0); +#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA + handle const res=CreateSemaphoreEx(0,initial_count,max_count,0,0); +#else + handle const res=CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access); #endif +#endif + return res; + } + + inline handle create_anonymous_semaphore(long initial_count,long max_count) + { + handle const res=create_anonymous_semaphore_nothrow(initial_count,max_count); + if(!res) + { + boost::throw_exception(thread_resource_error()); + } return res; } @@ -261,7 +305,34 @@ namespace boost { BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0); } +#if BOOST_PLAT_WINDOWS_RUNTIME + class BOOST_THREAD_DECL scoped_winrt_thread + { + public: + scoped_winrt_thread() : m_completionHandle(invalid_handle_value) + {} + ~scoped_winrt_thread() + { + if (m_completionHandle != detail::win32::invalid_handle_value) + { + CloseHandle(m_completionHandle); + } + } + + typedef unsigned(__stdcall * thread_func)(void *); + bool start(thread_func address, void *parameter, unsigned int *thrdId); + + handle waitable_handle() const + { + BOOST_ASSERT(m_completionHandle != detail::win32::invalid_handle_value); + return m_completionHandle; + } + + private: + handle m_completionHandle; + }; +#endif class BOOST_THREAD_DECL handle_manager { private: @@ -324,7 +395,6 @@ namespace boost cleanup(); } }; - } } } diff --git a/src/win32/gettickcount64.cpp b/src/win32/gettickcount64.cpp index 92a999b0..80859ea1 100644 --- a/src/win32/gettickcount64.cpp +++ b/src/win32/gettickcount64.cpp @@ -6,14 +6,19 @@ #include #include +#include #ifdef BOOST_USE_WINDOWS_H #include #else extern "C" { +#if BOOST_PLAT_WINDOWS_RUNTIME + __declspec(dllimport) unsigned long long __stdcall GetTickCount64(); +#else __declspec(dllimport) boost::detail::win32::gettickcount32fn __stdcall GetProcAddress(void *, const char *); __declspec(dllimport) void * __stdcall GetModuleHandleW(const wchar_t *); +#endif } #endif @@ -23,6 +28,7 @@ namespace boost { namespace win32 { +#if !BOOST_PLAT_WINDOWS_RUNTIME namespace { gettickcount64fn gettickcount64 = NULL; @@ -37,11 +43,16 @@ namespace boost ::GetModuleHandleW(L"Kernel32.dll"), "GetTickCount")); } } +#endif ticks_type GetTickCount64() { +#if BOOST_PLAT_WINDOWS_RUNTIME + return ::GetTickCount64(); +#else ::boost::call_once(&init_gettickcount64, initfnonce); return gettickcount64 ? gettickcount64() : static_cast (gettickcount32()); +#endif } } } diff --git a/src/win32/thread.cpp b/src/win32/thread.cpp index f73b404d..cc864974 100644 --- a/src/win32/thread.cpp +++ b/src/win32/thread.cpp @@ -1,9 +1,10 @@ -// 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) -// (C) Copyright 2007 Anthony Williams -// (C) Copyright 2007 David Deakins -// (C) Copyright 2011-2013 Vicente J. Botet Escriba +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007 David Deakins +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// (C) Copyright 2014 Microsoft Corporation +// 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) #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x400 @@ -20,7 +21,6 @@ #include #include #include - #include #include #if defined BOOST_THREAD_USES_DATETIME @@ -33,6 +33,20 @@ #endif #include #include +#include + +#if BOOST_PLAT_WINDOWS_RUNTIME +#include +#include +#include +#include +#include +#include +#include +#include +#include +#pragma comment(lib, "runtimeobject.lib") +#endif namespace boost { @@ -65,50 +79,67 @@ namespace boost // Windows CE does not define the TLS_OUT_OF_INDEXES constant. #define TLS_OUT_OF_INDEXES 0xFFFFFFFF #endif +#if !BOOST_PLAT_WINDOWS_RUNTIME DWORD current_thread_tls_key=TLS_OUT_OF_INDEXES; +#else + __declspec(thread) boost::detail::thread_data_base* current_thread_data_base; +#endif void create_current_thread_tls_key() { tss_cleanup_implemented(); // if anyone uses TSS, we need the cleanup linked in +#if !BOOST_PLAT_WINDOWS_RUNTIME current_thread_tls_key=TlsAlloc(); BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES); +#endif } void cleanup_tls_key() { +#if !BOOST_PLAT_WINDOWS_RUNTIME if(current_thread_tls_key!=TLS_OUT_OF_INDEXES) { TlsFree(current_thread_tls_key); current_thread_tls_key=TLS_OUT_OF_INDEXES; } +#endif } void set_current_thread_data(detail::thread_data_base* new_data) { boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key); - if (current_thread_tls_key!=TLS_OUT_OF_INDEXES) +#if BOOST_PLAT_WINDOWS_RUNTIME + current_thread_data_base = new_data; +#else + if (current_thread_tls_key != TLS_OUT_OF_INDEXES) { - BOOST_VERIFY(TlsSetValue(current_thread_tls_key,new_data)); + BOOST_VERIFY(TlsSetValue(current_thread_tls_key, new_data)); } else { BOOST_VERIFY(false); //boost::throw_exception(thread_resource_error()); } +#endif } - } + namespace detail { thread_data_base* get_current_thread_data() { - if(current_thread_tls_key==TLS_OUT_OF_INDEXES) +#if BOOST_PLAT_WINDOWS_RUNTIME + return current_thread_data_base; +#else + if (current_thread_tls_key == TLS_OUT_OF_INDEXES) { return 0; } return (detail::thread_data_base*)TlsGetValue(current_thread_tls_key); +#endif } } + namespace { #ifndef BOOST_HAS_THREADEX @@ -165,6 +196,84 @@ 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) + { + return false; + } + + // Create event for tracking work item completion. + *thrdId = ++threadCount; + handle completionHandle = CreateEventExW(NULL, NULL, 0, EVENT_ALL_ACCESS); + if (!completionHandle) + { + return false; + } + m_completionHandle = completionHandle; + + // Create new work item. + Microsoft::WRL::ComPtr workItem = + Microsoft::WRL::Callback, ABI::Windows::System::Threading::IWorkItemHandler, Microsoft::WRL::FtmBase>> + ([address, parameter, completionHandle](ABI::Windows::Foundation::IAsyncAction *) + { + // Add a reference since we need to access the completionHandle after the thread_start_function. + // This is to handle cases where detach() was called and run_thread_exit_callbacks() would end + // up closing the handle. + detail::thread_data_base* const thread_info(reinterpret_cast(parameter)); + intrusive_ptr_add_ref(thread_info); + + __try + { + address(parameter); + } + __finally + { + SetEvent(completionHandle); + intrusive_ptr_release(thread_info); + } + return S_OK; + }); + + // Schedule work item on the threadpool. + Microsoft::WRL::ComPtr asyncAction; + const HRESULT hr = threadPoolFactory->RunWithPriorityAndOptionsAsync( + workItem.Get(), + ABI::Windows::System::Threading::WorkItemPriority_Normal, + ABI::Windows::System::Threading::WorkItemOptions_TimeSliced, + &asyncAction); + return hr == S_OK; + } + } +#endif + namespace { void run_thread_exit_callbacks() @@ -199,7 +308,6 @@ namespace boost current_thread_data->tss_data.erase(current); } } - set_current_thread_data(0); } } @@ -236,6 +344,16 @@ namespace boost bool thread::start_thread_noexcept() { +#if BOOST_PLAT_WINDOWS_RUNTIME + intrusive_ptr_add_ref(thread_info.get()); + if (!thread_info->thread_handle.start(&thread_start_function, thread_info.get(), &thread_info->id)) + { + intrusive_ptr_release(thread_info.get()); +// boost::throw_exception(thread_resource_error()); + return false; + } + return true; +#else uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); if(!new_thread) { @@ -246,8 +364,10 @@ namespace boost thread_info->thread_handle=(detail::win32::handle)(new_thread); ResumeThread(thread_info->thread_handle); return true; +#endif } - + +#if !BOOST_PLAT_WINDOWS_RUNTIME bool thread::start_thread_noexcept(const attributes& attr) { //uintptr_t const new_thread=_beginthreadex(attr.get_security(),attr.get_stack_size(),&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id); @@ -262,6 +382,7 @@ namespace boost ResumeThread(thread_info->thread_handle); return true; } +#endif thread::thread(detail::thread_data_ptr data): thread_info(data) @@ -321,31 +442,37 @@ namespace boost } return current_thread_data; } - } thread::id thread::get_id() const BOOST_NOEXCEPT { - #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID - detail::thread_data_ptr local_thread_info=(get_thread_info)(); - return local_thread_info?local_thread_info->id:0; - //return const_cast(this)->native_handle(); - #else +#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID + detail::thread_data_ptr local_thread_info=(get_thread_info)(); + if(!local_thread_info) + { + return 0; + } + return local_thread_info->id; +#else return thread::id((get_thread_info)()); - #endif +#endif } bool thread::joinable() const BOOST_NOEXCEPT { - return (get_thread_info)() ? true : false; + detail::thread_data_ptr local_thread_info = (get_thread_info)(); + if(!local_thread_info) + { + return false; + } + return true; } bool thread::join_noexcept() { - detail::thread_data_ptr local_thread_info=(get_thread_info)(); if(local_thread_info) { - this_thread::interruptible_wait(local_thread_info->thread_handle,detail::timeout::sentinel()); + this_thread::interruptible_wait(this->native_handle(),detail::timeout::sentinel()); release_handle(); return true; } @@ -366,7 +493,7 @@ namespace boost detail::thread_data_ptr local_thread_info=(get_thread_info)(); if(local_thread_info) { - if(!this_thread::interruptible_wait(local_thread_info->thread_handle,milli)) + if(!this_thread::interruptible_wait(this->native_handle(),milli)) { res=false; return true; @@ -404,7 +531,11 @@ namespace boost bool thread::interruption_requested() const BOOST_NOEXCEPT { detail::thread_data_ptr local_thread_info=(get_thread_info)(); +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->interruption_handle,0)==0); +# else + return local_thread_info.get() && (detail::win32::WaitForSingleObjectEx(local_thread_info->interruption_handle,0,0)==0); +# endif } #endif @@ -413,12 +544,19 @@ namespace boost { //SYSTEM_INFO info={{0}}; SYSTEM_INFO info; +# if BOOST_PLAT_WINDOWS_RUNTIME + GetNativeSystemInfo(&info); +# else GetSystemInfo(&info); +# endif return info.dwNumberOfProcessors; } unsigned thread::physical_concurrency() BOOST_NOEXCEPT { +#if BOOST_PLAT_WINDOWS_RUNTIME + return hardware_concurrency(); +#else unsigned cores = 0; #if !(defined(__MINGW32__) || defined (__MINGW64__)) DWORD size = 0; @@ -439,12 +577,22 @@ namespace boost } #endif return cores; +#endif } thread::native_handle_type thread::native_handle() { detail::thread_data_ptr local_thread_info=(get_thread_info)(); - return local_thread_info?(detail::win32::handle)local_thread_info->thread_handle:detail::win32::invalid_handle_value; + if(!local_thread_info) + { + return detail::win32::invalid_handle_value; + } +#if BOOST_PLAT_WINDOWS_RUNTIME + // There is no 'real' Win32 handle so we return a handle that at least can be waited on. + return local_thread_info->thread_handle.waitable_handle(); +#else + return (detail::win32::handle)local_thread_info->thread_handle; +#endif } detail::thread_data_ptr thread::get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const @@ -535,6 +683,7 @@ namespace boost detail::win32::handle_manager timer_handle; #ifndef UNDER_CE +#if !BOOST_PLAT_WINDOWS_RUNTIME unsigned const min_timer_wait_period=20; if(!target_time.is_sentinel()) @@ -562,6 +711,7 @@ namespace boost target_time=detail::timeout(time_left.milliseconds); } } +#endif #endif bool const using_timer=timeout_index!=~0u; @@ -576,7 +726,11 @@ namespace boost if(handle_count) { +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds); +# else + unsigned long const notified_index=detail::win32::WaitForMultipleObjectsEx(handle_count,handles,false,using_timer?INFINITE:time_left.milliseconds, 0); +# endif if(notified_indexid; +#else + return detail::win32::GetCurrentThreadId(); +#endif +#else return thread::id(get_or_make_current_thread_data()); - #endif +#endif } #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS @@ -719,13 +891,21 @@ namespace boost bool interruption_requested() BOOST_NOEXCEPT { +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WINXP return detail::get_current_thread_data() && (detail::win32::WaitForSingleObject(detail::get_current_thread_data()->interruption_handle,0)==0); +# else + return detail::get_current_thread_data() && (detail::win32::WaitForSingleObjectEx(detail::get_current_thread_data()->interruption_handle,0,0)==0); +# endif } #endif void yield() BOOST_NOEXCEPT { +#if BOOST_PLAT_WINDOWS_RUNTIME + std::this_thread::yield(); +#else detail::win32::Sleep(0); +#endif } #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS @@ -839,6 +1019,7 @@ namespace boost } } } + BOOST_THREAD_DECL void __cdecl on_process_enter() {} diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c0170b4a..999ead49 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -95,9 +95,7 @@ project intel:-wd193,304,383,444 intel:-wd593,981 intel:-wd1418 - intel:-wd2415 - - + intel:-wd2415 ; rule thread-run ( sources ) @@ -430,10 +428,10 @@ rule thread-compile ( sources : reqs * : name ) [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/duration_pass.cpp : unique_lock__cons__duration_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_assign_pass.cpp : unique_lock__cons__move_assign_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_pass.cpp : unique_lock__cons__move_ctor_p ] - [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_p ] - [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_try_p ] - [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_for_p ] - [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp : unique_lock__cons__move_ctor_upgrade_lock_until_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_pass.cpp : uq_lk_cons_mv_c_upg_lk_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_try_pass.cpp : uq_lk_cons_mv_c_upg_lk_t_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_for_pass.cpp : uq_lk_cons_mv_c_upg_lk_f_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_upgrade_lock_until_pass.cpp : uq_lk_cons_mv_c_upg_lk_u_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/mutex_pass.cpp : unique_lock__cons__mutex_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/time_point_pass.cpp : unique_lock__cons__time_point_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/try_to_lock_pass.cpp : unique_lock__cons__try_to_lock_p ] @@ -477,8 +475,8 @@ rule thread-compile ( sources : reqs * : name ) [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/duration_pass.cpp : shared_lock__cons__duration_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_assign_pass.cpp : shared_lock__cons__move_assign_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_pass.cpp : shared_lock__cons__move_ctor_p ] - [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp : shared_lock__cons__move_ctor_unique_lock_p ] - [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp : shared_lock__cons__move_ctor_upgrade_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_unique_lock_pass.cpp : sh_lock_cons_move_ctor_unq_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/move_ctor_upgrade_lock_pass.cpp : sh_lock_cons_move_ctor_upg_lock_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/mutex_pass.cpp : shared_lock__cons__mutex_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/time_point_pass.cpp : shared_lock__cons__time_point_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/shared_lock/cons/try_to_lock_pass.cpp : shared_lock__cons__try_to_lock_p ] @@ -511,7 +509,7 @@ rule thread-compile ( sources : reqs * : name ) [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/duration_pass.cpp : upgrade_lock__cons__duration_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_assign_pass.cpp : upgrade_lock__cons__move_assign_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_pass.cpp : upgrade_lock__cons__move_ctor_p ] - [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp : upgrade_lock__cons__move_ctor_unique_lock_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_unique_lock_pass.cpp : upg_lock_cons_mv_ctor_uq_lock_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/mutex_pass.cpp : upgrade_lock__cons__mutex_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/time_point_pass.cpp : upgrade_lock__cons__time_point_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/try_to_lock_pass.cpp : upgrade_lock__cons__try_to_lock_p ] @@ -543,8 +541,8 @@ rule thread-compile ( sources : reqs * : name ) #explicit ts_nested_strict_lock ; test-suite ts_nested_strict_lock : - [ thread-compile-fail ./sync/mutual_exclusion/locks/nested_strict_lock/copy_assign_fail.cpp : : nested_strict_lock__cons__copy_assign_f ] - [ thread-compile-fail ./sync/mutual_exclusion/locks/nested_strict_lock/copy_ctor_fail.cpp : : nested_strict_lock__cons__copy_ctor_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/nested_strict_lock/copy_assign_fail.cpp : : nested_strict_lock_cons_copy_assign_f ] + [ thread-compile-fail ./sync/mutual_exclusion/locks/nested_strict_lock/copy_ctor_fail.cpp : : nested_strict_lock_cons_copy_ctor_f ] [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/default_pass.cpp : nested_strict_lock__cons__default_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/owns_lock_pass.cpp : nested_strict_lock__owns_lock_p ] [ thread-run2-noit ./sync/mutual_exclusion/locks/nested_strict_lock/types_pass.cpp : nested_strict_lock__types_p ] @@ -590,10 +588,10 @@ rule thread-compile ( sources : reqs * : name ) [ thread-compile-fail ./sync/mutual_exclusion/recursive_timed_mutex/copy_fail.cpp : : recursive_timed_mutex__copy_f ] [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/default_pass.cpp : recursive_timed_mutex__default_p ] [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/lock_pass.cpp : recursive_timed_mutex__lock_p ] - [ thread-run2-noit-pthread ./sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp : recursive_timed_mutex__native_handle_p ] - [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp : recursive_timed_mutex__try_lock_for_p ] + [ thread-run2-noit-pthread ./sync/mutual_exclusion/recursive_timed_mutex/native_handle_pass.cpp : rec_timed_mutex_native_handle_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_for_pass.cpp : rec_timed_mutex_try_lock_for_p ] [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_pass.cpp : recursive_timed_mutex__try_lock_p ] - [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp : recursive_timed_mutex__try_lock_until_p ] + [ thread-run2-noit ./sync/mutual_exclusion/recursive_timed_mutex/try_lock_until_pass.cpp : rec_timed_mutex_try_lock_until_p ] ; #explicit ts_timed_mutex ; @@ -643,8 +641,8 @@ rule thread-compile ( sources : reqs * : name ) test-suite ts_sync_bounded_queue : - [ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp : sync_bounded_queue__single_thread_p ] - [ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp : sync_bounded_queue__multi_thread_p ] + [ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/single_thread_pass.cpp : sync_bounded_q_single_thread_p ] + [ thread-run2-noit ./sync/mutual_exclusion/sync_bounded_queue/multi_thread_pass.cpp : sync_bounded_q_multi_thread_p ] ; #explicit ts_this_thread ; @@ -735,13 +733,13 @@ rule thread-compile ( sources : reqs * : name ) #explicit ts_shared_upwards ; test-suite ts_shared_upwards : - [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp : unique_lock__cons__move_ctor_shared_lock_try_p ] - [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp : unique_lock__cons__move_ctor_shared_lock_for_p ] - [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp : unique_lock__cons__move_ctor_shared_lock_until_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_try_pass.cpp : uq_lock_cons_mv_ctor_sh_lock_try_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_for_pass.cpp : uq_lock_cons_mv_ctor_sh_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/unique_lock/cons/move_ctor_shared_lock_until_pass.cpp : uq_lock_cons_mv_ctor_sh_lock_until_p ] - [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp : upgrade_lock__cons__move_ctor_shared_lock_try_p ] - [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp : upgrade_lock__cons__move_ctor_shared_lock_for_p ] - [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp : upgrade_lock__cons__move_ctor_shared_lock_until_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_try_pass.cpp : upg_lock_cons_move_ctor_sh_lock_try_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_for_pass.cpp : upg_lock_cons_move_ctor_sh_lock_for_p ] + [ thread-run2-noit ./sync/mutual_exclusion/locks/upgrade_lock/cons/move_ctor_shared_lock_until_pass.cpp : upg_lock_cons_move_ctor_sh_lock_untl_p ] ; diff --git a/test/test_2741.cpp b/test/test_2741.cpp index ecc87920..2c199139 100644 --- a/test/test_2741.cpp +++ b/test/test_2741.cpp @@ -1,11 +1,12 @@ -// Copyright (C) 2008 Vicente J. Botet Escriba -// +// Copyright (C) 2008 Vicente J. Botet Escriba +// Copyright (C) 2014 Microsoft Corporation // 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) #define BOOST_THREAD_VERSION 2 #include +#include #include #include @@ -60,6 +61,9 @@ void test_stack_size() BOOST_CHECK(attrs.get_stack_size() >= 0x4000); } + +// On Windows store thread creation with stack size not supported. +#if BOOST_PLAT_WINDOWS_DESKTOP void do_test_creation_with_attrs() { test_value = 0; @@ -74,6 +78,7 @@ 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*[]) { @@ -81,9 +86,10 @@ 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/test_tss.cpp b/test/test_tss.cpp index bd5381ed..c4a35f4f 100644 --- a/test/test_tss.cpp +++ b/test/test_tss.cpp @@ -1,7 +1,6 @@ -// Copyright (C) 2001-2003 -// William E. Kempf -// Copyright (C) 2007 Anthony Williams -// +// Copyright (C) 2001-2003 William E. Kempf +// Copyright (C) 2007 Anthony Williams +// Copyright (C) 2014 Microsoft Corporation // 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) @@ -9,6 +8,7 @@ #define BOOST_THREAD_PROVIDES_INTERRUPTIONS #include +#include #include #include @@ -67,6 +67,25 @@ void test_tss_thread() } #if defined(BOOST_THREAD_PLATFORM_WIN32) +#if BOOST_PLAT_WINDOWS_RUNTIME + typedef std::shared_ptr native_thread_t; + + void test_tss_thread_native() + { + test_tss_thread(); + } + + native_thread_t create_native_thread() + { + return std::make_shared(test_tss_thread_native); + } + + void join_native_thread(native_thread_t thread) + { + thread->join(); + } + +#else typedef HANDLE native_thread_t; DWORD WINAPI test_tss_thread_native(LPVOID /*lpParameter*/) @@ -97,6 +116,7 @@ void test_tss_thread() res = CloseHandle(thread); BOOST_CHECK(SUCCEEDED(res)); } +#endif #elif defined(BOOST_THREAD_PLATFORM_PTHREAD) typedef pthread_t native_thread_t;