diff options
author | Remko Tronçon <git@el-tramo.be> | 2012-12-23 13:16:26 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2012-12-23 14:43:26 (GMT) |
commit | 491ddd570a752cf9bda85933bed0c6942e39b1f9 (patch) | |
tree | 10c25c1be8cc08d0497df1dccd56a10fbb30beee /3rdParty/Boost/src/boost/thread | |
parent | da7d7a0ca71b80281aa9ff2526290b61ccb0cc60 (diff) | |
download | swift-491ddd570a752cf9bda85933bed0c6942e39b1f9.zip swift-491ddd570a752cf9bda85933bed0c6942e39b1f9.tar.bz2 |
Update Boost to 1.52.0.
Change-Id: I1e56bea2600bf2ed9c5b3aba8c4f9d2a0f350e77
Diffstat (limited to '3rdParty/Boost/src/boost/thread')
37 files changed, 4357 insertions, 1478 deletions
diff --git a/3rdParty/Boost/src/boost/thread/barrier.hpp b/3rdParty/Boost/src/boost/thread/barrier.hpp index 4ca30cb..4fd8988 100644 --- a/3rdParty/Boost/src/boost/thread/barrier.hpp +++ b/3rdParty/Boost/src/boost/thread/barrier.hpp @@ -2,7 +2,7 @@ // David Moore, William E. Kempf // Copyright (C) 2007-8 Anthony Williams // -// Distributed under the Boost Software License, Version 1.0. (See accompanying +// 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_BARRIER_JDM030602_HPP @@ -28,14 +28,14 @@ namespace boost : m_threshold(count), m_count(count), m_generation(0) { if (count == 0) - boost::throw_exception(std::invalid_argument("count cannot be zero.")); + boost::throw_exception(thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero.")); } - + bool wait() { boost::mutex::scoped_lock lock(m_mutex); unsigned int gen = m_generation; - + if (--m_count == 0) { m_generation++; diff --git a/3rdParty/Boost/src/boost/thread/condition.hpp b/3rdParty/Boost/src/boost/thread/condition.hpp deleted file mode 100644 index 35b879f..0000000 --- a/3rdParty/Boost/src/boost/thread/condition.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef BOOST_THREAD_CONDITION_HPP -#define BOOST_THREAD_CONDITION_HPP -// (C) Copyright 2007 Anthony Williams -// -// 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 <boost/thread/condition_variable.hpp> - -namespace boost -{ - typedef condition_variable_any condition; -} - -#endif diff --git a/3rdParty/Boost/src/boost/thread/cv_status.hpp b/3rdParty/Boost/src/boost/thread/cv_status.hpp new file mode 100644 index 0000000..99b3c0c --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/cv_status.hpp @@ -0,0 +1,26 @@ +// cv_status.hpp +// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// 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_CV_STATUS_HPP +#define BOOST_THREAD_CV_STATUS_HPP + +#include <boost/detail/scoped_enum_emulation.hpp> + +namespace boost +{ + + // enum class cv_status; + BOOST_SCOPED_ENUM_DECLARE_BEGIN(cv_status) + { + no_timeout, + timeout + } + BOOST_SCOPED_ENUM_DECLARE_END(cv_status) +} + +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/detail/config.hpp b/3rdParty/Boost/src/boost/thread/detail/config.hpp index 4015a6c..87bad34 100644 --- a/3rdParty/Boost/src/boost/thread/detail/config.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/config.hpp @@ -1,15 +1,138 @@ // Copyright (C) 2001-2003 // William E. Kempf +// Copyright (C) 2011-2012 Vicente J. Botet Escriba // -// Distributed under the Boost Software License, Version 1.0. (See accompanying +// 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_CONFIG_WEK01032003_HPP #define BOOST_THREAD_CONFIG_WEK01032003_HPP +// Force SIG_ATOMIC_MAX to be defined +//#ifndef __STDC_LIMIT_MACROS +//#define __STDC_LIMIT_MACROS +//#endif + #include <boost/config.hpp> #include <boost/detail/workaround.hpp> +#ifdef BOOST_NO_NOEXCEPT +# define BOOST_THREAD_NOEXCEPT_OR_THROW throw() +#else +# define BOOST_THREAD_NOEXCEPT_OR_THROW noexcept +#endif + +// This compiler doesn't support Boost.Chrono +#if defined __IBMCPP__ && (__IBMCPP__ < 1100) && ! defined BOOST_THREAD_DONT_USE_CHRONO +#define BOOST_THREAD_DONT_USE_CHRONO +#endif + +// This compiler doesn't support Boost.Move +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) && ! defined BOOST_THREAD_DONT_USE_MOVE +#define BOOST_THREAD_DONT_USE_MOVE +#endif + +// This compiler doesn't support Boost.Container Allocators files +#if defined __SUNPRO_CC && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS +#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS +#endif + +#if defined _WIN32_WCE && _WIN32_WCE==0x501 && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS +#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS +#endif + +#if ! defined BOOST_THREAD_DONT_PROVIDE_BASIC_THREAD_ID && ! defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID +#define BOOST_THREAD_PROVIDES_BASIC_THREAD_ID +#endif + +// Default version is 2 +#if !defined BOOST_THREAD_VERSION +#define BOOST_THREAD_VERSION 2 +#else +#if BOOST_THREAD_VERSION!=2 && BOOST_THREAD_VERSION!=3 +#error "BOOST_THREAD_VERSION must be 2 or 3" +#endif +#endif + +// Uses Boost.Chrono by default if not stated the opposite defining BOOST_THREAD_DONT_USE_CHRONO +#if ! defined BOOST_THREAD_DONT_USE_CHRONO && ! defined BOOST_THREAD_USES_CHRONO +#define BOOST_THREAD_USES_CHRONO +#endif + +// Don't provided by default in version 1. +#if defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION explicit +#else +#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION +#endif + + +#if BOOST_THREAD_VERSION==2 +#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY && ! defined BOOST_THREAD_PROMISE_LAZY +#define BOOST_THREAD_PROMISE_LAZY +#endif +#if ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 +#define BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 +#endif +#endif + +#if BOOST_THREAD_VERSION==3 +#if ! defined BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11 \ + && ! defined BOOST_THREAD_PROVIDES_ONCE_CXX11 +#define BOOST_THREAD_PROVIDES_ONCE_CXX11 +#endif +#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE \ + && ! defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE +#define BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE +#endif +#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE \ + && ! defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE +#define BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE +#endif +#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE \ + && ! defined BOOST_THREAD_PROVIDES_FUTURE +#define BOOST_THREAD_PROVIDES_FUTURE +#endif +#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS \ + && ! defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#define BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#endif +#if ! defined BOOST_THREAD_DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSIONS \ + && ! defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#endif +#if ! defined BOOST_THREAD_DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION \ + && ! defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#endif +#if ! defined BOOST_THREAD_DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN \ + && ! defined BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#endif +#if ! defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 \ + && ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_ +#define BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 +#endif +#if ! defined BOOST_THREAD_DONT_USE_MOVE \ + && ! defined BOOST_THREAD_USES_MOVE +#define BOOST_THREAD_USES_MOVE +#endif + +#endif + +// BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN is defined if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#if defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS \ +&& ! defined BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#endif + +// BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.52 +// BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.55 +#if ! defined BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 \ +&& ! defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 +#define BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 +#endif + #if BOOST_WORKAROUND(__BORLANDC__, < 0x600) # pragma warn -8008 // Condition always true/false # pragma warn -8080 // Identifier declared but never used @@ -17,11 +140,11 @@ # pragma warn -8066 // Unreachable code #endif -#include "platform.hpp" +#include <boost/thread/detail/platform.hpp> // provided for backwards compatibility, since this // macro was used for several releases by mistake. -#if defined(BOOST_THREAD_DYN_DLL) +#if defined(BOOST_THREAD_DYN_DLL) && ! defined BOOST_THREAD_DYN_LINK # define BOOST_THREAD_DYN_LINK #endif @@ -53,12 +176,18 @@ #if defined(BOOST_HAS_DECLSPEC) # if defined(BOOST_THREAD_BUILD_DLL) //Build dll -# define BOOST_THREAD_DECL __declspec(dllexport) +# define BOOST_THREAD_DECL BOOST_SYMBOL_EXPORT +//# define BOOST_THREAD_DECL __declspec(dllexport) + # elif defined(BOOST_THREAD_USE_DLL) //Use dll -# define BOOST_THREAD_DECL __declspec(dllimport) +# define BOOST_THREAD_DECL BOOST_SYMBOL_IMPORT +//# define BOOST_THREAD_DECL __declspec(dllimport) # else # define BOOST_THREAD_DECL # endif +#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# define BOOST_THREAD_DECL BOOST_SYMBOL_VISIBLE + #else # define BOOST_THREAD_DECL #endif // BOOST_HAS_DECLSPEC @@ -69,7 +198,7 @@ #if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL) && !defined(BOOST_THREAD_BUILD_LIB) // // Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp -// once it's done with it: +// once it's done with it: // #if defined(BOOST_THREAD_USE_DLL) # define BOOST_DYN_LINK diff --git a/3rdParty/Boost/src/boost/thread/detail/delete.hpp b/3rdParty/Boost/src/boost/thread/detail/delete.hpp new file mode 100644 index 0000000..30e7c93 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/detail/delete.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// 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_DETAIL_DELETE_HPP +#define BOOST_THREAD_DETAIL_DELETE_HPP + +#include <boost/config.hpp> + +/** + * BOOST_THREAD_DELETE_COPY_CTOR deletes the copy constructor when the compiler supports it or + * makes it private. + * + * BOOST_THREAD_DELETE_COPY_ASSIGN deletes the copy assignment when the compiler supports it or + * makes it private. + */ +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS +#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \ + CLASS(CLASS const&) = delete; \ + +#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \ + CLASS& operator=(CLASS const&) = delete; + +#else // BOOST_NO_CXX11_DELETED_FUNCTIONS +#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \ + private: \ + CLASS(CLASS&); \ + public: + +#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \ + private: \ + CLASS& operator=(CLASS&); \ + public: +#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS + +/** + * BOOST_THREAD_NO_COPYABLE deletes the copy constructor and assignment when the compiler supports it or + * makes them private. + */ +#define BOOST_THREAD_NO_COPYABLE(CLASS) \ + BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \ + BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) + +#endif // BOOST_THREAD_DETAIL_DELETE_HPP diff --git a/3rdParty/Boost/src/boost/thread/detail/memory.hpp b/3rdParty/Boost/src/boost/thread/detail/memory.hpp new file mode 100644 index 0000000..3c1692d --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/detail/memory.hpp @@ -0,0 +1,156 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_THREAD_DETAIL_MEMORY_HPP +#define BOOST_THREAD_DETAIL_MEMORY_HPP + +#include <boost/config.hpp> +#include <boost/container/allocator_traits.hpp> +#include <boost/container/scoped_allocator.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/is_convertible.hpp> +#include <boost/type_traits/is_scalar.hpp> +#include <boost/type_traits/is_pointer.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/static_assert.hpp> + +namespace boost +{ + namespace thread_detail + { + template <class _Alloc> + class allocator_destructor + { + typedef container::allocator_traits<_Alloc> alloc_traits; + public: + typedef typename alloc_traits::pointer pointer; + typedef typename alloc_traits::size_type size_type; + private: + _Alloc alloc_; + size_type s_; + public: + allocator_destructor(_Alloc& a, size_type s)BOOST_NOEXCEPT + : alloc_(a), s_(s) + {} + void operator()(pointer p)BOOST_NOEXCEPT + { + alloc_traits::destroy(alloc_, p); + alloc_traits::deallocate(alloc_, p, s_); + } + }; + } //namespace thread_detail + + typedef container::allocator_arg_t allocator_arg_t; + BOOST_CONSTEXPR_OR_CONST allocator_arg_t allocator_arg = {}; + + template <class T, class Alloc> + struct uses_allocator: public container::uses_allocator<T, Alloc> + { + }; + + template <class Ptr> + struct pointer_traits + { + typedef Ptr pointer; +// typedef <details> element_type; +// typedef <details> difference_type; + +// template <class U> using rebind = <details>; +// +// static pointer pointer_to(<details>); + }; + + template <class T> + struct pointer_traits<T*> + { + typedef T* pointer; + typedef T element_type; + typedef ptrdiff_t difference_type; + +// template <class U> using rebind = U*; +// +// static pointer pointer_to(<details>) noexcept; + }; + + + namespace thread_detail { + template <class _Ptr1, class _Ptr2, + bool = is_same<typename remove_cv<typename pointer_traits<_Ptr1>::element_type>::type, + typename remove_cv<typename pointer_traits<_Ptr2>::element_type>::type + >::value + > + struct same_or_less_cv_qualified_imp + : is_convertible<_Ptr1, _Ptr2> {}; + + template <class _Ptr1, class _Ptr2> + struct same_or_less_cv_qualified_imp<_Ptr1, _Ptr2, false> + : false_type {}; + + template <class _Ptr1, class _Ptr2, bool = is_scalar<_Ptr1>::value && + !is_pointer<_Ptr1>::value> + struct same_or_less_cv_qualified + : same_or_less_cv_qualified_imp<_Ptr1, _Ptr2> {}; + + template <class _Ptr1, class _Ptr2> + struct same_or_less_cv_qualified<_Ptr1, _Ptr2, true> + : false_type {}; + + } + template <class T> + struct BOOST_SYMBOL_VISIBLE default_delete + { + #ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS + BOOST_SYMBOL_VISIBLE + BOOST_CONSTEXPR default_delete() = default; + #else + BOOST_SYMBOL_VISIBLE + BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT {} + #endif + template <class U> + BOOST_SYMBOL_VISIBLE + default_delete(const default_delete<U>&, + typename enable_if<is_convertible<U*, T*> >::type* = 0) BOOST_NOEXCEPT {} + BOOST_SYMBOL_VISIBLE + void operator() (T* ptr) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type"); + delete ptr; + } + }; + + template <class T> + struct BOOST_SYMBOL_VISIBLE default_delete<T[]> + { + public: + #ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS + BOOST_SYMBOL_VISIBLE + BOOST_CONSTEXPR default_delete() = default; + #else + BOOST_SYMBOL_VISIBLE + BOOST_CONSTEXPR default_delete() BOOST_NOEXCEPT {} + #endif + template <class U> + BOOST_SYMBOL_VISIBLE + default_delete(const default_delete<U[]>&, + typename enable_if<thread_detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) BOOST_NOEXCEPT {} + template <class U> + BOOST_SYMBOL_VISIBLE + void operator() (U* ptr, + typename enable_if<thread_detail::same_or_less_cv_qualified<U*, T*> >::type* = 0) const BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "default_delete can not delete incomplete type"); + delete [] ptr; + } + }; + +} // namespace boost + + +#endif // BOOST_THREAD_DETAIL_MEMORY_HPP diff --git a/3rdParty/Boost/src/boost/thread/detail/move.hpp b/3rdParty/Boost/src/boost/thread/detail/move.hpp index eb21107..f2665e6 100644 --- a/3rdParty/Boost/src/boost/thread/detail/move.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/move.hpp @@ -2,21 +2,31 @@ // 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 #ifndef BOOST_THREAD_MOVE_HPP #define BOOST_THREAD_MOVE_HPP +#include <boost/thread/detail/config.hpp> #ifndef BOOST_NO_SFINAE #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_convertible.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/decay.hpp> #endif +#include <boost/thread/detail/delete.hpp> +#include <boost/move/move.hpp> #include <boost/config/abi_prefix.hpp> namespace boost { + namespace detail { + template <typename T> + struct has_move_emulation_enabled_aux_dummy_specialization; template<typename T> struct thread_move_t { @@ -39,22 +49,198 @@ namespace boost }; } + #ifndef BOOST_NO_SFINAE template<typename T> - typename enable_if<boost::is_convertible<T&,detail::thread_move_t<T> >, detail::thread_move_t<T> >::type move(T& t) + typename enable_if<boost::is_convertible<T&,boost::detail::thread_move_t<T> >, boost::detail::thread_move_t<T> >::type move(T& t) { - return detail::thread_move_t<T>(t); + return boost::detail::thread_move_t<T>(t); } #endif - + template<typename T> - detail::thread_move_t<T> move(detail::thread_move_t<T> t) + boost::detail::thread_move_t<T> move(boost::detail::thread_move_t<T> t) { return t; } - } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + +#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE) +#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG +#define BOOST_THREAD_RV_REF_END BOOST_RV_REF_END +#define BOOST_THREAD_RV(V) V +#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE +#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE) +#define BOOST_THREAD_DCL_MOVABLE(TYPE) +#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ + namespace detail { \ + template <typename T> \ + struct has_move_emulation_enabled_aux_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_END > \ + : integral_constant<bool, true> \ + {}; \ + } + +#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_MSVC + +#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE) +#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG +#define BOOST_THREAD_RV_REF_END BOOST_RV_REF_END +#define BOOST_THREAD_RV(V) V +#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE +#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE) +#define BOOST_THREAD_DCL_MOVABLE(TYPE) +#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ + namespace detail { \ + template <typename T> \ + struct has_move_emulation_enabled_aux_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_END > \ + : integral_constant<bool, true> \ + {}; \ + } + +#else + +#if defined BOOST_THREAD_USES_MOVE +#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE) +#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG +#define BOOST_THREAD_RV_REF_END BOOST_RV_REF_END +#define BOOST_THREAD_RV(V) V +#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE) +#define BOOST_THREAD_DCL_MOVABLE(TYPE) +#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ + namespace detail { \ + template <typename T> \ + struct has_move_emulation_enabled_aux_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_END > \ + : integral_constant<bool, true> \ + {}; \ + } + +#else + +#define BOOST_THREAD_RV_REF(TYPE) boost::detail::thread_move_t< TYPE > +#define BOOST_THREAD_RV_REF_BEG boost::detail::thread_move_t< +#define BOOST_THREAD_RV_REF_END > +#define BOOST_THREAD_RV(V) (*V) +#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE) + +#define BOOST_THREAD_DCL_MOVABLE(TYPE) \ +template <> \ +struct has_move_emulation_enabled_aux< TYPE > \ + : BOOST_MOVE_BOOST_NS::integral_constant<bool, true> \ +{}; + +#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ +template <typename T> \ +struct has_move_emulation_enabled_aux< + +#define BOOST_THREAD_DCL_MOVABLE_END > \ + : BOOST_MOVE_BOOST_NS::integral_constant<bool, true> \ +{}; + +#endif + +namespace boost +{ +namespace detail +{ + template <typename T> + BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type) + make_rv_ref(T v) BOOST_NOEXCEPT + { + return (BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v); + } +// template <typename T> +// BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type) +// make_rv_ref(T &v) BOOST_NOEXCEPT +// { +// return (BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v); +// } +// template <typename T> +// const BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type) +// make_rv_ref(T const&v) BOOST_NOEXCEPT +// { +// return (const BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v); +// } +} +} + +#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE.move() +//#define BOOST_THREAD_MAKE_RV_REF(RVALUE) boost::detail::make_rv_ref(RVALUE) +#endif + + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + +#define BOOST_THREAD_MOVABLE(TYPE) + +#else + +#if defined BOOST_THREAD_USES_MOVE + +#define BOOST_THREAD_MOVABLE(TYPE) \ + ::boost::rv<TYPE>& move() BOOST_NOEXCEPT \ + { \ + return *static_cast< ::boost::rv<TYPE>* >(this); \ + } \ + const ::boost::rv<TYPE>& move() const BOOST_NOEXCEPT \ + { \ + return *static_cast<const ::boost::rv<TYPE>* >(this); \ + } \ + operator ::boost::rv<TYPE>&() \ + { \ + return *static_cast< ::boost::rv<TYPE>* >(this); \ + } \ + operator const ::boost::rv<TYPE>&() const \ + { \ + return *static_cast<const ::boost::rv<TYPE>* >(this); \ + }\ + +#else + +#define BOOST_THREAD_MOVABLE(TYPE) \ + operator ::boost::detail::thread_move_t<TYPE>() BOOST_NOEXCEPT \ + { \ + return move(); \ + } \ + ::boost::detail::thread_move_t<TYPE> move() BOOST_NOEXCEPT \ + { \ + ::boost::detail::thread_move_t<TYPE> x(*this); \ + return x; \ + } \ + +#endif +#endif + +#define BOOST_THREAD_MOVABLE_ONLY(TYPE) \ + BOOST_THREAD_NO_COPYABLE(TYPE) \ + BOOST_THREAD_MOVABLE(TYPE) \ + +#define BOOST_THREAD_COPYABLE_AND_MOVABLE(TYPE) \ + BOOST_THREAD_MOVABLE(TYPE) \ + + + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +namespace boost +{ namespace thread_detail + { + template <class T> + typename decay<T>::type + decay_copy(T&& t) + { + return boost::forward<T>(t); + } + } +} +#endif + #include <boost/config/abi_suffix.hpp> #endif diff --git a/3rdParty/Boost/src/boost/thread/detail/platform.hpp b/3rdParty/Boost/src/boost/thread/detail/platform.hpp index 58601b0..1f33b1a 100644 --- a/3rdParty/Boost/src/boost/thread/detail/platform.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/platform.hpp @@ -19,6 +19,7 @@ // choose platform #if defined(linux) || defined(__linux) || defined(__linux__) # define BOOST_THREAD_LINUX +//# define BOOST_THREAD_WAIT_BUG boost::posix_time::microseconds(100000) #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) # define BOOST_THREAD_BSD #elif defined(sun) || defined(__sun) @@ -35,6 +36,7 @@ # define BOOST_THREAD_BEOS #elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) # define BOOST_THREAD_MACOS +//# define BOOST_THREAD_WAIT_BUG boost::posix_time::microseconds(1000) #elif defined(__IBMCPP__) || defined(_AIX) # define BOOST_THREAD_AIX #elif defined(__amigaos__) @@ -55,7 +57,7 @@ // dispatcher table. If there is no entry for a platform but pthreads is // available on the platform, pthread is choosen as default. If nothing is // available the preprocessor will fail with a diagnostic message. - + #if defined(BOOST_THREAD_POSIX) # define BOOST_THREAD_PLATFORM_PTHREAD #else diff --git a/3rdParty/Boost/src/boost/thread/detail/thread.hpp b/3rdParty/Boost/src/boost/thread/detail/thread.hpp index 005555e..2590f45 100644 --- a/3rdParty/Boost/src/boost/thread/detail/thread.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/thread.hpp @@ -4,7 +4,9 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007-10 Anthony Williams - +// (C) Copyright 20011-12 Vicente J. Botet Escriba + +#include <boost/thread/detail/config.hpp> #include <boost/thread/exceptions.hpp> #ifndef BOOST_NO_IOSTREAM #include <ostream> @@ -13,7 +15,6 @@ #include <boost/thread/mutex.hpp> #include <boost/thread/xtime.hpp> #include <boost/thread/detail/thread_heap_alloc.hpp> -#include <boost/utility.hpp> #include <boost/assert.hpp> #include <list> #include <algorithm> @@ -22,8 +23,18 @@ #include <boost/bind.hpp> #include <stdlib.h> #include <memory> +//#include <vector> +//#include <utility> #include <boost/utility/enable_if.hpp> #include <boost/type_traits/remove_reference.hpp> +#include <boost/io/ios_state.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/decay.hpp> +#include <boost/functional/hash.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif #include <boost/config/abi_prefix.hpp> @@ -34,6 +45,7 @@ namespace boost { + namespace detail { template<typename F> @@ -41,30 +53,33 @@ namespace boost public detail::thread_data_base { public: -#ifndef BOOST_NO_RVALUE_REFERENCES - thread_data(F&& f_): - f(static_cast<F&&>(f_)) - {} - thread_data(F& f_): - f(f_) - {} + BOOST_THREAD_NO_COPYABLE(thread_data) +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + thread_data(BOOST_THREAD_RV_REF(F) f_): + f(boost::forward<F>(f_)) + {} +// This overloading must be removed if we want the packaged_task's tests to pass. +// thread_data(F& f_): +// f(f_) +// {} #else - thread_data(F f_): - f(f_) + + thread_data(BOOST_THREAD_RV_REF(F) f_): + f(f_) {} - thread_data(detail::thread_move_t<F> f_): + thread_data(F f_): f(f_) {} -#endif +#endif + //thread_data() {} + void run() { f(); } + private: F f; - - void operator=(thread_data&); - thread_data(thread_data&); }; template<typename F> @@ -73,14 +88,11 @@ namespace boost { private: F& f; - - void operator=(thread_data&); - thread_data(thread_data&); public: + BOOST_THREAD_NO_COPYABLE(thread_data) thread_data(boost::reference_wrapper<F> f_): f(f_) {} - void run() { f(); @@ -93,45 +105,48 @@ namespace boost { private: F& f; - void operator=(thread_data&); - thread_data(thread_data&); public: + BOOST_THREAD_NO_COPYABLE(thread_data) thread_data(const boost::reference_wrapper<F> f_): f(f_) {} - void run() { f(); } }; } - + class BOOST_THREAD_DECL thread { + public: + typedef thread_attributes attributes; + + BOOST_THREAD_MOVABLE_ONLY(thread) private: - thread(thread&); - thread& operator=(thread&); void release_handle(); - + detail::thread_data_ptr thread_info; void start_thread(); - + void start_thread(const attributes& attr); + explicit thread(detail::thread_data_ptr data); detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const; -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template<typename F> - static inline detail::thread_data_ptr make_thread_info(F&& f) + static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f) { - return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(static_cast<F&&>(f))); + return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >( + boost::forward<F>(f))); } static inline detail::thread_data_ptr make_thread_info(void (*f)()) { - return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(static_cast<void(*&&)()>(f))); + return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >( + boost::forward<void(*)()>(f))); } #else template<typename F> @@ -140,7 +155,7 @@ namespace boost return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f)); } template<typename F> - static inline detail::thread_data_ptr make_thread_info(boost::detail::thread_move_t<F> f) + static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f) { return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f)); } @@ -148,46 +163,42 @@ namespace boost #endif struct dummy; public: +#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. #if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) - thread(const volatile thread&); -#endif - thread(); - ~thread(); - -#ifndef BOOST_NO_RVALUE_REFERENCES -#ifdef BOOST_MSVC - template <class F> - explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0): - thread_info(make_thread_info(static_cast<F&&>(f))) - { - start_thread(); - } -#else - template <class F> - thread(F&& f): - thread_info(make_thread_info(static_cast<F&&>(f))) - { - start_thread(); - } + thread(const volatile thread&); #endif - - thread(thread&& other) +#endif + thread() BOOST_NOEXCEPT; + ~thread() + { + #if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE + if (joinable()) { + std::terminate(); + } + #else + detach(); + #endif + } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template < + class F + > + explicit thread(BOOST_THREAD_RV_REF(F) f + , typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0 + ): + thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f)))) { - thread_info.swap(other.thread_info); + start_thread(); } - - thread& operator=(thread&& other) + template < + class F + > + thread(attributes& attrs, BOOST_THREAD_RV_REF(F) f): + thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f)))) { - thread_info=other.thread_info; - other.thread_info.reset(); - return *this; + start_thread(attrs); } - thread&& move() - { - return static_cast<thread&&>(*this); - } - #else #ifdef BOOST_NO_SFINAE template <class F> @@ -196,57 +207,73 @@ namespace boost { start_thread(); } + template <class F> + thread(attributes& attrs, F f): + thread_info(make_thread_info(f)) + { + start_thread(attrs); + } #else template <class F> - explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0): + explicit thread(F f + // todo Disable also if Or is_same<typename decay<F>::type, thread> + , typename disable_if<boost::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0): thread_info(make_thread_info(f)) { start_thread(); } + template <class F> + thread(attributes& attrs, F f + , typename disable_if<boost::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0): + thread_info(make_thread_info(f)) + { + start_thread(attrs); + } #endif - template <class F> - explicit thread(detail::thread_move_t<F> f): + explicit thread(BOOST_THREAD_RV_REF(F) f + , typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0 + ): thread_info(make_thread_info(f)) { start_thread(); } - thread(detail::thread_move_t<thread> x) + template <class F> + thread(attributes& attrs, BOOST_THREAD_RV_REF(F) f): + thread_info(make_thread_info(f)) { - thread_info=x->thread_info; - x->thread_info.reset(); + start_thread(attrs); } - -#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) - thread& operator=(thread x) - { - swap(x); - return *this; - } -#else - thread& operator=(detail::thread_move_t<thread> x) +#endif + thread(BOOST_THREAD_RV_REF(thread) x) { - thread new_thread(x); - swap(new_thread); - return *this; + thread_info=BOOST_THREAD_RV(x).thread_info; + BOOST_THREAD_RV(x).thread_info.reset(); } -#endif - operator detail::thread_move_t<thread>() +#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) + thread& operator=(thread x) { - return move(); + swap(x); + return *this; } - - detail::thread_move_t<thread> move() +#endif +#endif + + thread& operator=(BOOST_THREAD_RV_REF(thread) other) BOOST_NOEXCEPT { - detail::thread_move_t<thread> x(*this); - return x; - } +#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE + if (joinable()) std::terminate(); #endif + thread_info=BOOST_THREAD_RV(other).thread_info; + BOOST_THREAD_RV(other).thread_info.reset(); + return *this; + } template <class F,class A1> - thread(F f,A1 a1): + thread(F f,A1 a1,typename disable_if<boost::is_convertible<F&,thread_attributes >, dummy* >::type=0): thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1))) { start_thread(); @@ -307,40 +334,102 @@ namespace boost start_thread(); } - void swap(thread& x) + void swap(thread& x) BOOST_NOEXCEPT { thread_info.swap(x.thread_info); } - class id; - id get_id() const; + class BOOST_SYMBOL_VISIBLE id; + id get_id() const BOOST_NOEXCEPT; - bool joinable() const; + bool joinable() const BOOST_NOEXCEPT; void join(); - bool timed_join(const system_time& wait_until); +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool try_join_for(const chrono::duration<Rep, Period>& rel_time) + { + return try_join_until(chrono::steady_clock::now() + rel_time); + } + template <class Clock, class Duration> + bool try_join_until(const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_join_until(s_now + ceil<nanoseconds>(t - c_now)); + } + template <class Duration> + bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<system_clock, nanoseconds> nano_sys_tmpt; + return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + } +#endif +#if defined(BOOST_THREAD_PLATFORM_WIN32) + bool timed_join(const system_time& abs_time); + private: + bool do_try_join_until(uintmax_t milli); + public: +#ifdef BOOST_THREAD_USES_CHRONO + bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp) + { + chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now()); + return do_try_join_until(rel_time.count()); + } +#endif + + +#else + bool timed_join(const system_time& abs_time) + { + struct timespec const ts=detail::get_timespec(abs_time); + return do_try_join_until(ts); + } +#ifdef BOOST_THREAD_USES_CHRONO + bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts; + seconds s = duration_cast<seconds>(d); + ts.tv_sec = static_cast<long>(s.count()); + ts.tv_nsec = static_cast<long>((d - s).count()); + return do_try_join_until(ts); + } +#endif + private: + bool do_try_join_until(struct timespec const &timeout); + public: + +#endif template<typename TimeDuration> inline bool timed_join(TimeDuration const& rel_time) { return timed_join(get_system_time()+rel_time); } + void detach(); - static unsigned hardware_concurrency(); + static unsigned hardware_concurrency() BOOST_NOEXCEPT; +#define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE typedef detail::thread_data_base::native_handle_type native_handle_type; native_handle_type native_handle(); +#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 + // Use thread::id when comparisions are needed // backwards compatibility bool operator==(const thread& other) const; bool operator!=(const thread& other) const; - - static inline void yield() +#endif + static inline void yield() BOOST_NOEXCEPT { this_thread::yield(); } - + static inline void sleep(const system_time& xt) { this_thread::sleep(xt); @@ -348,85 +437,110 @@ namespace boost // extensions void interrupt(); - bool interruption_requested() const; + bool interruption_requested() const BOOST_NOEXCEPT; }; - inline void swap(thread& lhs,thread& rhs) + inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT { return lhs.swap(rhs); } - -#ifndef BOOST_NO_RVALUE_REFERENCES - inline thread&& move(thread& t) - { - return static_cast<thread&&>(t); - } - inline thread&& move(thread&& t) + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + inline thread&& move(thread& t) BOOST_NOEXCEPT { return static_cast<thread&&>(t); } -#else - inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t) - { - return t; - } #endif + BOOST_THREAD_DCL_MOVABLE(thread) + namespace this_thread { - thread::id BOOST_THREAD_DECL get_id(); + thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT; void BOOST_THREAD_DECL interruption_point(); - bool BOOST_THREAD_DECL interruption_enabled(); - bool BOOST_THREAD_DECL interruption_requested(); + bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT; + bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT; - inline void sleep(xtime const& abs_time) + inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time) { sleep(system_time(abs_time)); } } - class thread::id + class BOOST_SYMBOL_VISIBLE thread::id { private: - detail::thread_data_ptr thread_data; - - id(detail::thread_data_ptr thread_data_): + friend inline + std::size_t + hash_value(const thread::id &v) + { +#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID + return hash_value(v.thread_data); +#else + return hash_value(v.thread_data.get()); +#endif + } + +#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID +#if defined(BOOST_THREAD_PLATFORM_WIN32) + typedef unsigned int data; +#else + typedef thread::native_handle_type data; +#endif +#else + typedef detail::thread_data_ptr data; +#endif + data thread_data; + + id(data thread_data_): thread_data(thread_data_) {} friend class thread; - friend id BOOST_THREAD_DECL this_thread::get_id(); + friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT; public: - id(): - thread_data() + id() BOOST_NOEXCEPT: +#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID +#if defined(BOOST_THREAD_PLATFORM_WIN32) + thread_data(0) +#else + thread_data(0) +#endif +#else + thread_data() +#endif + {} + + id(const id& other) BOOST_NOEXCEPT : + thread_data(other.thread_data) {} - - bool operator==(const id& y) const + + bool operator==(const id& y) const BOOST_NOEXCEPT { return thread_data==y.thread_data; } - - bool operator!=(const id& y) const + + bool operator!=(const id& y) const BOOST_NOEXCEPT { return thread_data!=y.thread_data; } - - bool operator<(const id& y) const + + bool operator<(const id& y) const BOOST_NOEXCEPT { return thread_data<y.thread_data; } - - bool operator>(const id& y) const + + bool operator>(const id& y) const BOOST_NOEXCEPT { return y.thread_data<thread_data; } - - bool operator<=(const id& y) const + + bool operator<=(const id& y) const BOOST_NOEXCEPT { return !(y.thread_data<thread_data); } - - bool operator>=(const id& y) const + + bool operator>=(const id& y) const BOOST_NOEXCEPT { return !(thread_data<y.thread_data); } @@ -434,12 +548,14 @@ namespace boost #ifndef BOOST_NO_IOSTREAM #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS template<class charT, class traits> - friend std::basic_ostream<charT, traits>& + friend BOOST_SYMBOL_VISIBLE + std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const id& x) { if(x.thread_data) { - return os<<x.thread_data; + io::ios_flags_saver ifs( os ); + return os<< std::hex << x.thread_data; } else { @@ -448,12 +564,14 @@ namespace boost } #else template<class charT, class traits> - std::basic_ostream<charT, traits>& + BOOST_SYMBOL_VISIBLE + std::basic_ostream<charT, traits>& print(std::basic_ostream<charT, traits>& os) const { if(thread_data) { - return os<<thread_data; + io::ios_flags_saver ifs( os ); + return os<< std::hex << thread_data; } else { @@ -467,23 +585,26 @@ namespace boost #if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template<class charT, class traits> - std::basic_ostream<charT, traits>& + BOOST_SYMBOL_VISIBLE + std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x) { return x.print(os); } #endif +#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 inline bool thread::operator==(const thread& other) const { return get_id()==other.get_id(); } - + inline bool thread::operator!=(const thread& other) const { return get_id()!=other.get_id(); } - +#endif + namespace detail { struct thread_exit_function_base @@ -492,26 +613,26 @@ namespace boost {} virtual void operator()()=0; }; - + template<typename F> struct thread_exit_function: thread_exit_function_base { F f; - + thread_exit_function(F f_): f(f_) {} - + void operator()() { f(); } }; - + void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*); } - + namespace this_thread { template<typename F> diff --git a/3rdParty/Boost/src/boost/thread/detail/thread_interruption.hpp b/3rdParty/Boost/src/boost/thread/detail/thread_interruption.hpp index 60c0e65..f1a165c 100644 --- a/3rdParty/Boost/src/boost/thread/detail/thread_interruption.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/thread_interruption.hpp @@ -4,6 +4,10 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007-9 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/detail/delete.hpp> namespace boost { @@ -11,23 +15,20 @@ namespace boost { class BOOST_THREAD_DECL disable_interruption { - disable_interruption(const disable_interruption&); - disable_interruption& operator=(const disable_interruption&); - - bool interruption_was_enabled; - friend class restore_interruption; + bool interruption_was_enabled; + friend class restore_interruption; public: - disable_interruption(); - ~disable_interruption(); + BOOST_THREAD_NO_COPYABLE(disable_interruption) + disable_interruption() BOOST_NOEXCEPT; + ~disable_interruption() BOOST_NOEXCEPT; }; class BOOST_THREAD_DECL restore_interruption { - restore_interruption(const restore_interruption&); - restore_interruption& operator=(const restore_interruption&); public: - explicit restore_interruption(disable_interruption& d); - ~restore_interruption(); + BOOST_THREAD_NO_COPYABLE(restore_interruption) + explicit restore_interruption(disable_interruption& d) BOOST_NOEXCEPT; + ~restore_interruption() BOOST_NOEXCEPT; }; } } diff --git a/3rdParty/Boost/src/boost/thread/exceptions.hpp b/3rdParty/Boost/src/boost/thread/exceptions.hpp index 2a05b50..08c28d3 100644 --- a/3rdParty/Boost/src/boost/thread/exceptions.hpp +++ b/3rdParty/Boost/src/boost/thread/exceptions.hpp @@ -1,8 +1,9 @@ // Copyright (C) 2001-2003 // William E. Kempf // Copyright (C) 2007-9 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // -// Distributed under the Boost Software License, Version 1.0. (See accompanying +// 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_EXCEPTIONS_PDM070801_H @@ -18,161 +19,201 @@ #include <string> #include <stdexcept> +#include <boost/system/system_error.hpp> +#include <boost/system/error_code.hpp> + #include <boost/config/abi_prefix.hpp> namespace boost { - class thread_interrupted + class BOOST_SYMBOL_VISIBLE thread_interrupted {}; - class thread_exception: - public std::exception + class BOOST_SYMBOL_VISIBLE thread_exception: + public system::system_error + //public std::exception { - protected: - thread_exception(): - m_sys_err(0) + typedef system::system_error base_type; + public: + thread_exception() + : base_type(0,system::system_category()) {} - - thread_exception(int sys_err_code): - m_sys_err(sys_err_code) + + thread_exception(int sys_error_code) + : base_type(sys_error_code, system::system_category()) {} - - public: + thread_exception( int ev, const char * what_arg ) + : base_type(system::error_code(ev, system::system_category()), what_arg) + { + } + thread_exception( int ev, const std::string & what_arg ) + : base_type(system::error_code(ev, system::system_category()), what_arg) + { + } + ~thread_exception() throw() {} - + int native_error() const { - return m_sys_err; + return code().value(); } - - private: - int m_sys_err; }; - class condition_error: - public std::exception + class BOOST_SYMBOL_VISIBLE condition_error: + public system::system_error + //public std::exception { + typedef system::system_error base_type; public: - const char* what() const throw() - { - return "Condition error"; - } + condition_error() + : base_type(system::error_code(0, system::system_category()), "Condition error") + {} + condition_error( int ev ) + : base_type(system::error_code(ev, system::system_category()), "Condition error") + { + } + condition_error( int ev, const char * what_arg ) + : base_type(system::error_code(ev, system::system_category()), what_arg) + { + } + condition_error( int ev, const std::string & what_arg ) + : base_type(system::error_code(ev, system::system_category()), what_arg) + { + } }; - - class lock_error: + + class BOOST_SYMBOL_VISIBLE lock_error: public thread_exception { + typedef thread_exception base_type; public: lock_error() + : base_type(0, "boost::lock_error") {} - - lock_error(int sys_err_code): - thread_exception(sys_err_code) - {} - - ~lock_error() throw() - {} - - virtual const char* what() const throw() + lock_error( int ev ) + : base_type(ev, "boost::lock_error") + { + } + lock_error( int ev, const char * what_arg ) + : base_type(ev, what_arg) { - return "boost::lock_error"; } + lock_error( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + + ~lock_error() throw() + {} + }; - class thread_resource_error: + class BOOST_SYMBOL_VISIBLE thread_resource_error: public thread_exception { + typedef thread_exception base_type; public: - thread_resource_error() - {} - - thread_resource_error(int sys_err_code): - thread_exception(sys_err_code) - {} - + thread_resource_error() + : base_type(system::errc::resource_unavailable_try_again, "boost::thread_resource_error") + {} + + thread_resource_error( int ev ) + : base_type(ev, "boost::thread_resource_error") + { + } + thread_resource_error( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + thread_resource_error( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + + ~thread_resource_error() throw() {} - - virtual const char* what() const throw() - { - return "boost::thread_resource_error"; - } - }; - class unsupported_thread_option: + class BOOST_SYMBOL_VISIBLE unsupported_thread_option: public thread_exception { + typedef thread_exception base_type; public: - unsupported_thread_option() - {} - - unsupported_thread_option(int sys_err_code): - thread_exception(sys_err_code) - {} - - ~unsupported_thread_option() throw() - {} - + unsupported_thread_option() + : base_type(system::errc::invalid_argument, "boost::unsupported_thread_option") + {} + + unsupported_thread_option( int ev ) + : base_type(ev, "boost::unsupported_thread_option") + { + } + unsupported_thread_option( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + unsupported_thread_option( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } - virtual const char* what() const throw() - { - return "boost::unsupported_thread_option"; - } - }; - class invalid_thread_argument: + class BOOST_SYMBOL_VISIBLE invalid_thread_argument: public thread_exception { + typedef thread_exception base_type; public: invalid_thread_argument() + : base_type(system::errc::invalid_argument, "boost::invalid_thread_argument") {} - - invalid_thread_argument(int sys_err_code): - thread_exception(sys_err_code) - {} - - ~invalid_thread_argument() throw() - {} - - virtual const char* what() const throw() + invalid_thread_argument( int ev ) + : base_type(ev, "boost::invalid_thread_argument") + { + } + invalid_thread_argument( int ev, const char * what_arg ) + : base_type(ev, what_arg) { - return "boost::invalid_thread_argument"; } - + invalid_thread_argument( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + }; - class thread_permission_error: + class BOOST_SYMBOL_VISIBLE thread_permission_error: public thread_exception { + typedef thread_exception base_type; public: - thread_permission_error() - {} - - thread_permission_error(int sys_err_code): - thread_exception(sys_err_code) - {} - - ~thread_permission_error() throw() - {} - + thread_permission_error() + : base_type(system::errc::permission_denied, "boost::thread_permission_error") + {} + + thread_permission_error( int ev ) + : base_type(ev, "boost::thread_permission_error") + { + } + thread_permission_error( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + thread_permission_error( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } - virtual const char* what() const throw() - { - return "boost::thread_permission_error"; - } - }; } // namespace boost diff --git a/3rdParty/Boost/src/boost/thread/future.hpp b/3rdParty/Boost/src/boost/thread/future.hpp index a4b4343..6bf5cf6 100644 --- a/3rdParty/Boost/src/boost/thread/future.hpp +++ b/3rdParty/Boost/src/boost/thread/future.hpp @@ -1,4 +1,5 @@ -// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -6,6 +7,15 @@ #ifndef BOOST_THREAD_FUTURE_HPP #define BOOST_THREAD_FUTURE_HPP + +#include <boost/thread/detail/config.hpp> + +// boost::thread::future requires exception handling +// due to boost::exception::exception_ptr dependency + +#ifndef BOOST_NO_EXCEPTIONS + +#include <boost/detail/scoped_enum_emulation.hpp> #include <stdexcept> #include <boost/thread/detail/move.hpp> #include <boost/thread/thread_time.hpp> @@ -16,6 +26,8 @@ #include <boost/scoped_ptr.hpp> #include <boost/type_traits/is_fundamental.hpp> #include <boost/type_traits/is_convertible.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/type_traits/remove_cv.hpp> #include <boost/mpl/if.hpp> #include <boost/config.hpp> #include <boost/throw_exception.hpp> @@ -28,59 +40,168 @@ #include <list> #include <boost/next_prior.hpp> #include <vector> +#include <boost/system/error_code.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#endif + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include <boost/thread/detail/memory.hpp> +#endif + +#include <boost/utility/result_of.hpp> +#include <boost/thread/thread.hpp> + +#if defined BOOST_THREAD_PROVIDES_FUTURE +#define BOOST_THREAD_FUTURE future +#else +#define BOOST_THREAD_FUTURE unique_future +#endif + namespace boost { - class future_uninitialized: - public std::logic_error + + //enum class future_errc + BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc) + { + broken_promise, + future_already_retrieved, + promise_already_satisfied, + no_state + } + BOOST_SCOPED_ENUM_DECLARE_END(future_errc) + + namespace system + { + template <> + struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type {}; + + #ifdef BOOST_NO_CXX11_SCOPED_ENUMS + template <> + struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { }; + #endif + } + + //enum class launch + BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch) + { + async = 1, + deferred = 2, + any = async | deferred + } + BOOST_SCOPED_ENUM_DECLARE_END(launch) + + //enum class future_status + BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status) + { + ready, + timeout, + deferred + } + BOOST_SCOPED_ENUM_DECLARE_END(future_status) + + BOOST_THREAD_DECL + const system::error_category& future_category() BOOST_NOEXCEPT; + + namespace system + { + inline + error_code + make_error_code(future_errc e) //BOOST_NOEXCEPT + { + return error_code(underlying_cast<int>(e), boost::future_category()); + } + + inline + error_condition + make_error_condition(future_errc e) //BOOST_NOEXCEPT + { + return error_condition(underlying_cast<int>(e), future_category()); + } + } + + class BOOST_SYMBOL_VISIBLE future_error + : public std::logic_error + { + system::error_code ec_; + public: + future_error(system::error_code ec) + : logic_error(ec.message()), + ec_(ec) + { + } + + const system::error_code& code() const BOOST_NOEXCEPT + { + return ec_; + } + const char* what() const BOOST_THREAD_NOEXCEPT_OR_THROW + { + return code().message().c_str(); + } + + }; + + class BOOST_SYMBOL_VISIBLE future_uninitialized: + public future_error { public: - future_uninitialized(): - std::logic_error("Future Uninitialized") + future_uninitialized() : + future_error(system::make_error_code(future_errc::no_state)) {} }; - class broken_promise: - public std::logic_error + class BOOST_SYMBOL_VISIBLE broken_promise: + public future_error { public: broken_promise(): - std::logic_error("Broken promise") + future_error(system::make_error_code(future_errc::broken_promise)) {} }; - class future_already_retrieved: - public std::logic_error + class BOOST_SYMBOL_VISIBLE future_already_retrieved: + public future_error { public: future_already_retrieved(): - std::logic_error("Future already retrieved") + future_error(system::make_error_code(future_errc::future_already_retrieved)) {} }; - class promise_already_satisfied: - public std::logic_error + class BOOST_SYMBOL_VISIBLE promise_already_satisfied: + public future_error { public: promise_already_satisfied(): - std::logic_error("Promise already satisfied") + future_error(system::make_error_code(future_errc::promise_already_satisfied)) {} }; - class task_already_started: - public std::logic_error + class BOOST_SYMBOL_VISIBLE task_already_started: + public future_error { public: task_already_started(): - std::logic_error("Task already started") + future_error(system::make_error_code(future_errc::promise_already_satisfied)) {} }; - class task_moved: - public std::logic_error - { - public: - task_moved(): - std::logic_error("Task moved") - {} - }; + class BOOST_SYMBOL_VISIBLE task_moved: + public future_error + { + public: + task_moved(): + future_error(system::make_error_code(future_errc::no_state)) + {} + }; + + class promise_moved: + public future_error + { + public: + promise_moved(): + future_error(system::make_error_code(future_errc::no_state)) + {} + }; namespace future_state { @@ -93,6 +214,7 @@ namespace boost { boost::exception_ptr exception; bool done; + bool thread_was_interrupted; boost::mutex mutex; boost::condition_variable waiters; typedef std::list<boost::condition_variable_any*> waiter_list; @@ -100,7 +222,8 @@ namespace boost boost::function<void()> callback; future_object_base(): - done(false) + done(false), + thread_was_interrupted(false) {} virtual ~future_object_base() {} @@ -111,7 +234,7 @@ namespace boost do_callback(lock); return external_waiters.insert(external_waiters.end(),&cv); } - + void remove_external_waiter(waiter_list::iterator it) { boost::lock_guard<boost::mutex> lock(mutex); @@ -132,7 +255,7 @@ namespace boost struct relocker { boost::unique_lock<boost::mutex>& lock; - + relocker(boost::unique_lock<boost::mutex>& lock_): lock(lock_) { @@ -155,7 +278,7 @@ namespace boost local_callback(); } } - + void wait(bool rethrow=true) { @@ -165,6 +288,10 @@ namespace boost { waiters.wait(lock); } + if(rethrow && thread_was_interrupted) + { + throw boost::thread_interrupted(); + } if(rethrow && exception) { boost::rethrow_exception(exception); @@ -185,7 +312,26 @@ namespace boost } return true; } - + +#ifdef BOOST_THREAD_USES_CHRONO + + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) + { + boost::unique_lock<boost::mutex> lock(mutex); + do_callback(lock); + while(!done) + { + cv_status const st=waiters.wait_until(lock,abs_time); + if(st==cv_status::timeout && !done) + { + return future_status::timeout; + } + } + return future_status::ready; + } +#endif void mark_exceptional_finish_internal(boost::exception_ptr const& e) { exception=e; @@ -196,16 +342,21 @@ namespace boost boost::lock_guard<boost::mutex> lock(mutex); mark_exceptional_finish_internal(boost::current_exception()); } - + void mark_interrupted_finish() + { + boost::lock_guard<boost::mutex> lock(mutex); + thread_was_interrupted=true; + mark_finished_internal(); + } bool has_value() { boost::lock_guard<boost::mutex> lock(mutex); - return done && !exception; + return done && !(exception || thread_was_interrupted); } bool has_exception() { boost::lock_guard<boost::mutex> lock(mutex); - return done && exception; + return done && (exception || thread_was_interrupted); } template<typename F,typename U> @@ -213,7 +364,7 @@ namespace boost { callback=boost::bind(f,boost::ref(*u)); } - + private: future_object_base(future_object_base const&); future_object_base& operator=(future_object_base const&); @@ -223,25 +374,31 @@ namespace boost struct future_traits { typedef boost::scoped_ptr<T> storage_type; -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES typedef T const& source_reference_type; struct dummy; - typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,T&&>::type rvalue_source_type; - typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,T&&>::type move_dest_type; + typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type; + typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type; +#elif defined BOOST_THREAD_USES_MOVE + typedef T& source_reference_type; + typedef typename boost::mpl::if_<boost::has_move_emulation_enabled<T>,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type; + typedef typename boost::mpl::if_<boost::has_move_emulation_enabled<T>,BOOST_THREAD_RV_REF(T),T>::type move_dest_type; #else typedef T& source_reference_type; - typedef typename boost::mpl::if_<boost::is_convertible<T&,boost::detail::thread_move_t<T> >,boost::detail::thread_move_t<T>,T const&>::type rvalue_source_type; - typedef typename boost::mpl::if_<boost::is_convertible<T&,boost::detail::thread_move_t<T> >,boost::detail::thread_move_t<T>,T>::type move_dest_type; + typedef typename boost::mpl::if_<boost::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type; + typedef typename boost::mpl::if_<boost::is_convertible<T&,BOOST_THREAD_RV_REF(T) >,BOOST_THREAD_RV_REF(T),T>::type move_dest_type; #endif + typedef const T& shared_future_get_result_type; + static void init(storage_type& storage,source_reference_type t) { storage.reset(new T(t)); } - + static void init(storage_type& storage,rvalue_source_type t) { - storage.reset(new T(static_cast<rvalue_source_type>(t))); + storage.reset(new T(static_cast<rvalue_source_type>(t))); } static void cleanup(storage_type& storage) @@ -249,7 +406,7 @@ namespace boost storage.reset(); } }; - + template<typename T> struct future_traits<T&> { @@ -258,6 +415,7 @@ namespace boost struct rvalue_source_type {}; typedef T& move_dest_type; + typedef T& shared_future_get_result_type; static void init(storage_type& storage,T& t) { @@ -275,6 +433,7 @@ namespace boost { typedef bool storage_type; typedef void move_dest_type; + typedef void shared_future_get_result_type; static void init(storage_type& storage) { @@ -296,7 +455,8 @@ namespace boost typedef typename future_traits<T>::source_reference_type source_reference_type; typedef typename future_traits<T>::rvalue_source_type rvalue_source_type; typedef typename future_traits<T>::move_dest_type move_dest_type; - + typedef typename future_traits<T>::shared_future_get_result_type shared_future_get_result_type; + storage_type result; future_object(): @@ -308,6 +468,7 @@ namespace boost future_traits<T>::init(result,result_); mark_finished_internal(); } + void mark_finished_with_result_internal(rvalue_source_type result_) { future_traits<T>::init(result,static_cast<rvalue_source_type>(result_)); @@ -319,10 +480,11 @@ namespace boost boost::lock_guard<boost::mutex> lock(mutex); mark_finished_with_result_internal(result_); } + void mark_finished_with_result(rvalue_source_type result_) { boost::lock_guard<boost::mutex> lock(mutex); - mark_finished_with_result_internal(result_); + mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_)); } move_dest_type get() @@ -331,6 +493,12 @@ namespace boost return static_cast<move_dest_type>(*result); } + shared_future_get_result_type get_sh() + { + wait(); + return static_cast<shared_future_get_result_type>(*result); + } + future_state::state get_state() { boost::lock_guard<boost::mutex> guard(mutex); @@ -353,6 +521,8 @@ namespace boost struct future_object<void>: detail::future_object_base { + typedef void shared_future_get_result_type; + future_object() {} @@ -371,7 +541,10 @@ namespace boost { wait(); } - + void get_sh() + { + wait(); + } future_state::state get_state() { boost::lock_guard<boost::mutex> guard(mutex); @@ -384,74 +557,93 @@ namespace boost return future_state::ready; } } - private: future_object(future_object const&); future_object& operator=(future_object const&); }; +// template<typename T, typename Allocator> +// struct future_object_alloc: public future_object<T> +// { +// typedef future_object<T> base; +// Allocator alloc_; +// +// public: +// explicit future_object_alloc(const Allocator& a) +// : alloc_(a) {} +// +// }; class future_waiter { struct registered_waiter; - typedef std::vector<registered_waiter>::size_type count_type; - + typedef std::vector<int>::size_type count_type; + struct registered_waiter { - boost::shared_ptr<detail::future_object_base> future; + boost::shared_ptr<detail::future_object_base> future_; detail::future_object_base::waiter_list::iterator wait_iterator; count_type index; - registered_waiter(boost::shared_ptr<detail::future_object_base> const& future_, + registered_waiter(boost::shared_ptr<detail::future_object_base> const& a_future, detail::future_object_base::waiter_list::iterator wait_iterator_, count_type index_): - future(future_),wait_iterator(wait_iterator_),index(index_) + future_(a_future),wait_iterator(wait_iterator_),index(index_) {} }; - + struct all_futures_lock { - count_type count; +#ifdef _MANAGED + typedef std::ptrdiff_t count_type_portable; +#else + typedef count_type count_type_portable; +#endif + count_type_portable count; boost::scoped_array<boost::unique_lock<boost::mutex> > locks; - + all_futures_lock(std::vector<registered_waiter>& futures): count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count]) { - for(count_type i=0;i<count;++i) + for(count_type_portable i=0;i<count;++i) { - locks[i]=boost::unique_lock<boost::mutex>(futures[i].future->mutex); +#if defined __DECCXX || defined __SUNPRO_CC || defined __hpux + locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex).move(); +#else + locks[i]=boost::unique_lock<boost::mutex>(futures[i].future_->mutex); +#endif } } - + void lock() { boost::lock(locks.get(),locks.get()+count); } - + void unlock() { - for(count_type i=0;i<count;++i) + for(count_type_portable i=0;i<count;++i) { locks[i].unlock(); } } }; - + boost::condition_variable_any cv; std::vector<registered_waiter> futures; count_type future_count; - + public: future_waiter(): future_count(0) {} - + template<typename F> void add(F& f) { - if(f.future) + if(f.future_) { - futures.push_back(registered_waiter(f.future,f.future->register_external_waiter(cv),future_count)); + futures.push_back(registered_waiter(f.future_,f.future_->register_external_waiter(cv),future_count)); } ++future_count; } @@ -463,7 +655,7 @@ namespace boost { for(count_type i=0;i<futures.size();++i) { - if(futures[i].future->done) + if(futures[i].future_->done) { return futures[i].index; } @@ -471,21 +663,21 @@ namespace boost cv.wait(lk); } } - + ~future_waiter() { for(count_type i=0;i<futures.size();++i) { - futures[i].future->remove_external_waiter(futures[i].wait_iterator); + futures[i].future_->remove_external_waiter(futures[i].wait_iterator); } } - + }; - + } template <typename R> - class unique_future; + class BOOST_THREAD_FUTURE; template <typename R> class shared_future; @@ -495,13 +687,13 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value=false); }; - + template<typename T> - struct is_future_type<unique_future<T> > + struct is_future_type<BOOST_THREAD_FUTURE<T> > { BOOST_STATIC_CONSTANT(bool, value=true); }; - + template<typename T> struct is_future_type<shared_future<T> > { @@ -531,7 +723,7 @@ namespace boost f2.wait(); f3.wait(); } - + template<typename F1,typename F2,typename F3,typename F4> void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4) { @@ -556,7 +748,7 @@ namespace boost { if(begin==end) return end; - + detail::future_waiter waiter; for(Iterator current=begin;current!=end;++current) { @@ -583,7 +775,7 @@ namespace boost waiter.add(f3); return waiter.wait(); } - + template<typename F1,typename F2,typename F3,typename F4> unsigned wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4) { @@ -606,7 +798,7 @@ namespace boost waiter.add(f5); return waiter.wait(); } - + template <typename R> class promise; @@ -614,14 +806,13 @@ namespace boost class packaged_task; template <typename R> - class unique_future + class BOOST_THREAD_FUTURE { - unique_future(unique_future & rhs);// = delete; - unique_future& operator=(unique_future& rhs);// = delete; + private: typedef boost::shared_ptr<detail::future_object<R> > future_ptr; - - future_ptr future; + + future_ptr future_; friend class shared_future<R>; friend class promise<R>; @@ -630,139 +821,151 @@ namespace boost typedef typename detail::future_traits<R>::move_dest_type move_dest_type; - unique_future(future_ptr future_): - future(future_) + BOOST_THREAD_FUTURE(future_ptr a_future): + future_(a_future) {} public: + BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) typedef future_state::state state; - unique_future() + BOOST_THREAD_FUTURE() {} - - ~unique_future() + + ~BOOST_THREAD_FUTURE() {} -#ifndef BOOST_NO_RVALUE_REFERENCES - unique_future(unique_future && other) - { - future.swap(other.future); - } - unique_future& operator=(unique_future && other) - { - future=other.future; - other.future.reset(); - return *this; - } -#else - unique_future(boost::detail::thread_move_t<unique_future> other): - future(other->future) + BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: + future_(BOOST_THREAD_RV(other).future_) { - other->future.reset(); + BOOST_THREAD_RV(other).future_.reset(); } - unique_future& operator=(boost::detail::thread_move_t<unique_future> other) + BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT { - future=other->future; - other->future.reset(); + future_=BOOST_THREAD_RV(other).future_; + BOOST_THREAD_RV(other).future_.reset(); return *this; } - operator boost::detail::thread_move_t<unique_future>() + shared_future<R> share() { - return boost::detail::thread_move_t<unique_future>(*this); + return shared_future<R>(::boost::move(*this)); } -#endif - void swap(unique_future& other) + void swap(BOOST_THREAD_FUTURE& other) { - future.swap(other.future); + future_.swap(other.future_); } // retrieving the value move_dest_type get() { - if(!future) + if(!future_) { boost::throw_exception(future_uninitialized()); } - return future->get(); + return future_->get(); } - + // functions to check state, and wait for ready - state get_state() const + state get_state() const BOOST_NOEXCEPT { - if(!future) + if(!future_) { return future_state::uninitialized; } - return future->get_state(); + return future_->get_state(); } - - bool is_ready() const + bool is_ready() const BOOST_NOEXCEPT { return get_state()==future_state::ready; } - - bool has_exception() const + + bool has_exception() const BOOST_NOEXCEPT { - return future && future->has_exception(); + return future_ && future_->has_exception(); } - - bool has_value() const + + bool has_value() const BOOST_NOEXCEPT { - return future && future->has_value(); + return future_ && future_->has_value(); } - + + bool valid() const BOOST_NOEXCEPT + { + return future_ != 0; + } + + void wait() const { - if(!future) + if(!future_) { boost::throw_exception(future_uninitialized()); } - future->wait(false); + future_->wait(false); } - + template<typename Duration> bool timed_wait(Duration const& rel_time) const { return timed_wait_until(boost::get_system_time()+rel_time); } - + bool timed_wait_until(boost::system_time const& abs_time) const { - if(!future) + if(!future_) { boost::throw_exception(future_uninitialized()); } - return future->timed_wait_until(abs_time); + return future_->timed_wait_until(abs_time); } - +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + future_status + wait_for(const chrono::duration<Rep, Period>& rel_time) const + { + return wait_until(chrono::steady_clock::now() + rel_time); + + } + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) const + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->wait_until(abs_time); + } +#endif }; + BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END + template <typename R> class shared_future { typedef boost::shared_ptr<detail::future_object<R> > future_ptr; - - future_ptr future; -// shared_future(const unique_future<R>& other); -// shared_future& operator=(const unique_future<R>& other); + future_ptr future_; friend class detail::future_waiter; friend class promise<R>; friend class packaged_task<R>; - - shared_future(future_ptr future_): - future(future_) + + shared_future(future_ptr a_future): + future_(a_future) {} public: + BOOST_THREAD_MOVABLE(shared_future) + shared_future(shared_future const& other): - future(other.future) + future_(other.future_) {} typedef future_state::state state; @@ -775,396 +978,405 @@ namespace boost shared_future& operator=(shared_future const& other) { - future=other.future; + future_=other.future_; return *this; } -#ifndef BOOST_NO_RVALUE_REFERENCES - shared_future(shared_future && other) + shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(other).future_) { - future.swap(other.future); + BOOST_THREAD_RV(other).future_.reset(); } - shared_future(unique_future<R> && other) + shared_future(BOOST_THREAD_RV_REF_BEG BOOST_THREAD_FUTURE<R> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(other).future_) { - future.swap(other.future); + BOOST_THREAD_RV(other).future_.reset(); } - shared_future& operator=(shared_future && other) + shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT { - future.swap(other.future); - other.future.reset(); + future_.swap(BOOST_THREAD_RV(other).future_); + BOOST_THREAD_RV(other).future_.reset(); return *this; } - shared_future& operator=(unique_future<R> && other) + shared_future& operator=(BOOST_THREAD_RV_REF_BEG BOOST_THREAD_FUTURE<R> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT { - future.swap(other.future); - other.future.reset(); + future_.swap(BOOST_THREAD_RV(other).future_); + BOOST_THREAD_RV(other).future_.reset(); return *this; } -#else - shared_future(boost::detail::thread_move_t<shared_future> other): - future(other->future) - { - other->future.reset(); - } -// shared_future(const unique_future<R> &) = delete; - shared_future(boost::detail::thread_move_t<unique_future<R> > other): - future(other->future) - { - other->future.reset(); - } - shared_future& operator=(boost::detail::thread_move_t<shared_future> other) - { - future.swap(other->future); - other->future.reset(); - return *this; - } - shared_future& operator=(boost::detail::thread_move_t<unique_future<R> > other) - { - future.swap(other->future); - other->future.reset(); - return *this; - } - - operator boost::detail::thread_move_t<shared_future>() - { - return boost::detail::thread_move_t<shared_future>(*this); - } - -#endif - void swap(shared_future& other) + void swap(shared_future& other) BOOST_NOEXCEPT { - future.swap(other.future); + future_.swap(other.future_); } // retrieving the value - R get() + typename detail::future_object<R>::shared_future_get_result_type get() { - if(!future) + if(!future_) { boost::throw_exception(future_uninitialized()); } - return future->get(); + return future_->get_sh(); } - + // functions to check state, and wait for ready - state get_state() const + state get_state() const BOOST_NOEXCEPT { - if(!future) + if(!future_) { return future_state::uninitialized; } - return future->get_state(); + return future_->get_state(); } - - bool is_ready() const + bool valid() const BOOST_NOEXCEPT + { + return future_ != 0; + } + + bool is_ready() const BOOST_NOEXCEPT { return get_state()==future_state::ready; } - - bool has_exception() const + + bool has_exception() const BOOST_NOEXCEPT { - return future && future->has_exception(); + return future_ && future_->has_exception(); } - - bool has_value() const + + bool has_value() const BOOST_NOEXCEPT { - return future && future->has_value(); + return future_ && future_->has_value(); } void wait() const { - if(!future) + if(!future_) { boost::throw_exception(future_uninitialized()); } - future->wait(false); + future_->wait(false); } - + template<typename Duration> bool timed_wait(Duration const& rel_time) const { return timed_wait_until(boost::get_system_time()+rel_time); } - + bool timed_wait_until(boost::system_time const& abs_time) const { - if(!future) + if(!future_) { boost::throw_exception(future_uninitialized()); } - return future->timed_wait_until(abs_time); + return future_->timed_wait_until(abs_time); } - +#ifdef BOOST_THREAD_USES_CHRONO + + template <class Rep, class Period> + future_status + wait_for(const chrono::duration<Rep, Period>& rel_time) const + { + return wait_until(chrono::steady_clock::now() + rel_time); + + } + template <class Clock, class Duration> + future_status + wait_until(const chrono::time_point<Clock, Duration>& abs_time) const + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->wait_until(abs_time); + } +#endif }; + BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END + template <typename R> class promise { typedef boost::shared_ptr<detail::future_object<R> > future_ptr; - - future_ptr future; + + future_ptr future_; bool future_obtained; - - promise(promise & rhs);// = delete; - promise & operator=(promise & rhs);// = delete; void lazy_init() { - if(!atomic_load(&future)) +#if defined BOOST_THREAD_PROMISE_LAZY + if(!atomic_load(&future_)) { future_ptr blank; - atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<R>)); + atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<R>)); } +#endif } - + public: -// template <class Allocator> explicit promise(Allocator a); + BOOST_THREAD_MOVABLE_ONLY(promise) +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template <class Allocator> + promise(boost::allocator_arg_t, Allocator a) + { + typedef typename Allocator::template rebind<detail::future_object<R> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<R>(), D(a2, 1) ); + future_obtained = false; + } +#endif promise(): - future(),future_obtained(false) +#if defined BOOST_THREAD_PROMISE_LAZY + future_(), +#else + future_(new detail::future_object<R>()), +#endif + future_obtained(false) {} - + ~promise() { - if(future) + if(future_) { - boost::lock_guard<boost::mutex> lock(future->mutex); + boost::lock_guard<boost::mutex> lock(future_->mutex); - if(!future->done) + if(!future_->done) { - future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise())); + future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise())); } } } // Assignment -#ifndef BOOST_NO_RVALUE_REFERENCES - promise(promise && rhs): - future_obtained(rhs.future_obtained) + promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) { - future.swap(rhs.future); - rhs.future_obtained=false; + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; } - promise & operator=(promise&& rhs) + promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT { - future.swap(rhs.future); - future_obtained=rhs.future_obtained; - rhs.future.reset(); - rhs.future_obtained=false; - return *this; - } -#else - promise(boost::detail::thread_move_t<promise> rhs): - future(rhs->future),future_obtained(rhs->future_obtained) - { - rhs->future.reset(); - rhs->future_obtained=false; - } - promise & operator=(boost::detail::thread_move_t<promise> rhs) - { - future=rhs->future; - future_obtained=rhs->future_obtained; - rhs->future.reset(); - rhs->future_obtained=false; + future_=BOOST_THREAD_RV(rhs).future_; + future_obtained=BOOST_THREAD_RV(rhs).future_obtained; + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; return *this; } - operator boost::detail::thread_move_t<promise>() - { - return boost::detail::thread_move_t<promise>(*this); - } -#endif - void swap(promise& other) { - future.swap(other.future); + future_.swap(other.future_); std::swap(future_obtained,other.future_obtained); } // Result retrieval - unique_future<R> get_future() + BOOST_THREAD_FUTURE<R> get_future() { lazy_init(); - if(future_obtained) + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + if (future_obtained) { boost::throw_exception(future_already_retrieved()); } future_obtained=true; - return unique_future<R>(future); + return BOOST_THREAD_FUTURE<R>(future_); } void set_value(typename detail::future_traits<R>::source_reference_type r) { lazy_init(); - boost::lock_guard<boost::mutex> lock(future->mutex); - if(future->done) + boost::lock_guard<boost::mutex> lock(future_->mutex); + if(future_->done) { boost::throw_exception(promise_already_satisfied()); } - future->mark_finished_with_result_internal(r); + future_->mark_finished_with_result_internal(r); } // void set_value(R && r); void set_value(typename detail::future_traits<R>::rvalue_source_type r) { lazy_init(); - boost::lock_guard<boost::mutex> lock(future->mutex); - if(future->done) + boost::lock_guard<boost::mutex> lock(future_->mutex); + if(future_->done) { boost::throw_exception(promise_already_satisfied()); } - future->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r)); + future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r)); } void set_exception(boost::exception_ptr p) { lazy_init(); - boost::lock_guard<boost::mutex> lock(future->mutex); - if(future->done) + boost::lock_guard<boost::mutex> lock(future_->mutex); + if(future_->done) { boost::throw_exception(promise_already_satisfied()); } - future->mark_exceptional_finish_internal(p); + future_->mark_exceptional_finish_internal(p); } + // setting the result with deferred notification + //void set_value_at_thread_exit(const R& r); // NOT YET IMPLEMENTED + //void set_value_at_thread_exit(see below); // NOT YET IMPLEMENTED + //void set_exception_at_thread_exit(exception_ptr p); // NOT YET IMPLEMENTED + template<typename F> void set_wait_callback(F f) { lazy_init(); - future->set_wait_callback(f,this); + future_->set_wait_callback(f,this); } - + }; template <> class promise<void> { typedef boost::shared_ptr<detail::future_object<void> > future_ptr; - - future_ptr future; + + future_ptr future_; bool future_obtained; - - promise(promise & rhs);// = delete; - promise & operator=(promise & rhs);// = delete; void lazy_init() { - if(!atomic_load(&future)) +#if defined BOOST_THREAD_PROMISE_LAZY + if(!atomic_load(&future_)) { future_ptr blank; - atomic_compare_exchange(&future,&blank,future_ptr(new detail::future_object<void>)); + atomic_compare_exchange(&future_,&blank,future_ptr(new detail::future_object<void>)); } +#endif } public: -// template <class Allocator> explicit promise(Allocator a); + BOOST_THREAD_MOVABLE_ONLY(promise) + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template <class Allocator> + promise(boost::allocator_arg_t, Allocator a) + { + typedef typename Allocator::template rebind<detail::future_object<void> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + future_ = future_ptr(::new(a2.allocate(1)) detail::future_object<void>(), D(a2, 1) ); + future_obtained = false; + } +#endif promise(): - future(),future_obtained(false) +#if defined BOOST_THREAD_PROMISE_LAZY + future_(), +#else + future_(new detail::future_object<void>), +#endif + future_obtained(false) {} - + ~promise() { - if(future) + if(future_) { - boost::lock_guard<boost::mutex> lock(future->mutex); + boost::lock_guard<boost::mutex> lock(future_->mutex); - if(!future->done) + if(!future_->done) { - future->mark_exceptional_finish_internal(boost::copy_exception(broken_promise())); + future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise())); } } } // Assignment -#ifndef BOOST_NO_RVALUE_REFERENCES - promise(promise && rhs): - future_obtained(rhs.future_obtained) - { - future.swap(rhs.future); - rhs.future_obtained=false; - } - promise & operator=(promise&& rhs) + promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) { - future.swap(rhs.future); - future_obtained=rhs.future_obtained; - rhs.future.reset(); - rhs.future_obtained=false; - return *this; - } -#else - promise(boost::detail::thread_move_t<promise> rhs): - future(rhs->future),future_obtained(rhs->future_obtained) - { - rhs->future.reset(); - rhs->future_obtained=false; + // we need to release the future as shared_ptr doesn't implements move semantics + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; } - promise & operator=(boost::detail::thread_move_t<promise> rhs) + + promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT { - future=rhs->future; - future_obtained=rhs->future_obtained; - rhs->future.reset(); - rhs->future_obtained=false; + future_=BOOST_THREAD_RV(rhs).future_; + future_obtained=BOOST_THREAD_RV(rhs).future_obtained; + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; return *this; } - operator boost::detail::thread_move_t<promise>() - { - return boost::detail::thread_move_t<promise>(*this); - } -#endif - void swap(promise& other) { - future.swap(other.future); + future_.swap(other.future_); std::swap(future_obtained,other.future_obtained); } // Result retrieval - unique_future<void> get_future() + BOOST_THREAD_FUTURE<void> get_future() { lazy_init(); - + + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } if(future_obtained) { boost::throw_exception(future_already_retrieved()); } future_obtained=true; - return unique_future<void>(future); + return BOOST_THREAD_FUTURE<void>(future_); } void set_value() { lazy_init(); - boost::lock_guard<boost::mutex> lock(future->mutex); - if(future->done) + boost::lock_guard<boost::mutex> lock(future_->mutex); + if(future_->done) { boost::throw_exception(promise_already_satisfied()); } - future->mark_finished_with_result_internal(); + future_->mark_finished_with_result_internal(); } void set_exception(boost::exception_ptr p) { lazy_init(); - boost::lock_guard<boost::mutex> lock(future->mutex); - if(future->done) + boost::lock_guard<boost::mutex> lock(future_->mutex); + if(future_->done) { boost::throw_exception(promise_already_satisfied()); } - future->mark_exceptional_finish_internal(p); + future_->mark_exceptional_finish_internal(p); } template<typename F> void set_wait_callback(F f) { lazy_init(); - future->set_wait_callback(f,this); + future_->set_wait_callback(f,this); } - + }; +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + namespace container + { + template <class R, class Alloc> + struct uses_allocator<promise<R> , Alloc> : true_type + { + }; + } +#endif + + BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END + namespace detail { template<typename R> @@ -1177,6 +1389,10 @@ namespace boost started(false) {} + void reset() + { + started=false; + } void run() { { @@ -1199,30 +1415,44 @@ namespace boost this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise())); } } - - + + virtual void do_run()=0; }; - - + + + + template<typename R,typename F> struct task_object: task_base<R> { + private: + task_object(task_object&); + public: F f; task_object(F const& f_): f(f_) {} - task_object(boost::detail::thread_move_t<F> f_): - f(f_) +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + task_object(BOOST_THREAD_RV_REF(F) f_): + f(boost::forward<F>(f_)) + {} +#else + task_object(BOOST_THREAD_RV_REF(F) f_): + f(boost::move(f_)) {} - +#endif void do_run() { try { this->mark_finished_with_result(f()); } + catch(thread_interrupted& ) + { + this->mark_interrupted_finish(); + } catch(...) { this->mark_exceptional_finish(); @@ -1230,18 +1460,55 @@ namespace boost } }; + template<typename R> + struct task_object<R,R (*)()>: + task_base<R> + { + private: + task_object(task_object&); + public: + R (*f)(); + task_object(R (*f_)()): + f(f_) + {} + void do_run() + { + try + { + this->mark_finished_with_result(f()); + } + catch(thread_interrupted& ) + { + this->mark_interrupted_finish(); + } + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; + template<typename F> struct task_object<void,F>: task_base<void> { + private: + task_object(task_object&); + public: F f; task_object(F const& f_): f(f_) {} - task_object(boost::detail::thread_move_t<F> f_): - f(f_) +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + task_object(BOOST_THREAD_RV_REF(F) f_): + f(boost::forward<F>(f_)) {} - +#else + task_object(BOOST_THREAD_RV_REF(F) f_): + f(boost::move(f_)) + {} +#endif + void do_run() { try @@ -1249,6 +1516,39 @@ namespace boost f(); this->mark_finished_with_result(); } + catch(thread_interrupted& ) + { + this->mark_interrupted_finish(); + } + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; + + template<> + struct task_object<void,void (*)()>: + task_base<void> + { + private: + task_object(task_object&); + public: + void (*f)(); + task_object(void (*f_)()): + f(f_) + {} + void do_run() + { + try + { + f(); + this->mark_finished_with_result(); + } + catch(thread_interrupted& ) + { + this->mark_interrupted_finish(); + } catch(...) { this->mark_exceptional_finish(); @@ -1257,41 +1557,92 @@ namespace boost }; } - template<typename R> class packaged_task { + typedef boost::shared_ptr<detail::task_base<R> > task_ptr; boost::shared_ptr<detail::task_base<R> > task; bool future_obtained; - packaged_task(packaged_task&);// = delete; - packaged_task& operator=(packaged_task&);// = delete; - public: + typedef R result_type; + BOOST_THREAD_MOVABLE_ONLY(packaged_task) + packaged_task(): future_obtained(false) {} - + // construction and destruction - template <class F> - explicit packaged_task(F const& f): - task(new detail::task_object<R,F>(f)),future_obtained(false) - {} + explicit packaged_task(R(*f)()): task(new detail::task_object<R,R(*)()>(f)),future_obtained(false) {} - +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template <class F> + explicit packaged_task(BOOST_THREAD_RV_REF(F) f): + task(new detail::task_object<R, + typename remove_cv<typename remove_reference<F>::type>::type + >(boost::forward<F>(f))),future_obtained(false) + {} +#else template <class F> - explicit packaged_task(boost::detail::thread_move_t<F> f): + explicit packaged_task(F const& f): task(new detail::task_object<R,F>(f)),future_obtained(false) {} + template <class F> + explicit packaged_task(BOOST_THREAD_RV_REF(F) f): + task(new detail::task_object<R,F>(boost::move(f))),future_obtained(false) + {} +#endif -// template <class F, class Allocator> -// explicit packaged_task(F const& f, Allocator a); -// template <class F, class Allocator> -// explicit packaged_task(F&& f, Allocator a); +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template <class Allocator> + packaged_task(boost::allocator_arg_t, Allocator a, R(*f)()) + { + typedef R(*FR)(); + typedef typename Allocator::template rebind<detail::task_object<R,FR> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,FR>(f), D(a2, 1) ); + future_obtained = false; + } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template <class F, class Allocator> + packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f) + { + typedef typename remove_cv<typename remove_reference<F>::type>::type FR; + typedef typename Allocator::template rebind<detail::task_object<R,FR> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + + task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,FR>(boost::forward<F>(f)), D(a2, 1) ); + future_obtained = false; + } +#else + template <class F, class Allocator> + packaged_task(boost::allocator_arg_t, Allocator a, const F& f) + { + typedef typename Allocator::template rebind<detail::task_object<R,F> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + + task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(f), D(a2, 1) ); + future_obtained = false; + } + template <class F, class Allocator> + packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f) + { + typedef typename Allocator::template rebind<detail::task_object<R,F> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + + task = task_ptr(::new(a2.allocate(1)) detail::task_object<R,F>(boost::move(f)), D(a2, 1) ); + future_obtained = false; + } +#endif //BOOST_NO_CXX11_RVALUE_REFERENCES +#endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS ~packaged_task() { @@ -1302,46 +1653,39 @@ namespace boost } // assignment -#ifndef BOOST_NO_RVALUE_REFERENCES - packaged_task(packaged_task&& other): - future_obtained(other.future_obtained) + packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT : + future_obtained(BOOST_THREAD_RV(other).future_obtained) { - task.swap(other.task); - other.future_obtained=false; + task.swap(BOOST_THREAD_RV(other).task); + BOOST_THREAD_RV(other).future_obtained=false; } - packaged_task& operator=(packaged_task&& other) + packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT { - packaged_task temp(static_cast<packaged_task&&>(other)); + packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other)); swap(temp); return *this; } -#else - packaged_task(boost::detail::thread_move_t<packaged_task> other): - future_obtained(other->future_obtained) - { - task.swap(other->task); - other->future_obtained=false; - } - packaged_task& operator=(boost::detail::thread_move_t<packaged_task> other) - { - packaged_task temp(other); - swap(temp); - return *this; - } - operator boost::detail::thread_move_t<packaged_task>() + + void reset() { - return boost::detail::thread_move_t<packaged_task>(*this); + if (!valid()) + throw future_error(system::make_error_code(future_errc::no_state)); + task->reset(); + future_obtained=false; } -#endif - void swap(packaged_task& other) + void swap(packaged_task& other) BOOST_NOEXCEPT { task.swap(other.task); std::swap(future_obtained,other.future_obtained); } + bool valid() const BOOST_NOEXCEPT + { + return task.get()!=0; + } // result retrieval - unique_future<R> get_future() + BOOST_THREAD_FUTURE<R> get_future() { if(!task) { @@ -1350,14 +1694,16 @@ namespace boost else if(!future_obtained) { future_obtained=true; - return unique_future<R>(task); + return BOOST_THREAD_FUTURE<R>(task); } else { boost::throw_exception(future_already_retrieved()); } + return BOOST_THREAD_FUTURE<R>(); + } - + // execution void operator()() @@ -1374,10 +1720,149 @@ namespace boost { task->set_wait_callback(f,this); } - + }; -} +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + namespace container + { + template <class R, class Alloc> + struct uses_allocator<packaged_task<R>, Alloc> + : public true_type {}; + } +#endif + + BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END + + + template <class R> + BOOST_THREAD_FUTURE<R> + async(launch policy, R(*f)()) + { + if (int(policy) & int(launch::async)) + { + packaged_task<R> pt( f ); + + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + boost::thread( boost::move(pt) ).detach(); + return ::boost::move(ret); + } + else if (int(policy) & int(launch::deferred)) + { + packaged_task<R> pt( f ); + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + return ::boost::move(ret); + } else { + BOOST_THREAD_FUTURE<R> ret; + return ::boost::move(ret); + } + } + + template <class R> + BOOST_THREAD_FUTURE<R> + async(R(*f)()) + { + return async(launch::any, f); + } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template <class F> + BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> + async(launch policy, BOOST_THREAD_FWD_REF(F) f) + { + typedef typename boost::result_of<typename decay<F>::type()>::type R; + if (int(policy) & int(launch::async)) + { + packaged_task<R> pt( boost::forward<F>(f) ); + + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + boost::thread( boost::move(pt) ).detach(); + return ::boost::move(ret); + } + else if (int(policy) & int(launch::deferred)) + { + packaged_task<R> pt( boost::forward<F>(f) ); + + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + return ::boost::move(ret); + } else { + BOOST_THREAD_FUTURE<R> ret; + return ::boost::move(ret); + } + } + template <class F> + BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> + async(BOOST_THREAD_RV_REF(F) f) + { + return async(launch::any, boost::forward<F>(f)); + } +#else + +// template <class F> +// BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> +// async(launch policy, F const& f) +// { +// typedef typename boost::result_of<typename decay<F>::type()>::type R; +// if (int(policy) & int(launch::async)) +// { +// packaged_task<R> pt( f ); +// +// BOOST_THREAD_FUTURE<R> ret = pt.get_future(); +// boost::thread( boost::move(pt) ).detach(); +// return ::boost::move(ret); +// } +// else if (int(policy) & int(launch::deferred)) +// { +// packaged_task<R> pt( f ); +// +// BOOST_THREAD_FUTURE<R> ret = pt.get_future(); +// return ::boost::move(ret); +// } else { +// BOOST_THREAD_FUTURE<R> ret; +// return ::boost::move(ret); +// } +// } +// template <class F> +// BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> +// async(F const& f) +// { +// return async(launch::any, f); +// } + + template <class F> + BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> + async(launch policy, BOOST_THREAD_FWD_REF(F) f) + { + typedef typename boost::result_of<typename decay<F>::type()>::type R; + if (int(policy) & int(launch::async)) + { + packaged_task<R> pt( boost::forward<F>(f) ); + + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + boost::thread( boost::move(pt) ).detach(); + return ::boost::move(ret); + } + else if (int(policy) & int(launch::deferred)) + { + packaged_task<R> pt( boost::forward<F>(f) ); + + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + return ::boost::move(ret); + } else { + BOOST_THREAD_FUTURE<R> ret; + return ::boost::move(ret); + } + } + template <class F> + BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> + async(BOOST_THREAD_FWD_REF(F) f) + { + return async(launch::any, boost::forward<F>(f)); + } #endif + +} + +#endif // BOOST_NO_EXCEPTION +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/locks.hpp b/3rdParty/Boost/src/boost/thread/locks.hpp index d23e619..c11c2bd 100644 --- a/3rdParty/Boost/src/boost/thread/locks.hpp +++ b/3rdParty/Boost/src/boost/thread/locks.hpp @@ -2,6 +2,8 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + #ifndef BOOST_THREAD_LOCKS_HPP #define BOOST_THREAD_LOCKS_HPP #include <boost/thread/detail/config.hpp> @@ -12,6 +14,10 @@ #include <boost/thread/thread_time.hpp> #include <boost/detail/workaround.hpp> #include <boost/type_traits/is_class.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/time_point.hpp> +#include <boost/chrono/duration.hpp> +#endif #include <boost/config/abi_prefix.hpp> @@ -71,7 +77,7 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value=false); }; - + template<typename T> struct has_member_lock<T,true> { @@ -80,22 +86,22 @@ namespace boost { true_type dummy[2]; }; - + template<typename U,typename V> static true_type has_member(V (U::*)()); template<typename U> static false_type has_member(U); - + BOOST_STATIC_CONSTANT( bool,value=sizeof(has_member_lock<T>::has_member(&T::lock))==sizeof(true_type)); }; - + template<typename T,bool=has_member_called_unlock<T>::value > struct has_member_unlock { BOOST_STATIC_CONSTANT(bool, value=false); }; - + template<typename T> struct has_member_unlock<T,true> { @@ -104,22 +110,22 @@ namespace boost { true_type dummy[2]; }; - + template<typename U,typename V> static true_type has_member(V (U::*)()); template<typename U> static false_type has_member(U); - + BOOST_STATIC_CONSTANT( bool,value=sizeof(has_member_unlock<T>::has_member(&T::unlock))==sizeof(true_type)); }; - + template<typename T,bool=has_member_called_try_lock<T>::value > struct has_member_try_lock { BOOST_STATIC_CONSTANT(bool, value=false); }; - + template<typename T> struct has_member_try_lock<T,true> { @@ -128,18 +134,18 @@ namespace boost { true_type dummy[2]; }; - + template<typename U> static true_type has_member(bool (U::*)()); template<typename U> static false_type has_member(U); - + BOOST_STATIC_CONSTANT( bool,value=sizeof(has_member_try_lock<T>::has_member(&T::try_lock))==sizeof(true_type)); }; } - + template<typename T> struct is_mutex_type @@ -147,7 +153,7 @@ namespace boost BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value && detail::has_member_unlock<T>::value && detail::has_member_try_lock<T>::value); - + }; #else template<typename T> @@ -155,7 +161,7 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value = false); }; -#endif +#endif struct defer_lock_t {}; @@ -163,10 +169,10 @@ namespace boost {}; struct adopt_lock_t {}; - - const defer_lock_t defer_lock={}; - const try_to_lock_t try_to_lock={}; - const adopt_lock_t adopt_lock={}; + + BOOST_CONSTEXPR_OR_CONST defer_lock_t defer_lock={}; + BOOST_CONSTEXPR_OR_CONST try_to_lock_t try_to_lock={}; + BOOST_CONSTEXPR_OR_CONST adopt_lock_t adopt_lock={}; template<typename Mutex> class shared_lock; @@ -182,7 +188,7 @@ namespace boost template<typename Mutex> class try_lock_wrapper; } - + #ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES template<typename T> struct is_mutex_type<unique_lock<T> > @@ -201,7 +207,7 @@ namespace boost { BOOST_STATIC_CONSTANT(bool, value = true); }; - + template<typename T> struct is_mutex_type<detail::try_lock_wrapper<T> > { @@ -213,7 +219,7 @@ namespace boost class recursive_mutex; class recursive_timed_mutex; class shared_mutex; - + template<> struct is_mutex_type<mutex> { @@ -248,9 +254,10 @@ namespace boost private: Mutex& m; - explicit lock_guard(lock_guard&); - lock_guard& operator=(lock_guard&); public: + typedef Mutex mutex_type; + BOOST_THREAD_NO_COPYABLE(lock_guard) + explicit lock_guard(Mutex& m_): m(m_) { @@ -265,25 +272,29 @@ namespace boost } }; - template<typename Mutex> class unique_lock { private: Mutex* m; bool is_locked; - unique_lock(unique_lock&); + + private: explicit unique_lock(upgrade_lock<Mutex>&); - unique_lock& operator=(unique_lock&); unique_lock& operator=(upgrade_lock<Mutex>& other); public: -#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) - unique_lock(const volatile unique_lock&); + typedef Mutex mutex_type; + BOOST_THREAD_MOVABLE_ONLY(unique_lock) + +#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) + unique_lock(const volatile unique_lock&); #endif - unique_lock(): +#endif + unique_lock() BOOST_NOEXCEPT : m(0),is_locked(false) {} - + explicit unique_lock(Mutex& m_): m(&m_),is_locked(false) { @@ -292,7 +303,7 @@ namespace boost unique_lock(Mutex& m_,adopt_lock_t): m(&m_),is_locked(true) {} - unique_lock(Mutex& m_,defer_lock_t): + unique_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT: m(&m_),is_locked(false) {} unique_lock(Mutex& m_,try_to_lock_t): @@ -311,91 +322,172 @@ namespace boost { timed_lock(target_time); } -#ifndef BOOST_NO_RVALUE_REFERENCES - unique_lock(unique_lock&& other): - m(other.m),is_locked(other.is_locked) + +#ifdef BOOST_THREAD_USES_CHRONO + template <class Clock, class Duration> + unique_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t) + : m(&mtx), is_locked(mtx.try_lock_until(t)) { - other.is_locked=false; - other.m=0; } - explicit unique_lock(upgrade_lock<Mutex>&& other); - - unique_lock<Mutex>&& move() + template <class Rep, class Period> + unique_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d) + : m(&mtx), is_locked(mtx.try_lock_for(d)) { - return static_cast<unique_lock<Mutex>&&>(*this); } +#endif + unique_lock(BOOST_THREAD_RV_REF(unique_lock) other) BOOST_NOEXCEPT: + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) + { + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; + } + BOOST_THREAD_EXPLICIT_LOCK_CONVERSION unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other); - unique_lock& operator=(unique_lock&& other) +#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION + unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT { - unique_lock temp(other.move()); + unique_lock temp(::boost::move(other)); swap(temp); return *this; } +#endif - unique_lock& operator=(upgrade_lock<Mutex>&& other) + unique_lock& operator=(BOOST_THREAD_RV_REF(unique_lock) other) BOOST_NOEXCEPT { - unique_lock temp(other.move()); + unique_lock temp(::boost::move(other)); swap(temp); return *this; } - void swap(unique_lock&& other) - { - std::swap(m,other.m); - std::swap(is_locked,other.is_locked); - } -#else - unique_lock(detail::thread_move_t<unique_lock<Mutex> > other): - m(other->m),is_locked(other->is_locked) +#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) + unique_lock& operator=(unique_lock<Mutex> other) { - other->is_locked=false; - other->m=0; + swap(other); + return *this; } - unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other); +#endif // BOOST_WORKAROUND +#endif - operator detail::thread_move_t<unique_lock<Mutex> >() + // Conversion from upgrade locking + unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul, try_to_lock_t) + : m(0),is_locked(false) { - return move(); + if (BOOST_THREAD_RV(ul).owns_lock()) { + if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock()) + { + m = BOOST_THREAD_RV(ul).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(ul).release(); + } } - detail::thread_move_t<unique_lock<Mutex> > move() +#ifdef BOOST_THREAD_USES_CHRONO + template <class Clock, class Duration> + unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul, + const chrono::time_point<Clock, Duration>& abs_time) + : m(0),is_locked(false) { - return detail::thread_move_t<unique_lock<Mutex> >(*this); + if (BOOST_THREAD_RV(ul).owns_lock()) { + if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock_until(abs_time)) + { + m = BOOST_THREAD_RV(ul).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(ul).release(); + } } -#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) - unique_lock& operator=(unique_lock<Mutex> other) - { - swap(other); - return *this; - } -#else - unique_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other) + template <class Rep, class Period> + unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<mutex_type> BOOST_THREAD_RV_REF_END ul, + const chrono::duration<Rep, Period>& rel_time) + : m(0),is_locked(false) { - unique_lock temp(other); - swap(temp); - return *this; + if (BOOST_THREAD_RV(ul).owns_lock()) { + if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock_for(rel_time)) + { + m = BOOST_THREAD_RV(ul).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(ul).release(); + } } #endif - unique_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other) +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + // Conversion from shared locking + unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, try_to_lock_t) + : m(0),is_locked(false) { - unique_lock temp(other); - swap(temp); - return *this; + if (BOOST_THREAD_RV(sl).owns_lock()) { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock()) + { + m = BOOST_THREAD_RV(sl).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(sl).release(); + } + } + +#ifdef BOOST_THREAD_USES_CHRONO + template <class Clock, class Duration> + unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, + const chrono::time_point<Clock, Duration>& abs_time) + : m(0),is_locked(false) + { + if (BOOST_THREAD_RV(sl).owns_lock()) { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_until(abs_time)) + { + m = BOOST_THREAD_RV(sl).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(sl).release(); + } } - void swap(detail::thread_move_t<unique_lock<Mutex> > other) + + template <class Rep, class Period> + unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, + const chrono::duration<Rep, Period>& rel_time) + : m(0),is_locked(false) { - std::swap(m,other->m); - std::swap(is_locked,other->is_locked); + if (BOOST_THREAD_RV(sl).owns_lock()) { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_for(rel_time)) + { + m = BOOST_THREAD_RV(sl).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(sl).release(); + } } -#endif - void swap(unique_lock& other) +#endif // BOOST_THREAD_USES_CHRONO +#endif // BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + + + void swap(unique_lock& other) BOOST_NOEXCEPT { std::swap(m,other.m); std::swap(is_locked,other.is_locked); } - + ~unique_lock() { if(owns_lock()) @@ -405,18 +497,26 @@ namespace boost } void lock() { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex")); + } if(owns_lock()) { - boost::throw_exception(boost::lock_error()); + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex")); } m->lock(); is_locked=true; } bool try_lock() { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex")); + } if(owns_lock()) { - boost::throw_exception(boost::lock_error()); + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex")); } is_locked=m->try_lock(); return is_locked; @@ -424,50 +524,118 @@ namespace boost template<typename TimeDuration> bool timed_lock(TimeDuration const& relative_time) { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex")); + } is_locked=m->timed_lock(relative_time); return is_locked; } - + bool timed_lock(::boost::system_time const& absolute_time) { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex")); + } is_locked=m->timed_lock(absolute_time); return is_locked; } bool timed_lock(::boost::xtime const& absolute_time) { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex")); + } is_locked=m->timed_lock(absolute_time); return is_locked; } + +#ifdef BOOST_THREAD_USES_CHRONO + + template <class Rep, class Period> + bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex")); + } + is_locked=m->try_lock_for(rel_time); + return is_locked; + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex")); + } + is_locked=m->try_lock_until(abs_time); + return is_locked; + } +#endif + void unlock() { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock has no mutex")); + } if(!owns_lock()) { - boost::throw_exception(boost::lock_error()); + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost unique_lock doesn't own the mutex")); } m->unlock(); is_locked=false; } - + +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) typedef void (unique_lock::*bool_type)(); - operator bool_type() const + operator bool_type() const BOOST_NOEXCEPT { return is_locked?&unique_lock::lock:0; } - bool operator!() const + bool operator!() const BOOST_NOEXCEPT { return !owns_lock(); } - bool owns_lock() const +#else + explicit operator bool() const BOOST_NOEXCEPT + { + return owns_lock(); + } +#endif + bool owns_lock() const BOOST_NOEXCEPT { return is_locked; } - Mutex* mutex() const + Mutex* mutex() const BOOST_NOEXCEPT { return m; } - Mutex* release() + Mutex* release() BOOST_NOEXCEPT { Mutex* const res=m; m=0; @@ -479,44 +647,13 @@ namespace boost friend class upgrade_lock<Mutex>; }; -#ifndef BOOST_NO_RVALUE_REFERENCES - template<typename Mutex> - void swap(unique_lock<Mutex>&& lhs,unique_lock<Mutex>&& rhs) - { - lhs.swap(rhs); - } - - template<typename Mutex> - inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>&& ul) - { - return static_cast<upgrade_lock<Mutex>&&>(ul); - } - - template<typename Mutex> - inline upgrade_lock<Mutex>&& move(upgrade_lock<Mutex>& ul) - { - return static_cast<upgrade_lock<Mutex>&&>(ul); - } -#endif template<typename Mutex> - void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs) + void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs) BOOST_NOEXCEPT { lhs.swap(rhs); } -#ifndef BOOST_NO_RVALUE_REFERENCES - template<typename Mutex> - inline unique_lock<Mutex>&& move(unique_lock<Mutex>&& ul) - { - return static_cast<unique_lock<Mutex>&&>(ul); - } - - template<typename Mutex> - inline unique_lock<Mutex>&& move(unique_lock<Mutex>& ul) - { - return static_cast<unique_lock<Mutex>&&>(ul); - } -#endif + BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END template<typename Mutex> class shared_lock @@ -524,14 +661,15 @@ namespace boost protected: Mutex* m; bool is_locked; - private: - explicit shared_lock(shared_lock&); - shared_lock& operator=(shared_lock&); + public: - shared_lock(): + typedef Mutex mutex_type; + BOOST_THREAD_MOVABLE_ONLY(shared_lock) + + shared_lock() BOOST_NOEXCEPT: m(0),is_locked(false) {} - + explicit shared_lock(Mutex& m_): m(&m_),is_locked(false) { @@ -540,7 +678,7 @@ namespace boost shared_lock(Mutex& m_,adopt_lock_t): m(&m_),is_locked(true) {} - shared_lock(Mutex& m_,defer_lock_t): + shared_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT: m(&m_),is_locked(false) {} shared_lock(Mutex& m_,try_to_lock_t): @@ -554,91 +692,90 @@ namespace boost timed_lock(target_time); } - shared_lock(detail::thread_move_t<shared_lock<Mutex> > other): - m(other->m),is_locked(other->is_locked) +#ifdef BOOST_THREAD_USES_CHRONO + template <class Clock, class Duration> + shared_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t) + : m(&mtx), is_locked(mtx.try_lock_shared_until(t)) + { + } + template <class Rep, class Period> + shared_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d) + : m(&mtx), is_locked(mtx.try_lock_shared_for(d)) + { + } +#endif + + shared_lock(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT: + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) { - other->is_locked=false; - other->m=0; + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; } - shared_lock(detail::thread_move_t<unique_lock<Mutex> > other): - m(other->m),is_locked(other->is_locked) + BOOST_THREAD_EXPLICIT_LOCK_CONVERSION shared_lock(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other): + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) { if(is_locked) { m->unlock_and_lock_shared(); } - other->is_locked=false; - other->m=0; + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; } - shared_lock(detail::thread_move_t<upgrade_lock<Mutex> > other): - m(other->m),is_locked(other->is_locked) + BOOST_THREAD_EXPLICIT_LOCK_CONVERSION shared_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other): + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) { if(is_locked) { m->unlock_upgrade_and_lock_shared(); } - other->is_locked=false; - other->m=0; + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; } - operator detail::thread_move_t<shared_lock<Mutex> >() - { - return move(); - } - detail::thread_move_t<shared_lock<Mutex> > move() + shared_lock& operator=(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT { - return detail::thread_move_t<shared_lock<Mutex> >(*this); - } - - - shared_lock& operator=(detail::thread_move_t<shared_lock<Mutex> > other) - { - shared_lock temp(other); + shared_lock temp(::boost::move(other)); swap(temp); return *this; } - - shared_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other) +#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION + shared_lock& operator=(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) { - shared_lock temp(other); + shared_lock temp(::boost::move(other)); swap(temp); return *this; } - shared_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other) + shared_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) { - shared_lock temp(other); + shared_lock temp(::boost::move(other)); swap(temp); return *this; } +#endif -#ifndef BOOST_NO_RVALUE_REFERENCES - void swap(shared_lock&& other) + void swap(shared_lock& other) BOOST_NOEXCEPT { std::swap(m,other.m); std::swap(is_locked,other.is_locked); } -#else - void swap(boost::detail::thread_move_t<shared_lock<Mutex> > other) - { - std::swap(m,other->m); - std::swap(is_locked,other->is_locked); - } -#endif - void swap(shared_lock& other) + + Mutex* mutex() const BOOST_NOEXCEPT { - std::swap(m,other.m); - std::swap(is_locked,other.is_locked); + return m; } - Mutex* mutex() const + Mutex* release() BOOST_NOEXCEPT { - return m; + Mutex* const res=m; + m=0; + is_locked=false; + return res; } - + ~shared_lock() { if(owns_lock()) @@ -648,27 +785,39 @@ namespace boost } void lock() { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex")); + } if(owns_lock()) { - boost::throw_exception(boost::lock_error()); + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex")); } m->lock_shared(); is_locked=true; } bool try_lock() { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex")); + } if(owns_lock()) { - boost::throw_exception(boost::lock_error()); + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex")); } is_locked=m->try_lock_shared(); return is_locked; } bool timed_lock(boost::system_time const& target_time) { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex")); + } if(owns_lock()) { - boost::throw_exception(boost::lock_error()); + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex")); } is_locked=m->timed_lock_shared(target_time); return is_locked; @@ -676,52 +825,91 @@ namespace boost template<typename Duration> bool timed_lock(Duration const& target_time) { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex")); + } if(owns_lock()) { - boost::throw_exception(boost::lock_error()); + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex")); } is_locked=m->timed_lock_shared(target_time); return is_locked; } +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex")); + } + is_locked=m->try_lock_shared_for(rel_time); + return is_locked; + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex")); + } + is_locked=m->try_lock_shared_until(abs_time); + return is_locked; + } +#endif void unlock() { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex")); + } if(!owns_lock()) { - boost::throw_exception(boost::lock_error()); + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock doesn't own the mutex")); } m->unlock_shared(); is_locked=false; } - + +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) typedef void (shared_lock<Mutex>::*bool_type)(); - operator bool_type() const + operator bool_type() const BOOST_NOEXCEPT { return is_locked?&shared_lock::lock:0; } - bool operator!() const + bool operator!() const BOOST_NOEXCEPT { return !owns_lock(); } - bool owns_lock() const +#else + explicit operator bool() const BOOST_NOEXCEPT + { + return owns_lock(); + } +#endif + bool owns_lock() const BOOST_NOEXCEPT { return is_locked; } }; -#ifndef BOOST_NO_RVALUE_REFERENCES - template<typename Mutex> - void swap(shared_lock<Mutex>&& lhs,shared_lock<Mutex>&& rhs) - { - lhs.swap(rhs); - } -#else + BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) shared_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END + template<typename Mutex> - void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs) + void swap(shared_lock<Mutex>& lhs,shared_lock<Mutex>& rhs) BOOST_NOEXCEPT { lhs.swap(rhs); } -#endif template<typename Mutex> class upgrade_lock @@ -729,14 +917,15 @@ namespace boost protected: Mutex* m; bool is_locked; - private: - explicit upgrade_lock(upgrade_lock&); - upgrade_lock& operator=(upgrade_lock&); + public: - upgrade_lock(): + typedef Mutex mutex_type; + BOOST_THREAD_MOVABLE_ONLY(upgrade_lock) + + upgrade_lock() BOOST_NOEXCEPT: m(0),is_locked(false) {} - + explicit upgrade_lock(Mutex& m_): m(&m_),is_locked(false) { @@ -745,7 +934,7 @@ namespace boost upgrade_lock(Mutex& m_,adopt_lock_t): m(&m_),is_locked(true) {} - upgrade_lock(Mutex& m_,defer_lock_t): + upgrade_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT: m(&m_),is_locked(false) {} upgrade_lock(Mutex& m_,try_to_lock_t): @@ -753,89 +942,128 @@ namespace boost { try_lock(); } -#ifdef BOOST_HAS_RVALUE_REFS - upgrade_lock(upgrade_lock<Mutex>&& other): - m(other.m),is_locked(other.is_locked) + +#ifdef BOOST_THREAD_USES_CHRONO + template <class Clock, class Duration> + upgrade_lock(Mutex& mtx, const chrono::time_point<Clock, Duration>& t) + : m(&mtx), is_locked(mtx.try_lock_upgrade_until(t)) + { + } + template <class Rep, class Period> + upgrade_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d) + : m(&mtx), is_locked(mtx.try_lock_upgrade_for(d)) + { + } +#endif + + upgrade_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT: + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) { - other.is_locked=false; - other.m=0; + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; } - upgrade_lock(unique_lock<Mutex>&& other): - m(other.m),is_locked(other.is_locked) + BOOST_THREAD_EXPLICIT_LOCK_CONVERSION upgrade_lock(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other): + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) { if(is_locked) { m->unlock_and_lock_upgrade(); } - other.is_locked=false; - other.m=0; + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; } - upgrade_lock& operator=(upgrade_lock<Mutex>&& other) + upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT { - upgrade_lock temp(static_cast<upgrade_lock<Mutex>&&>(other)); + upgrade_lock temp(::boost::move(other)); swap(temp); return *this; } - upgrade_lock& operator=(unique_lock<Mutex>&& other) +#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION + upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) { - upgrade_lock temp(static_cast<unique_lock<Mutex>&&>(other)); + upgrade_lock temp(::boost::move(other)); swap(temp); return *this; } -#else - upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other): - m(other->m),is_locked(other->is_locked) - { - other->is_locked=false; - other->m=0; - } +#endif - upgrade_lock(detail::thread_move_t<unique_lock<Mutex> > other): - m(other->m),is_locked(other->is_locked) +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + // Conversion from shared locking + upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, try_to_lock_t) + : m(0),is_locked(false) { - if(is_locked) + if (BOOST_THREAD_RV(sl).owns_lock()) { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade()) { - m->unlock_and_lock_upgrade(); + m = BOOST_THREAD_RV(sl).release(); + is_locked = true; } - other->is_locked=false; - other->m=0; + } + else + { + m = BOOST_THREAD_RV(sl).release(); + } } - operator detail::thread_move_t<upgrade_lock<Mutex> >() +#ifdef BOOST_THREAD_USES_CHRONO + template <class Clock, class Duration> + upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, + const chrono::time_point<Clock, Duration>& abs_time) + : m(0),is_locked(false) { - return move(); + if (BOOST_THREAD_RV(sl).owns_lock()) { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade_until(abs_time)) + { + m = BOOST_THREAD_RV(sl).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(sl).release(); + } } - detail::thread_move_t<upgrade_lock<Mutex> > move() + template <class Rep, class Period> + upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock<mutex_type> BOOST_THREAD_RV_REF_END sl, + const chrono::duration<Rep, Period>& rel_time) + : m(0),is_locked(false) { - return detail::thread_move_t<upgrade_lock<Mutex> >(*this); + if (BOOST_THREAD_RV(sl).owns_lock()) { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade_for(rel_time)) + { + m = BOOST_THREAD_RV(sl).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(sl).release(); + } } +#endif // BOOST_THREAD_USES_CHRONO +#endif // BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS - - upgrade_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other) + void swap(upgrade_lock& other) BOOST_NOEXCEPT { - upgrade_lock temp(other); - swap(temp); - return *this; + std::swap(m,other.m); + std::swap(is_locked,other.is_locked); } - - upgrade_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other) + Mutex* mutex() const BOOST_NOEXCEPT { - upgrade_lock temp(other); - swap(temp); - return *this; + return m; } -#endif - void swap(upgrade_lock& other) + Mutex* release() BOOST_NOEXCEPT { - std::swap(m,other.m); - std::swap(is_locked,other.is_locked); + Mutex* const res=m; + m=0; + is_locked=false; + return res; } - ~upgrade_lock() { if(owns_lock()) @@ -845,42 +1073,90 @@ namespace boost } void lock() { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex")); + } if(owns_lock()) { - boost::throw_exception(boost::lock_error()); + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost upgrade_lock owns already the mutex")); } m->lock_upgrade(); is_locked=true; } bool try_lock() { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex")); + } if(owns_lock()) { - boost::throw_exception(boost::lock_error()); + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost upgrade_lock owns already the mutex")); } is_locked=m->try_lock_upgrade(); return is_locked; } void unlock() { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex")); + } if(!owns_lock()) { - boost::throw_exception(boost::lock_error()); + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost upgrade_lock doesn't own the mutex")); } m->unlock_upgrade(); is_locked=false; } - +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex")); + } + is_locked=m->try_lock_upgrade_for(rel_time); + return is_locked; + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(system::errc::operation_not_permitted, "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex")); + } + is_locked=m->try_lock_upgrade_until(abs_time); + return is_locked; + } +#endif +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) typedef void (upgrade_lock::*bool_type)(); - operator bool_type() const + operator bool_type() const BOOST_NOEXCEPT { return is_locked?&upgrade_lock::lock:0; } - bool operator!() const + bool operator!() const BOOST_NOEXCEPT { return !owns_lock(); } - bool owns_lock() const +#else + explicit operator bool() const BOOST_NOEXCEPT + { + return owns_lock(); + } +#endif + bool owns_lock() const BOOST_NOEXCEPT { return is_locked; } @@ -888,30 +1164,25 @@ namespace boost friend class unique_lock<Mutex>; }; - -#ifndef BOOST_NO_RVALUE_REFERENCES template<typename Mutex> - unique_lock<Mutex>::unique_lock(upgrade_lock<Mutex>&& other): - m(other.m),is_locked(other.is_locked) + void swap(upgrade_lock<Mutex>& lhs,upgrade_lock<Mutex>& rhs) BOOST_NOEXCEPT { - other.is_locked=false; - if(is_locked) - { - m->unlock_upgrade_and_lock(); - } + lhs.swap(rhs); } -#else + + BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END + template<typename Mutex> - unique_lock<Mutex>::unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other): - m(other->m),is_locked(other->is_locked) + unique_lock<Mutex>::unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other): + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) { - other->is_locked=false; if(is_locked) { m->unlock_upgrade_and_lock(); } + BOOST_THREAD_RV(other).release(); } -#endif + template <class Mutex> class upgrade_to_unique_lock { @@ -919,67 +1190,65 @@ namespace boost upgrade_lock<Mutex>* source; unique_lock<Mutex> exclusive; - explicit upgrade_to_unique_lock(upgrade_to_unique_lock&); - upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&); public: + typedef Mutex mutex_type; + BOOST_THREAD_MOVABLE_ONLY(upgrade_to_unique_lock) + explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_): - source(&m_),exclusive(move(*source)) + source(&m_),exclusive(::boost::move(*source)) {} ~upgrade_to_unique_lock() { if(source) { - *source=move(exclusive); + *source=BOOST_THREAD_MAKE_RV_REF(upgrade_lock<Mutex>(::boost::move(exclusive))); } } -#ifdef BOOST_HAS_RVALUE_REFS - upgrade_to_unique_lock(upgrade_to_unique_lock<Mutex>&& other): - source(other.source),exclusive(move(other.exclusive)) - { - other.source=0; - } - - upgrade_to_unique_lock& operator=(upgrade_to_unique_lock<Mutex>&& other) - { - upgrade_to_unique_lock temp(other); - swap(temp); - return *this; - } -#else - upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other): - source(other->source),exclusive(move(other->exclusive)) + upgrade_to_unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT: + source(BOOST_THREAD_RV(other).source),exclusive(::boost::move(BOOST_THREAD_RV(other).exclusive)) { - other->source=0; + BOOST_THREAD_RV(other).source=0; } - - upgrade_to_unique_lock& operator=(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other) + + upgrade_to_unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT { upgrade_to_unique_lock temp(other); swap(temp); return *this; } -#endif - void swap(upgrade_to_unique_lock& other) + + void swap(upgrade_to_unique_lock& other) BOOST_NOEXCEPT { std::swap(source,other.source); exclusive.swap(other.exclusive); } + +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&); - operator bool_type() const + operator bool_type() const BOOST_NOEXCEPT { return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0; } - bool operator!() const + bool operator!() const BOOST_NOEXCEPT { return !owns_lock(); } - bool owns_lock() const +#else + explicit operator bool() const BOOST_NOEXCEPT + { + return owns_lock(); + } +#endif + + bool owns_lock() const BOOST_NOEXCEPT { return exclusive.owns_lock(); } }; + BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_to_unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END + namespace detail { template<typename Mutex> @@ -988,9 +1257,11 @@ namespace boost { typedef unique_lock<Mutex> base; public: + BOOST_THREAD_MOVABLE_ONLY(try_lock_wrapper) + try_lock_wrapper() {} - + explicit try_lock_wrapper(Mutex& m): base(m,try_to_lock) {} @@ -1004,54 +1275,27 @@ namespace boost try_lock_wrapper(Mutex& m_,try_to_lock_t): base(m_,try_to_lock) {} -#ifndef BOOST_NO_RVALUE_REFERENCES - try_lock_wrapper(try_lock_wrapper&& other): - base(other.move()) +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other): + base(::boost::move(other)) {} - try_lock_wrapper&& move() - { - return static_cast<try_lock_wrapper&&>(*this); - } - - try_lock_wrapper& operator=(try_lock_wrapper<Mutex>&& other) - { - try_lock_wrapper temp(other.move()); - swap(temp); - return *this; - } +#elif defined BOOST_THREAD_USES_MOVE + try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other): + base(::boost::move(static_cast<base&>(other))) + {} - void swap(try_lock_wrapper&& other) - { - base::swap(other); - } #else - try_lock_wrapper(detail::thread_move_t<try_lock_wrapper<Mutex> > other): - base(detail::thread_move_t<base>(*other)) + try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other): + base(BOOST_THREAD_RV_REF(base)(*other)) {} - - operator detail::thread_move_t<try_lock_wrapper<Mutex> >() - { - return move(); - } - - detail::thread_move_t<try_lock_wrapper<Mutex> > move() - { - return detail::thread_move_t<try_lock_wrapper<Mutex> >(*this); - } - - try_lock_wrapper& operator=(detail::thread_move_t<try_lock_wrapper<Mutex> > other) +#endif + try_lock_wrapper& operator=(BOOST_THREAD_RV_REF_BEG try_lock_wrapper<Mutex> BOOST_THREAD_RV_REF_END other) { try_lock_wrapper temp(other); swap(temp); return *this; } - - void swap(detail::thread_move_t<try_lock_wrapper<Mutex> > other) - { - base::swap(*other); - } -#endif void swap(try_lock_wrapper& other) { base::swap(other); @@ -1080,32 +1324,31 @@ namespace boost { return base::release(); } - bool operator!() const - { - return !this->owns_lock(); - } +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) typedef typename base::bool_type bool_type; operator bool_type() const { return base::operator bool_type(); } + bool operator!() const + { + return !this->owns_lock(); + } +#else + explicit operator bool() const + { + return owns_lock(); + } +#endif }; -#ifndef BOOST_NO_RVALUE_REFERENCES - template<typename Mutex> - void swap(try_lock_wrapper<Mutex>&& lhs,try_lock_wrapper<Mutex>&& rhs) - { - lhs.swap(rhs); - } -#else template<typename Mutex> void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs) { lhs.swap(rhs); } -#endif - + template<typename MutexType1,typename MutexType2> unsigned try_lock_internal(MutexType1& m1,MutexType2& m2) { @@ -1234,7 +1477,7 @@ namespace boost template<bool x> struct is_mutex_type_wrapper {}; - + template<typename MutexType1,typename MutexType2> void lock_impl(MutexType1& m1,MutexType2& m2,is_mutex_type_wrapper<true>) { @@ -1262,7 +1505,7 @@ namespace boost template<typename Iterator> void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>); } - + template<typename MutexType1,typename MutexType2> void lock(MutexType1& m1,MutexType2& m2) @@ -1407,7 +1650,7 @@ namespace boost { typedef int type; }; - + template<typename Iterator> struct try_lock_impl_return<Iterator,false> { @@ -1423,7 +1666,7 @@ namespace boost template<typename Iterator> Iterator try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>); } - + template<typename MutexType1,typename MutexType2> typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1,MutexType2& m2) { @@ -1465,7 +1708,7 @@ namespace boost { return ((int)detail::try_lock_internal(m1,m2,m3,m4,m5))-1; } - + namespace detail { @@ -1474,13 +1717,13 @@ namespace boost { Iterator begin; Iterator end; - + range_lock_guard(Iterator begin_,Iterator end_): begin(begin_),end(end_) { - lock(begin,end); + boost::lock(begin,end); } - + void release() { begin=end; @@ -1505,21 +1748,21 @@ namespace boost } typedef typename std::iterator_traits<Iterator>::value_type lock_type; unique_lock<lock_type> guard(*begin,try_to_lock); - + if(!guard.owns_lock()) { return begin; } - Iterator const failed=try_lock(++begin,end); + Iterator const failed=boost::try_lock(++begin,end); if(failed==end) { guard.release(); } - + return failed; } } - + namespace detail { @@ -1527,7 +1770,7 @@ namespace boost void lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>) { typedef typename std::iterator_traits<Iterator>::value_type lock_type; - + if(begin==end) { return; @@ -1536,14 +1779,14 @@ namespace boost Iterator second=begin; ++second; Iterator next=second; - + for(;;) { unique_lock<lock_type> begin_lock(*begin,defer_lock); if(start_with_begin) { begin_lock.lock(); - Iterator const failed_lock=try_lock(next,end); + Iterator const failed_lock=boost::try_lock(next,end); if(failed_lock==end) { begin_lock.release(); @@ -1557,7 +1800,7 @@ namespace boost detail::range_lock_guard<Iterator> guard(next,end); if(begin_lock.try_lock()) { - Iterator const failed_lock=try_lock(second,next); + Iterator const failed_lock=boost::try_lock(second,next); if(failed_lock==next) { begin_lock.release(); @@ -1575,11 +1818,10 @@ namespace boost } } } - + } - -} +} #include <boost/config/abi_suffix.hpp> #endif diff --git a/3rdParty/Boost/src/boost/thread/once.hpp b/3rdParty/Boost/src/boost/thread/once.hpp index 975304e..acd216e 100644 --- a/3rdParty/Boost/src/boost/thread/once.hpp +++ b/3rdParty/Boost/src/boost/thread/once.hpp @@ -3,7 +3,7 @@ // once.hpp // -// (C) Copyright 2006-7 Anthony Williams +// (C) Copyright 2006-7 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -22,6 +22,8 @@ namespace boost { + // template<class Callable, class ...Args> void + // call_once(once_flag& flag, Callable&& func, Args&&... args); inline void call_once(void (*func)(),once_flag& flag) { call_once(flag,func); diff --git a/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp b/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp index 9c5bee2..aa71007 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp @@ -4,11 +4,17 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007-10 Anthony Williams +// (C) Copyright 2011 Vicente J. Botet Escriba -#include "timespec.hpp" -#include "pthread_mutex_scoped_lock.hpp" -#include "thread_data.hpp" -#include "condition_variable_fwd.hpp" +#include <boost/thread/pthread/timespec.hpp> +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> +#include <boost/thread/pthread/thread_data.hpp> +#include <boost/thread/pthread/condition_variable_fwd.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif +#include <boost/thread/detail/delete.hpp> #include <boost/config/abi_prefix.hpp> @@ -18,14 +24,14 @@ namespace boost { void BOOST_THREAD_DECL interruption_point(); } - + namespace thread_cv_detail { template<typename MutexType> struct lock_on_exit { MutexType* m; - + lock_on_exit(): m(0) {} @@ -44,66 +50,82 @@ namespace boost } }; } - + inline void condition_variable::wait(unique_lock<mutex>& m) { - thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; - detail::interruption_checker check_for_interruption(&internal_mutex,&cond); - guard.activate(m); - int const res=pthread_cond_wait(&cond,&internal_mutex); - BOOST_ASSERT(!res); + int res=0; + { + thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; + detail::interruption_checker check_for_interruption(&internal_mutex,&cond); + guard.activate(m); + do { + res = pthread_cond_wait(&cond,&internal_mutex); + } while (res == EINTR); + } this_thread::interruption_point(); + if(res) + { + boost::throw_exception(condition_error(res, "boost:: condition_variable constructor failed in pthread_cond_wait")); + } } - inline bool condition_variable::timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until) + inline bool condition_variable::do_timed_wait( + unique_lock<mutex>& m, + struct timespec const &timeout) { + if (!m.owns_lock()) + boost::throw_exception(condition_error(EPERM, "condition_variable do_timed_wait: mutex not locked")); + thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; - detail::interruption_checker check_for_interruption(&internal_mutex,&cond); - guard.activate(m); - struct timespec const timeout=detail::get_timespec(wait_until); - int const cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); + int cond_res; + { + detail::interruption_checker check_for_interruption(&internal_mutex,&cond); + guard.activate(m); + cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); + } this_thread::interruption_point(); if(cond_res==ETIMEDOUT) { return false; } - BOOST_ASSERT(!cond_res); + if(cond_res) + { + boost::throw_exception(condition_error(cond_res, "condition_variable failed in pthread_cond_timedwait")); + } return true; } - inline void condition_variable::notify_one() + inline void condition_variable::notify_one() BOOST_NOEXCEPT { boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); BOOST_VERIFY(!pthread_cond_signal(&cond)); } - - inline void condition_variable::notify_all() + + inline void condition_variable::notify_all() BOOST_NOEXCEPT { boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); BOOST_VERIFY(!pthread_cond_broadcast(&cond)); } - + class condition_variable_any { pthread_mutex_t internal_mutex; pthread_cond_t cond; - condition_variable_any(condition_variable_any&); - condition_variable_any& operator=(condition_variable_any&); - public: + BOOST_THREAD_NO_COPYABLE(condition_variable_any) condition_variable_any() { int const res=pthread_mutex_init(&internal_mutex,NULL); if(res) { - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_mutex_init")); } int const res2=pthread_cond_init(&cond,NULL); if(res2) { BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_cond_init")); } } ~condition_variable_any() @@ -111,7 +133,7 @@ namespace boost BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); BOOST_VERIFY(!pthread_cond_destroy(&cond)); } - + template<typename lock_type> void wait(lock_type& m) { @@ -121,11 +143,11 @@ namespace boost detail::interruption_checker check_for_interruption(&internal_mutex,&cond); guard.activate(m); res=pthread_cond_wait(&cond,&internal_mutex); - this_thread::interruption_point(); } + this_thread::interruption_point(); if(res) { - boost::throw_exception(condition_error()); + boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_wait")); } } @@ -134,28 +156,12 @@ namespace boost { while(!pred()) wait(m); } - + template<typename lock_type> bool timed_wait(lock_type& m,boost::system_time const& wait_until) { struct timespec const timeout=detail::get_timespec(wait_until); - int res=0; - { - thread_cv_detail::lock_on_exit<lock_type> guard; - detail::interruption_checker check_for_interruption(&internal_mutex,&cond); - guard.activate(m); - res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); - this_thread::interruption_point(); - } - if(res==ETIMEDOUT) - { - return false; - } - if(res) - { - boost::throw_exception(condition_error()); - } - return true; + return do_timed_wait(m, timeout); } template<typename lock_type> bool timed_wait(lock_type& m,xtime const& wait_until) @@ -192,17 +198,134 @@ namespace boost return timed_wait(m,get_system_time()+wait_duration,pred); } - void notify_one() +#ifdef BOOST_THREAD_USES_CHRONO + template <class lock_type,class Duration> + cv_status + wait_until( + lock_type& lock, + const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<system_clock, nanoseconds> nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + return system_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template <class lock_type, class Clock, class Duration> + cv_status + wait_until( + lock_type& lock, + const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + wait_until(lock, s_now + ceil<nanoseconds>(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; + } + + template <class lock_type, class Clock, class Duration, class Predicate> + bool + wait_until( + lock_type& lock, + const chrono::time_point<Clock, Duration>& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + + + template <class lock_type, class Rep, class Period> + cv_status + wait_for( + lock_type& lock, + const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, s_now + ceil<nanoseconds>(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + + } + + + template <class lock_type, class Rep, class Period, class Predicate> + bool + wait_for( + lock_type& lock, + const chrono::duration<Rep, Period>& d, + Predicate pred) + { + while (!pred()) + { + if (wait_for(lock, d) == cv_status::timeout) + return pred(); + } + return true; + } + + template <class lock_type> + inline void wait_until( + lock_type& lk, + chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts; + seconds s = duration_cast<seconds>(d); + ts.tv_sec = static_cast<long>(s.count()); + ts.tv_nsec = static_cast<long>((d - s).count()); + do_timed_wait(lk, ts); + } +#endif + + void notify_one() BOOST_NOEXCEPT { boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); BOOST_VERIFY(!pthread_cond_signal(&cond)); } - - void notify_all() + + void notify_all() BOOST_NOEXCEPT { boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); BOOST_VERIFY(!pthread_cond_broadcast(&cond)); } + private: // used by boost::thread::try_join_until + + template <class lock_type> + inline bool do_timed_wait( + lock_type& m, + struct timespec const &timeout) + { + int res=0; + { + thread_cv_detail::lock_on_exit<lock_type> guard; + detail::interruption_checker check_for_interruption(&internal_mutex,&cond); + guard.activate(m); + res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); + } + this_thread::interruption_point(); + if(res==ETIMEDOUT) + { + return false; + } + if(res) + { + boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_timedwait")); + } + return true; + } + + }; } diff --git a/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp b/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp index 365f511..dbb3892 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp @@ -4,47 +4,57 @@ // 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 Vicente J. Botet Escriba #include <boost/assert.hpp> #include <boost/throw_exception.hpp> #include <pthread.h> +#include <boost/thread/cv_status.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/locks.hpp> #include <boost/thread/thread_time.hpp> #include <boost/thread/xtime.hpp> - +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif +#include <boost/thread/detail/delete.hpp> +#include <boost/date_time/posix_time/posix_time_duration.hpp> #include <boost/config/abi_prefix.hpp> namespace boost { + class condition_variable { private: pthread_mutex_t internal_mutex; pthread_cond_t cond; - - condition_variable(condition_variable&); - condition_variable& operator=(condition_variable&); public: + BOOST_THREAD_NO_COPYABLE(condition_variable) condition_variable() { int const res=pthread_mutex_init(&internal_mutex,NULL); if(res) { - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res, "boost:: condition_variable constructor failed in pthread_mutex_init")); } int const res2=pthread_cond_init(&cond,NULL); if(res2) { BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res2, "boost:: condition_variable constructor failed in pthread_cond_init")); } } ~condition_variable() { BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); - BOOST_VERIFY(!pthread_cond_destroy(&cond)); + int ret; + do { + ret = pthread_cond_destroy(&cond); + } while (ret == EINTR); + BOOST_VERIFY(!ret); } void wait(unique_lock<mutex>& m); @@ -55,21 +65,38 @@ namespace boost while(!pred()) wait(m); } - inline bool timed_wait(unique_lock<mutex>& m, - boost::system_time const& wait_until); - bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until) + + inline bool timed_wait( + unique_lock<mutex>& m, + boost::system_time const& wait_until) + { +#if defined BOOST_THREAD_WAIT_BUG + struct timespec const timeout=detail::get_timespec(wait_until + BOOST_THREAD_WAIT_BUG); + return do_timed_wait(m, timeout); +#else + struct timespec const timeout=detail::get_timespec(wait_until); + return do_timed_wait(m, timeout); +#endif + } + bool timed_wait( + unique_lock<mutex>& m, + xtime const& wait_until) { return timed_wait(m,system_time(wait_until)); } template<typename duration_type> - bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration) + bool timed_wait( + unique_lock<mutex>& m, + duration_type const& wait_duration) { return timed_wait(m,get_system_time()+wait_duration); } template<typename predicate_type> - bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred) + bool timed_wait( + unique_lock<mutex>& m, + boost::system_time const& wait_until,predicate_type pred) { while (!pred()) { @@ -80,28 +107,133 @@ namespace boost } template<typename predicate_type> - bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until,predicate_type pred) + bool timed_wait( + unique_lock<mutex>& m, + xtime const& wait_until,predicate_type pred) { return timed_wait(m,system_time(wait_until),pred); } template<typename duration_type,typename predicate_type> - bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred) + bool timed_wait( + unique_lock<mutex>& m, + duration_type const& wait_duration,predicate_type pred) { return timed_wait(m,get_system_time()+wait_duration,pred); } +#ifdef BOOST_THREAD_USES_CHRONO + + template <class Duration> + cv_status + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<system_clock, nanoseconds> nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + return system_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template <class Clock, class Duration> + cv_status + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + wait_until(lock, s_now + ceil<nanoseconds>(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; + } + + template <class Clock, class Duration, class Predicate> + bool + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<Clock, Duration>& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + + + template <class Rep, class Period> + cv_status + wait_for( + unique_lock<mutex>& lock, + const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, s_now + ceil<nanoseconds>(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + + } + + + template <class Rep, class Period, class Predicate> + bool + wait_for( + unique_lock<mutex>& lock, + const chrono::duration<Rep, Period>& d, + Predicate pred) + { + while (!pred()) + { + if (wait_for(lock, d) == cv_status::timeout) + return pred(); + } + return true; + } +#endif + +#define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE typedef pthread_cond_t* native_handle_type; native_handle_type native_handle() { return &cond; } - void notify_one(); - void notify_all(); + void notify_one() BOOST_NOEXCEPT; + void notify_all() BOOST_NOEXCEPT; + +#ifdef BOOST_THREAD_USES_CHRONO + inline void wait_until( + unique_lock<mutex>& lk, + chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts; + seconds s = duration_cast<seconds>(d); + ts.tv_sec = static_cast<long>(s.count()); + ts.tv_nsec = static_cast<long>((d - s).count()); + do_timed_wait(lk, ts); + } +#endif + //private: // used by boost::thread::try_join_until + + inline bool do_timed_wait( + unique_lock<mutex>& lock, + struct timespec const &timeout); }; + + BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); } + #include <boost/config/abi_suffix.hpp> #endif diff --git a/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp index 2a326d7..2c5af92 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp @@ -1,12 +1,12 @@ #ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP #define BOOST_THREAD_PTHREAD_MUTEX_HPP // (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // 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 <pthread.h> -#include <boost/utility.hpp> #include <boost/throw_exception.hpp> #include <boost/thread/exceptions.hpp> #include <boost/thread/locks.hpp> @@ -14,11 +14,16 @@ #include <boost/thread/xtime.hpp> #include <boost/assert.hpp> #include <errno.h> -#include "timespec.hpp" -#include "pthread_mutex_scoped_lock.hpp" +#include <boost/thread/pthread/timespec.hpp> +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif +#include <boost/thread/detail/delete.hpp> #ifdef _POSIX_TIMEOUTS -#if _POSIX_TIMEOUTS >= 0 +#if _POSIX_TIMEOUTS >= 0 && _POSIX_C_SOURCE>=200112L #define BOOST_PTHREAD_HAS_TIMEDLOCK #endif #endif @@ -30,48 +35,70 @@ namespace boost class mutex { private: - mutex(mutex const&); - mutex& operator=(mutex const&); pthread_mutex_t m; public: + BOOST_THREAD_NO_COPYABLE(mutex) + mutex() { int const res=pthread_mutex_init(&m,NULL); if(res) { - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res, "boost:: mutex constructor failed in pthread_mutex_init")); } } ~mutex() { - BOOST_VERIFY(!pthread_mutex_destroy(&m)); + int ret; + do + { + ret = pthread_mutex_destroy(&m); + } while (ret == EINTR); } - + void lock() { - int const res=pthread_mutex_lock(&m); - if(res) + int res; + do + { + res = pthread_mutex_lock(&m); + } while (res == EINTR); + if (res) { - boost::throw_exception(lock_error(res)); + boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock")); } } void unlock() { - BOOST_VERIFY(!pthread_mutex_unlock(&m)); + int ret; + do + { + ret = pthread_mutex_unlock(&m); + } while (ret == EINTR); + BOOST_VERIFY(!ret); } - + bool try_lock() { - int const res=pthread_mutex_trylock(&m); + int res; + do + { + res = pthread_mutex_trylock(&m); + } while (res == EINTR); if(res && (res!=EBUSY)) { - boost::throw_exception(lock_error(res)); + // The following throw_exception has been replaced by an assertion and just return false, + // as this is an internal error and the user can do nothing with the exception. + //boost::throw_exception(lock_error(res,"boost: mutex try_lock failed in pthread_mutex_trylock")); + BOOST_ASSERT_MSG(false ,"boost: mutex try_lock failed in pthread_mutex_trylock"); + return false; } - + return !res; } +#define BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE typedef pthread_mutex_t* native_handle_type; native_handle_type native_handle() { @@ -87,28 +114,26 @@ namespace boost class timed_mutex { private: - timed_mutex(timed_mutex const&); - timed_mutex& operator=(timed_mutex const&); - private: pthread_mutex_t m; #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK pthread_cond_t cond; bool is_locked; #endif public: + BOOST_THREAD_NO_COPYABLE(timed_mutex) timed_mutex() { int const res=pthread_mutex_init(&m,NULL); if(res) { - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init")); } #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK int const res2=pthread_cond_init(&cond,NULL); if(res2) { BOOST_VERIFY(!pthread_mutex_destroy(&m)); - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init")); } is_locked=false; #endif @@ -141,26 +166,23 @@ namespace boost { BOOST_VERIFY(!pthread_mutex_unlock(&m)); } - + bool try_lock() { int const res=pthread_mutex_trylock(&m); BOOST_ASSERT(!res || res==EBUSY); return !res; } - bool timed_lock(system_time const & abs_time) - { - struct timespec const timeout=detail::get_timespec(abs_time); - int const res=pthread_mutex_timedlock(&m,&timeout); - BOOST_ASSERT(!res || res==ETIMEDOUT); - return !res; - } - typedef pthread_mutex_t* native_handle_type; - native_handle_type native_handle() + + private: + bool do_try_lock_until(struct timespec const &timeout) { - return &m; + int const res=pthread_mutex_timedlock(&m,&timeout); + BOOST_ASSERT(!res || res==ETIMEDOUT); + return !res; } + public: #else void lock() @@ -179,7 +201,7 @@ namespace boost is_locked=false; BOOST_VERIFY(!pthread_cond_signal(&cond)); } - + bool try_lock() { boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); @@ -191,9 +213,9 @@ namespace boost return true; } - bool timed_lock(system_time const & abs_time) + private: + bool do_try_lock_until(struct timespec const &timeout) { - struct timespec const timeout=detail::get_timespec(abs_time); boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); while(is_locked) { @@ -207,8 +229,55 @@ namespace boost is_locked=true; return true; } + public: #endif + bool timed_lock(system_time const & abs_time) + { + struct timespec const ts=detail::get_timespec(abs_time); + return do_try_lock_until(ts); + } + +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) + { + return try_lock_until(chrono::steady_clock::now() + rel_time); + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil<nanoseconds>(t - c_now)); + } + template <class Duration> + bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<system_clock, nanoseconds> nano_sys_tmpt; + return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts; + seconds s = duration_cast<seconds>(d); + ts.tv_sec = static_cast<long>(s.count()); + ts.tv_nsec = static_cast<long>((d - s).count()); + return do_try_lock_until(ts); + } +#endif + +#define BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE + typedef pthread_mutex_t* native_handle_type; + native_handle_type native_handle() + { + return &m; + } + typedef unique_lock<timed_mutex> scoped_timed_lock; typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock; typedef scoped_timed_lock scoped_lock; diff --git a/3rdParty/Boost/src/boost/thread/pthread/once.hpp b/3rdParty/Boost/src/boost/thread/pthread/once.hpp index 6321aa2..02c2732 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/once.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/once.hpp @@ -3,53 +3,86 @@ // once.hpp // -// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // // 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 <boost/thread/detail/config.hpp> -#include <boost/config.hpp> -#include <pthread.h> -#include <boost/assert.hpp> -#include "pthread_mutex_scoped_lock.hpp" #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> -#include <boost/cstdint.hpp> +#include <boost/thread/detail/delete.hpp> +#include <boost/detail/no_exceptions_support.hpp> +#include <boost/assert.hpp> #include <boost/config/abi_prefix.hpp> +#include <boost/cstdint.hpp> +#include <pthread.h> +#include <csignal> + namespace boost { +#define BOOST_ONCE_INITIAL_FLAG_VALUE 0 + + namespace thread_detail + { +//#ifdef SIG_ATOMIC_MAX +// typedef sig_atomic_t uintmax_atomic_t; +// #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C SIG_ATOMIC_MAX +//#else + typedef unsigned long uintmax_atomic_t; + #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(value) value##ul + #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(~0) +//#endif + } + +#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 + + struct once_flag + { + BOOST_THREAD_NO_COPYABLE(once_flag) + BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT + : epoch(BOOST_ONCE_INITIAL_FLAG_VALUE) + {} + private: + volatile thread_detail::uintmax_atomic_t epoch; + template<typename Function> + friend + void call_once(once_flag& flag,Function f); + }; + +#else // BOOST_THREAD_PROVIDES_ONCE_CXX11 + struct once_flag { - boost::uintmax_t epoch; + volatile thread_detail::uintmax_atomic_t epoch; }; +#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE} +#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11 + namespace detail { - BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch(); - BOOST_THREAD_DECL extern boost::uintmax_t once_global_epoch; + BOOST_THREAD_DECL thread_detail::uintmax_atomic_t& get_once_per_thread_epoch(); + BOOST_THREAD_DECL extern thread_detail::uintmax_atomic_t once_global_epoch; BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex; BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv; } - -#define BOOST_ONCE_INITIAL_FLAG_VALUE 0 -#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE} - // Based on Mike Burrows fast_pthread_once algorithm as described in // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html template<typename Function> void call_once(once_flag& flag,Function f) { - static boost::uintmax_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; - static boost::uintmax_t const being_initialized=uninitialized_flag+1; - boost::uintmax_t const epoch=flag.epoch; - boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch(); - + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=detail::get_once_per_thread_epoch(); + if(epoch<this_thread_epoch) { pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex); @@ -59,21 +92,18 @@ namespace boost if(flag.epoch==uninitialized_flag) { flag.epoch=being_initialized; -#ifndef BOOST_NO_EXCEPTIONS - try + BOOST_TRY { -#endif pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex); f(); -#ifndef BOOST_NO_EXCEPTIONS } - catch(...) + BOOST_CATCH (...) { flag.epoch=uninitialized_flag; BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv)); - throw; + BOOST_RETHROW } -#endif + BOOST_CATCH_END flag.epoch=--detail::once_global_epoch; BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv)); } diff --git a/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp index 4158a57..2a6bc7d 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp @@ -1,12 +1,12 @@ #ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP #define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP // (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // 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 <pthread.h> -#include <boost/utility.hpp> #include <boost/throw_exception.hpp> #include <boost/thread/exceptions.hpp> #include <boost/thread/locks.hpp> @@ -17,8 +17,13 @@ #endif #include <boost/date_time/posix_time/conversion.hpp> #include <errno.h> -#include "timespec.hpp" -#include "pthread_mutex_scoped_lock.hpp" +#include <boost/thread/pthread/timespec.hpp> +#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif +#include <boost/thread/detail/delete.hpp> #ifdef _POSIX_TIMEOUTS #if _POSIX_TIMEOUTS >= 0 @@ -26,7 +31,7 @@ #endif #endif -#if defined(BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK) +#if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK) #define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK #endif @@ -37,51 +42,50 @@ namespace boost class recursive_mutex { private: - recursive_mutex(recursive_mutex const&); - recursive_mutex& operator=(recursive_mutex const&); pthread_mutex_t m; -#ifndef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE +#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE pthread_cond_t cond; bool is_locked; pthread_t owner; unsigned count; #endif public: + BOOST_THREAD_NO_COPYABLE(recursive_mutex) recursive_mutex() { -#ifdef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE +#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE pthread_mutexattr_t attr; - + int const init_attr_res=pthread_mutexattr_init(&attr); if(init_attr_res) { - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_init")); } int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); if(set_attr_res) { BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_settype")); } - + int const res=pthread_mutex_init(&m,&attr); if(res) { BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init")); } BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); #else int const res=pthread_mutex_init(&m,NULL); if(res) { - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init")); } int const res2=pthread_cond_init(&cond,NULL); if(res2) { BOOST_VERIFY(!pthread_mutex_destroy(&m)); - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init")); } is_locked=false; count=0; @@ -90,12 +94,12 @@ namespace boost ~recursive_mutex() { BOOST_VERIFY(!pthread_mutex_destroy(&m)); -#ifndef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE +#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE BOOST_VERIFY(!pthread_cond_destroy(&cond)); #endif } -#ifdef BOOST_PTHREAD_HAS_MUTEXATTR_SETTYPE +#ifdef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE void lock() { BOOST_VERIFY(!pthread_mutex_lock(&m)); @@ -105,13 +109,14 @@ namespace boost { BOOST_VERIFY(!pthread_mutex_unlock(&m)); } - - bool try_lock() + + bool try_lock() BOOST_NOEXCEPT { int const res=pthread_mutex_trylock(&m); BOOST_ASSERT(!res || res==EBUSY); return !res; } +#define BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE typedef pthread_mutex_t* native_handle_type; native_handle_type native_handle() { @@ -127,7 +132,7 @@ namespace boost ++count; return; } - + while(is_locked) { BOOST_VERIFY(!pthread_cond_wait(&cond,&m)); @@ -146,7 +151,7 @@ namespace boost } BOOST_VERIFY(!pthread_cond_signal(&cond)); } - + bool try_lock() { boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); @@ -171,9 +176,6 @@ namespace boost class recursive_timed_mutex { private: - recursive_timed_mutex(recursive_timed_mutex const&); - recursive_timed_mutex& operator=(recursive_timed_mutex const&); - private: pthread_mutex_t m; #ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK pthread_cond_t cond; @@ -182,40 +184,41 @@ namespace boost unsigned count; #endif public: + BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex) recursive_timed_mutex() { #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK pthread_mutexattr_t attr; - + int const init_attr_res=pthread_mutexattr_init(&attr); if(init_attr_res) { - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_init")); } int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); if(set_attr_res) { - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_settype")); } - + int const res=pthread_mutex_init(&m,&attr); if(res) { BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init")); } BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); #else int const res=pthread_mutex_init(&m,NULL); if(res) { - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init")); } int const res2=pthread_cond_init(&cond,NULL); if(res2) { BOOST_VERIFY(!pthread_mutex_destroy(&m)); - boost::throw_exception(thread_resource_error()); + boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init")); } is_locked=false; count=0; @@ -245,26 +248,22 @@ namespace boost { BOOST_VERIFY(!pthread_mutex_unlock(&m)); } - + bool try_lock() { int const res=pthread_mutex_trylock(&m); BOOST_ASSERT(!res || res==EBUSY); return !res; } - bool timed_lock(system_time const & abs_time) + private: + bool do_try_lock_until(struct timespec const &timeout) { - struct timespec const timeout=detail::get_timespec(abs_time); int const res=pthread_mutex_timedlock(&m,&timeout); BOOST_ASSERT(!res || res==ETIMEDOUT); return !res; } - typedef pthread_mutex_t* native_handle_type; - native_handle_type native_handle() - { - return &m; - } + public: #else void lock() @@ -275,7 +274,7 @@ namespace boost ++count; return; } - + while(is_locked) { BOOST_VERIFY(!pthread_cond_wait(&cond,&m)); @@ -294,8 +293,8 @@ namespace boost } BOOST_VERIFY(!pthread_cond_signal(&cond)); } - - bool try_lock() + + bool try_lock() BOOST_NOEXCEPT { boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); if(is_locked && !pthread_equal(owner,pthread_self())) @@ -308,9 +307,9 @@ namespace boost return true; } - bool timed_lock(system_time const & abs_time) + private: + bool do_try_lock_until(struct timespec const &timeout) { - struct timespec const timeout=detail::get_timespec(abs_time); boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); if(is_locked && pthread_equal(owner,pthread_self())) { @@ -331,8 +330,56 @@ namespace boost owner=pthread_self(); return true; } + public: + #endif + bool timed_lock(system_time const & abs_time) + { + struct timespec const ts=detail::get_timespec(abs_time); + return do_try_lock_until(ts); + } + +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) + { + return try_lock_until(chrono::steady_clock::now() + rel_time); + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil<nanoseconds>(t - c_now)); + } + template <class Duration> + bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<system_clock, nanoseconds> nano_sys_tmpt; + return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts; + seconds s = duration_cast<seconds>(d); + ts.tv_sec = static_cast<long>(s.count()); + ts.tv_nsec = static_cast<long>((d - s).count()); + return do_try_lock_until(ts); + } +#endif + +#define BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE + typedef pthread_mutex_t* native_handle_type; + native_handle_type native_handle() + { + return &m; + } + typedef unique_lock<recursive_timed_mutex> scoped_timed_lock; typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock; typedef scoped_timed_lock scoped_lock; diff --git a/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp index bc26282..cf45188 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp @@ -2,6 +2,7 @@ #define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP // (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -12,6 +13,11 @@ #include <boost/thread/mutex.hpp> #include <boost/thread/condition_variable.hpp> #include <boost/thread/detail/thread_interruption.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif +#include <boost/thread/detail/delete.hpp> #include <boost/config/abi_prefix.hpp> @@ -27,7 +33,7 @@ namespace boost bool upgrade; bool exclusive_waiting_blocked; }; - + state_data state; @@ -41,9 +47,10 @@ namespace boost exclusive_cond.notify_one(); shared_cond.notify_all(); } - public: + BOOST_THREAD_NO_COPYABLE(shared_mutex) + shared_mutex() { state_data state_={0,0,0,0}; @@ -58,7 +65,7 @@ namespace boost { boost::this_thread::disable_interruption do_not_disturb; boost::mutex::scoped_lock lk(state_change); - + while(state.exclusive || state.exclusive_waiting_blocked) { shared_cond.wait(lk); @@ -69,7 +76,7 @@ namespace boost bool try_lock_shared() { boost::mutex::scoped_lock lk(state_change); - + if(state.exclusive || state.exclusive_waiting_blocked) { return false; @@ -85,7 +92,7 @@ namespace boost { boost::this_thread::disable_interruption do_not_disturb; boost::mutex::scoped_lock lk(state_change); - + while(state.exclusive || state.exclusive_waiting_blocked) { if(!shared_cond.timed_wait(lk,timeout)) @@ -102,12 +109,34 @@ namespace boost { return timed_lock_shared(get_system_time()+relative_time); } +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time) + { + return try_lock_shared_until(chrono::steady_clock::now() + rel_time); + } + template <class Clock, class Duration> + bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time) + { + boost::this_thread::disable_interruption do_not_disturb; + boost::mutex::scoped_lock lk(state_change); + while(state.exclusive || state.exclusive_waiting_blocked) + { + if(cv_status::timeout==shared_cond.wait_until(lk,abs_time)) + { + return false; + } + } + ++state.shared_count; + return true; + } +#endif void unlock_shared() { boost::mutex::scoped_lock lk(state_change); bool const last_reader=!--state.shared_count; - + if(last_reader) { if(state.upgrade) @@ -128,7 +157,7 @@ namespace boost { boost::this_thread::disable_interruption do_not_disturb; boost::mutex::scoped_lock lk(state_change); - + while(state.shared_count || state.exclusive) { state.exclusive_waiting_blocked=true; @@ -150,7 +179,7 @@ namespace boost if(state.shared_count || state.exclusive) { state.exclusive_waiting_blocked=false; - exclusive_cond.notify_one(); + release_waiters(); return false; } break; @@ -166,10 +195,41 @@ namespace boost return timed_lock(get_system_time()+relative_time); } +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) + { + return try_lock_until(chrono::steady_clock::now() + rel_time); + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time) + { + boost::this_thread::disable_interruption do_not_disturb; + boost::mutex::scoped_lock lk(state_change); + + while(state.shared_count || state.exclusive) + { + state.exclusive_waiting_blocked=true; + if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time)) + { + if(state.shared_count || state.exclusive) + { + state.exclusive_waiting_blocked=false; + release_waiters(); + return false; + } + break; + } + } + state.exclusive=true; + return true; + } +#endif + bool try_lock() { boost::mutex::scoped_lock lk(state_change); - + if(state.shared_count || state.exclusive) { return false; @@ -179,7 +239,7 @@ namespace boost state.exclusive=true; return true; } - + } void unlock() @@ -228,6 +288,33 @@ namespace boost return timed_lock_upgrade(get_system_time()+relative_time); } +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time) + { + return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time); + } + template <class Clock, class Duration> + bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time) + { + boost::this_thread::disable_interruption do_not_disturb; + boost::mutex::scoped_lock lk(state_change); + while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + if(cv_status::timeout == shared_cond.wait_until(lk,abs_time)) + { + if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + return false; + } + break; + } + } + ++state.shared_count; + state.upgrade=true; + return true; + } +#endif bool try_lock_upgrade() { boost::mutex::scoped_lock lk(state_change); @@ -248,14 +335,17 @@ namespace boost boost::mutex::scoped_lock lk(state_change); state.upgrade=false; bool const last_reader=!--state.shared_count; - + if(last_reader) { state.exclusive_waiting_blocked=false; release_waiters(); + } else { + shared_cond.notify_all(); } } + // Upgrade <-> Exclusive void unlock_upgrade_and_lock() { boost::this_thread::disable_interruption do_not_disturb; @@ -278,7 +368,58 @@ namespace boost state.exclusive_waiting_blocked=false; release_waiters(); } - + + bool try_unlock_upgrade_and_lock() + { + boost::mutex::scoped_lock lk(state_change); + if( !state.exclusive + && !state.exclusive_waiting_blocked + && state.upgrade + && state.shared_count==1) + { + state.shared_count=0; + state.exclusive=true; + state.upgrade=false; + return true; + } + return false; + } +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool + try_unlock_upgrade_and_lock_for( + const chrono::duration<Rep, Period>& rel_time) + { + return try_unlock_upgrade_and_lock_until( + chrono::steady_clock::now() + rel_time); + } + template <class Clock, class Duration> + bool + try_unlock_upgrade_and_lock_until( + const chrono::time_point<Clock, Duration>& abs_time) + { + boost::this_thread::disable_interruption do_not_disturb; + boost::mutex::scoped_lock lk(state_change); + if (state.shared_count != 1) + { + for (;;) + { + cv_status status = shared_cond.wait_until(lk,abs_time); + if (state.shared_count == 1) + break; + if(status == cv_status::timeout) + return false; + } + } + state.upgrade=false; + state.exclusive=true; + state.exclusive_waiting_blocked=false; + state.shared_count=0; + return true; + } +#endif + + // Shared <-> Exclusive void unlock_and_lock_shared() { boost::mutex::scoped_lock lk(state_change); @@ -287,7 +428,59 @@ namespace boost state.exclusive_waiting_blocked=false; release_waiters(); } - + +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + bool try_unlock_shared_and_lock() + { + boost::mutex::scoped_lock lk(state_change); + if( !state.exclusive + && !state.exclusive_waiting_blocked + && !state.upgrade + && state.shared_count==1) + { + state.shared_count=0; + state.exclusive=true; + return true; + } + return false; + } +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool + try_unlock_shared_and_lock_for( + const chrono::duration<Rep, Period>& rel_time) + { + return try_unlock_shared_and_lock_until( + chrono::steady_clock::now() + rel_time); + } + template <class Clock, class Duration> + bool + try_unlock_shared_and_lock_until( + const chrono::time_point<Clock, Duration>& abs_time) + { + boost::this_thread::disable_interruption do_not_disturb; + boost::mutex::scoped_lock lk(state_change); + if (state.shared_count != 1) + { + for (;;) + { + cv_status status = shared_cond.wait_until(lk,abs_time); + if (state.shared_count == 1) + break; + if(status == cv_status::timeout) + return false; + } + } + state.upgrade=false; + state.exclusive=true; + state.exclusive_waiting_blocked=false; + state.shared_count=0; + return true; + } +#endif +#endif + + // Shared <-> Upgrade void unlock_upgrade_and_lock_shared() { boost::mutex::scoped_lock lk(state_change); @@ -295,7 +488,62 @@ namespace boost state.exclusive_waiting_blocked=false; release_waiters(); } + +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + bool try_unlock_shared_and_lock_upgrade() + { + boost::mutex::scoped_lock lk(state_change); + if( !state.exclusive + && !state.exclusive_waiting_blocked + && !state.upgrade + ) + { + state.upgrade=true; + return true; + } + return false; + } +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool + try_unlock_shared_and_lock_upgrade_for( + const chrono::duration<Rep, Period>& rel_time) + { + return try_unlock_shared_and_lock_upgrade_until( + chrono::steady_clock::now() + rel_time); + } + template <class Clock, class Duration> + bool + try_unlock_shared_and_lock_upgrade_until( + const chrono::time_point<Clock, Duration>& abs_time) + { + boost::this_thread::disable_interruption do_not_disturb; + boost::mutex::scoped_lock lk(state_change); + if( state.exclusive + || state.exclusive_waiting_blocked + || state.upgrade + ) + { + for (;;) + { + cv_status status = exclusive_cond.wait_until(lk,abs_time); + if( ! state.exclusive + && ! state.exclusive_waiting_blocked + && ! state.upgrade + ) + break; + if(status == cv_status::timeout) + return false; + } + } + state.upgrade=true; + return true; + } +#endif +#endif }; + + typedef shared_mutex upgrade_mutex; } #include <boost/config/abi_suffix.hpp> diff --git a/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp b/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp index 1bee28b..db4e09f 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp @@ -4,24 +4,77 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba #include <boost/thread/detail/config.hpp> #include <boost/thread/exceptions.hpp> +#include <boost/thread/locks.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/pthread/condition_variable_fwd.hpp> + #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> -#include <boost/thread/mutex.hpp> #include <boost/optional.hpp> -#include <pthread.h> #include <boost/assert.hpp> -#include "condition_variable_fwd.hpp" +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#endif + #include <map> +#include <vector> +#include <utility> + +#include <pthread.h> +#include <unistd.h> #include <boost/config/abi_prefix.hpp> namespace boost { + class thread_attributes { + public: + thread_attributes() BOOST_NOEXCEPT { + int res = pthread_attr_init(&val_); + BOOST_VERIFY(!res && "pthread_attr_init failed"); + } + ~thread_attributes() { + int res = pthread_attr_destroy(&val_); + BOOST_VERIFY(!res && "pthread_attr_destroy failed"); + } + // stack + void set_stack_size(std::size_t size) BOOST_NOEXCEPT { + if (size==0) return; + std::size_t page_size = getpagesize(); +#ifdef PTHREAD_STACK_MIN + if (size<PTHREAD_STACK_MIN) size=PTHREAD_STACK_MIN; +#endif + size = ((size+page_size-1)/page_size)*page_size; + int res = pthread_attr_setstacksize(&val_, size); + BOOST_VERIFY(!res && "pthread_attr_setstacksize failed"); + } + + std::size_t get_stack_size() const BOOST_NOEXCEPT { + std::size_t size; + int res = pthread_attr_getstacksize(&val_, &size); + BOOST_VERIFY(!res && "pthread_attr_getstacksize failed"); + return size; + } +#define BOOST_THREAD_DEFINES_THREAD_ATTRIBUTES_NATIVE_HANDLE + + typedef pthread_attr_t native_handle_type; + native_handle_type* native_handle() BOOST_NOEXCEPT { + return &val_; + } + const native_handle_type* native_handle() const BOOST_NOEXCEPT { + return &val_; + } + + private: + pthread_attr_t val_; + }; + class thread; - + namespace detail { struct tss_cleanup_function; @@ -39,7 +92,7 @@ namespace boost struct thread_data_base; typedef boost::shared_ptr<thread_data_base> thread_data_ptr; - + struct BOOST_THREAD_DECL thread_data_base: enable_shared_from_this<thread_data_base> { @@ -58,19 +111,28 @@ namespace boost bool interrupt_requested; pthread_mutex_t* cond_mutex; pthread_cond_t* current_cond; + typedef std::vector<std::pair<condition_variable*, mutex*> + //, hidden_allocator<std::pair<condition_variable*, mutex*> > + > notify_list_t; + notify_list_t notify; thread_data_base(): done(false),join_started(false),joined(false), thread_exit_callbacks(0), interrupt_enabled(true), interrupt_requested(false), - current_cond(0) + current_cond(0), + notify() {} virtual ~thread_data_base(); typedef pthread_t native_handle_type; virtual void run()=0; + void notify_all_at_thread_exit(condition_variable* cv, mutex* m) + { + notify.push_back(std::pair<condition_variable*, mutex*>(cv, m)); + } }; BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); @@ -83,13 +145,15 @@ namespace boost void check_for_interruption() { +#ifndef BOOST_NO_EXCEPTIONS if(thread_info->interrupt_requested) { thread_info->interrupt_requested=false; - throw thread_interrupted(); + throw thread_interrupted(); // BOOST_NO_EXCEPTIONS protected } +#endif } - + void operator=(interruption_checker&); public: explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond): @@ -128,15 +192,66 @@ namespace boost namespace this_thread { - void BOOST_THREAD_DECL yield(); - - void BOOST_THREAD_DECL sleep(system_time const& abs_time); - +#ifdef BOOST_THREAD_USES_CHRONO + inline + void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) + { + using namespace chrono; + boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data(); + + if(thread_info) + { + unique_lock<mutex> lk(thread_info->sleep_mutex); + while(cv_status::no_timeout==thread_info->sleep_condition.wait_for(lk,ns)) {} + } + else + { + if (ns >= nanoseconds::zero()) + { + + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) + timespec ts; + ts.tv_sec = static_cast<long>(duration_cast<seconds>(ns).count()); + ts.tv_nsec = static_cast<long>((ns - seconds(ts.tv_sec)).count()); + BOOST_VERIFY(!pthread_delay_np(&ts)); + # elif defined(BOOST_HAS_NANOSLEEP) + timespec ts; + ts.tv_sec = static_cast<long>(duration_cast<seconds>(ns).count()); + ts.tv_nsec = static_cast<long>((ns - seconds(ts.tv_sec)).count()); + // nanosleep takes a timespec that is an offset, not + // an absolute time. + nanosleep(&ts, 0); + # else + mutex mx; + mutex::scoped_lock lock(mx); + condition_variable cond; + cond.wait_for(lock, ns); + # endif + } + } + } +#endif + void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; + +#ifdef __DECXXX + /// Workaround of DECCXX issue of incorrect template substitution template<typename TimeDuration> inline void sleep(TimeDuration const& rel_time) { this_thread::sleep(get_system_time()+rel_time); } + + template<> + void BOOST_THREAD_DECL sleep(system_time const& abs_time); +#else + void BOOST_THREAD_DECL sleep(system_time const& abs_time); + + template<typename TimeDuration> + inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) + { + this_thread::sleep(get_system_time()+rel_time); + } +#endif } } diff --git a/3rdParty/Boost/src/boost/thread/pthread/thread_heap_alloc.hpp b/3rdParty/Boost/src/boost/thread/pthread/thread_heap_alloc.hpp index 737c298..7828318 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/thread_heap_alloc.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/thread_heap_alloc.hpp @@ -17,7 +17,7 @@ namespace boost return new T(); } -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template<typename T,typename A1> inline T* heap_new(A1&& a1) { @@ -72,7 +72,7 @@ namespace boost { return heap_new_impl<T,A1&>(a1); } - + template<typename T,typename A1,typename A2> inline T* heap_new(A1 const& a1,A2 const& a2) { @@ -218,8 +218,8 @@ namespace boost { return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4); } - -#endif + +#endif template<typename T> inline void heap_delete(T* data) { diff --git a/3rdParty/Boost/src/boost/thread/shared_mutex.hpp b/3rdParty/Boost/src/boost/thread/shared_mutex.hpp index 51eda0d..e85e269 100644 --- a/3rdParty/Boost/src/boost/thread/shared_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/shared_mutex.hpp @@ -3,15 +3,20 @@ // shared_mutex.hpp // -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // // 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 <boost/thread/detail/platform.hpp> +#include <boost/thread/detail/config.hpp> #if defined(BOOST_THREAD_PLATFORM_WIN32) +#if defined(BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN) +#include <boost/thread/pthread/shared_mutex.hpp> +#else #include <boost/thread/win32/shared_mutex.hpp> +#endif #elif defined(BOOST_THREAD_PLATFORM_PTHREAD) #include <boost/thread/pthread/shared_mutex.hpp> #else diff --git a/3rdParty/Boost/src/boost/thread/thread.hpp b/3rdParty/Boost/src/boost/thread/thread.hpp index fdfdadc..ee15c6e 100644 --- a/3rdParty/Boost/src/boost/thread/thread.hpp +++ b/3rdParty/Boost/src/boost/thread/thread.hpp @@ -3,7 +3,7 @@ // thread.hpp // -// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2007-8 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -22,6 +22,7 @@ #include <boost/thread/detail/thread.hpp> #include <boost/thread/detail/thread_interruption.hpp> #include <boost/thread/detail/thread_group.hpp> +#include <boost/thread/v2/thread.hpp> #endif diff --git a/3rdParty/Boost/src/boost/thread/v2/thread.hpp b/3rdParty/Boost/src/boost/thread/v2/thread.hpp new file mode 100644 index 0000000..d686c5f --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/v2/thread.hpp @@ -0,0 +1,56 @@ +// 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 2011 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_V2_THREAD_HPP +#define BOOST_THREAD_V2_THREAD_HPP + +#include <boost/thread/detail/config.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#endif +#include <boost/thread/condition_variable.hpp> +#include <boost/thread/locks.hpp> + +namespace boost +{ + namespace this_thread + { + +#ifdef BOOST_THREAD_USES_CHRONO + + template <class Rep, class Period> + void sleep_for(const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + nanoseconds ns = duration_cast<nanoseconds> (d); + if (ns < d) ++ns; + sleep_for(ns); + } + + template <class Clock, class Duration> + void sleep_until(const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + mutex mut; + condition_variable cv; + unique_lock<mutex> lk(mut); + while (Clock::now() < t) + cv.wait_until(lk, t); + } + + template <class Duration> + inline BOOST_SYMBOL_VISIBLE + void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t) + { + using namespace chrono; + sleep_for(t - steady_clock::now()); + } + +#endif + } +} + + +#endif diff --git a/3rdParty/Boost/src/boost/thread/win32/basic_recursive_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/basic_recursive_mutex.hpp index 05eb8d7..e259121 100644 --- a/3rdParty/Boost/src/boost/thread/win32/basic_recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/basic_recursive_mutex.hpp @@ -3,14 +3,19 @@ // basic_recursive_mutex.hpp // -// (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // // 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 "thread_primitives.hpp" -#include "basic_timed_mutex.hpp" +#include <boost/thread/win32/thread_primitives.hpp> +#include <boost/thread/win32/basic_timed_mutex.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif #include <boost/config/abi_prefix.hpp> @@ -37,12 +42,12 @@ namespace boost mutex.destroy(); } - bool try_lock() + bool try_lock() BOOST_NOEXCEPT { long const current_thread_id=win32::GetCurrentThreadId(); return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id); } - + void lock() { long const current_thread_id=win32::GetCurrentThreadId(); @@ -64,6 +69,20 @@ namespace boost return timed_lock(get_system_time()+timeout); } +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_timed_lock_for(current_thread_id,rel_time); + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& t) + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_timed_lock_until(current_thread_id,t); + } +#endif void unlock() { if(!--recursion_count) @@ -74,7 +93,7 @@ namespace boost } private: - bool try_recursive_lock(long current_thread_id) + bool try_recursive_lock(long current_thread_id) BOOST_NOEXCEPT { if(::boost::detail::interlocked_read_acquire(&locking_thread_id)==current_thread_id) { @@ -83,8 +102,8 @@ namespace boost } return false; } - - bool try_basic_lock(long current_thread_id) + + bool try_basic_lock(long current_thread_id) BOOST_NOEXCEPT { if(mutex.try_lock()) { @@ -94,7 +113,7 @@ namespace boost } return false; } - + bool try_timed_lock(long current_thread_id,::boost::system_time const& target) { if(mutex.timed_lock(target)) @@ -105,7 +124,28 @@ namespace boost } return false; } - + template <typename TP> + bool try_timed_lock_until(long current_thread_id,TP const& target) + { + if(mutex.try_lock_until(target)) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + return false; + } + template <typename D> + bool try_timed_lock_for(long current_thread_id,D const& target) + { + if(mutex.try_lock_for(target)) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + return false; + } }; typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_mutex; diff --git a/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp index 7c6797d..6a43077 100644 --- a/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp @@ -3,19 +3,23 @@ // basic_timed_mutex_win32.hpp // -// (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // // 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 <boost/assert.hpp> -#include "thread_primitives.hpp" -#include "interlocked_read.hpp" +#include <boost/thread/win32/thread_primitives.hpp> +#include <boost/thread/win32/interlocked_read.hpp> #include <boost/thread/thread_time.hpp> #include <boost/thread/xtime.hpp> #include <boost/detail/interlocked.hpp> - +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif #include <boost/config/abi_prefix.hpp> namespace boost @@ -52,13 +56,13 @@ namespace boost win32::CloseHandle(old_event); } } - - - bool try_lock() + + + bool try_lock() BOOST_NOEXCEPT { return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit); } - + void lock() { if(try_lock()) @@ -112,8 +116,8 @@ namespace boost old_count=current; } } - - + + bool timed_lock(::boost::system_time const& wait_until) { if(try_lock()) @@ -143,6 +147,7 @@ namespace boost return true; } + template<typename Duration> bool timed_lock(Duration const& timeout) { @@ -154,6 +159,59 @@ namespace boost return timed_lock(system_time(timeout)); } +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) + { + return try_lock_until(chrono::steady_clock::now() + rel_time); + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now)); + } + template <class Duration> + bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt; + return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp) + { + if(try_lock()) + { + return true; + } + long old_count=active_count; + mark_waiting_and_try_lock(old_count); + + if(old_count&lock_flag_value) + { + bool lock_acquired=false; + void* const sem=get_event(); + + do + { + chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now()); + + if(win32::WaitForSingleObject(sem,static_cast<unsigned long>(rel_time.count()))!=0) + { + BOOST_INTERLOCKED_DECREMENT(&active_count); + return false; + } + clear_waiting_and_try_lock(old_count); + lock_acquired=!(old_count&lock_flag_value); + } + while(!lock_acquired); + } + return true; + } +#endif + void unlock() { long const offset=lock_flag_value; @@ -171,7 +229,7 @@ namespace boost void* get_event() { void* current_event=::boost::detail::interlocked_read_acquire(&event); - + if(!current_event) { void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset); @@ -196,9 +254,9 @@ namespace boost } return current_event; } - + }; - + } } diff --git a/3rdParty/Boost/src/boost/thread/win32/condition_variable.hpp b/3rdParty/Boost/src/boost/thread/win32/condition_variable.hpp index 6e676b4..4c893ad 100644 --- a/3rdParty/Boost/src/boost/thread/win32/condition_variable.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/condition_variable.hpp @@ -4,18 +4,28 @@ // 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 +#include <boost/thread/win32/thread_primitives.hpp> +#include <boost/thread/win32/thread_data.hpp> +#include <boost/thread/win32/thread_data.hpp> +#include <boost/thread/win32/interlocked_read.hpp> +#include <boost/thread/cv_status.hpp> +#include <boost/thread/xtime.hpp> #include <boost/thread/mutex.hpp> -#include "thread_primitives.hpp" -#include <limits.h> +#include <boost/thread/thread_time.hpp> + #include <boost/assert.hpp> +#include <boost/intrusive_ptr.hpp> + +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif + +#include <limits.h> #include <algorithm> -#include <boost/thread/thread.hpp> -#include <boost/thread/thread_time.hpp> -#include "interlocked_read.hpp" -#include <boost/thread/xtime.hpp> #include <vector> -#include <boost/intrusive_ptr.hpp> #include <boost/config/abi_prefix.hpp> @@ -26,7 +36,7 @@ namespace boost class basic_cv_list_entry; void intrusive_ptr_add_ref(basic_cv_list_entry * p); void intrusive_ptr_release(basic_cv_list_entry * p); - + class basic_cv_list_entry { private: @@ -36,10 +46,8 @@ namespace boost bool notified; long references; - basic_cv_list_entry(basic_cv_list_entry&); - void operator=(basic_cv_list_entry&); - public: + BOOST_THREAD_NO_COPYABLE(basic_cv_list_entry) explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_): semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)), wake_sem(wake_sem_.duplicate()), @@ -55,7 +63,7 @@ namespace boost { BOOST_INTERLOCKED_INCREMENT(&waiters); } - + void remove_waiter() { BOOST_INTERLOCKED_DECREMENT(&waiters); @@ -77,9 +85,9 @@ namespace boost return notified; } - bool wait(timeout wait_until) + bool wait(timeout abs_time) { - return this_thread::interruptible_wait(semaphore,wait_until); + return this_thread::interruptible_wait(semaphore,abs_time); } bool woken() @@ -97,7 +105,7 @@ namespace boost { BOOST_INTERLOCKED_INCREMENT(&p->references); } - + inline void intrusive_ptr_release(basic_cv_list_entry * p) { if(!BOOST_INTERLOCKED_DECREMENT(&p->references)) @@ -125,13 +133,14 @@ namespace boost detail::interlocked_write_release(&total_count,total_count-count_to_wake); detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0); } - + template<typename lock_type> struct relocker { + BOOST_THREAD_NO_COPYABLE(relocker) lock_type& lock; bool unlocked; - + relocker(lock_type& lock_): lock(lock_),unlocked(false) {} @@ -146,13 +155,10 @@ namespace boost { lock.lock(); } - + } - private: - relocker(relocker&); - void operator=(relocker&); }; - + entry_ptr get_wait_entry() { @@ -177,37 +183,37 @@ namespace boost return generations.back(); } } - + struct entry_manager { entry_ptr const entry; - + + BOOST_THREAD_NO_COPYABLE(entry_manager) entry_manager(entry_ptr const& entry_): entry(entry_) {} - + ~entry_manager() { + if(! entry->is_notified()) + { entry->remove_waiter(); + } } list_entry* operator->() { return entry.get(); } - - private: - void operator=(entry_manager&); - entry_manager(entry_manager&); }; - + protected: template<typename lock_type> - bool do_wait(lock_type& lock,timeout wait_until) + bool do_wait(lock_type& lock,timeout abs_time) { relocker<lock_type> locker(lock); - + entry_manager entry(get_wait_entry()); locker.unlock(); @@ -215,27 +221,27 @@ namespace boost bool woken=false; while(!woken) { - if(!entry->wait(wait_until)) + if(!entry->wait(abs_time)) { return false; } - + woken=entry->woken(); } return woken; } template<typename lock_type,typename predicate_type> - bool do_wait(lock_type& m,timeout const& wait_until,predicate_type pred) + bool do_wait(lock_type& m,timeout const& abs_time,predicate_type pred) { while (!pred()) { - if(!do_wait(m, wait_until)) + if(!do_wait(m, abs_time)) return pred(); } return true; } - + basic_condition_variable(const basic_condition_variable& other); basic_condition_variable& operator=(const basic_condition_variable& other); @@ -243,11 +249,11 @@ namespace boost basic_condition_variable(): total_count(0),active_generation_count(0),wake_sem(0) {} - + ~basic_condition_variable() {} - void notify_one() + void notify_one() BOOST_NOEXCEPT { if(detail::interlocked_read_acquire(&total_count)) { @@ -267,8 +273,8 @@ namespace boost generations.erase(std::remove_if(generations.begin(),generations.end(),&basic_cv_list_entry::no_waiters),generations.end()); } } - - void notify_all() + + void notify_all() BOOST_NOEXCEPT { if(detail::interlocked_read_acquire(&total_count)) { @@ -288,23 +294,21 @@ namespace boost wake_sem=detail::win32::handle(0); } } - + }; } class condition_variable: private detail::basic_condition_variable { - private: - condition_variable(condition_variable&); - void operator=(condition_variable&); public: + BOOST_THREAD_NO_COPYABLE(condition_variable) condition_variable() {} - + using detail::basic_condition_variable::notify_one; using detail::basic_condition_variable::notify_all; - + void wait(unique_lock<mutex>& m) { do_wait(m,detail::timeout::sentinel()); @@ -315,16 +319,16 @@ namespace boost { while(!pred()) wait(m); } - - bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until) + + bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time) { - return do_wait(m,wait_until); + return do_wait(m,abs_time); } - bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until) + bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time) { - return do_wait(m,system_time(wait_until)); + return do_wait(m,system_time(abs_time)); } template<typename duration_type> bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration) @@ -333,35 +337,85 @@ namespace boost } template<typename predicate_type> - bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred) + bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time,predicate_type pred) { - return do_wait(m,wait_until,pred); + return do_wait(m,abs_time,pred); } template<typename predicate_type> - bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until,predicate_type pred) + bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time,predicate_type pred) { - return do_wait(m,system_time(wait_until),pred); + return do_wait(m,system_time(abs_time),pred); } template<typename duration_type,typename predicate_type> bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred) { return do_wait(m,wait_duration.total_milliseconds(),pred); } + +#ifdef BOOST_THREAD_USES_CHRONO + + template <class Clock, class Duration> + cv_status + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + do_wait(lock, ceil<milliseconds>(t-Clock::now()).count()); + return Clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template <class Rep, class Period> + cv_status + wait_for( + unique_lock<mutex>& lock, + const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + steady_clock::time_point c_now = steady_clock::now(); + do_wait(lock, ceil<milliseconds>(d).count()); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + } + + template <class Clock, class Duration, class Predicate> + bool + wait_until( + unique_lock<mutex>& lock, + const chrono::time_point<Clock, Duration>& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + template <class Rep, class Period, class Predicate> + bool + wait_for( + unique_lock<mutex>& lock, + const chrono::duration<Rep, Period>& d, + Predicate pred) + { + return wait_until(lock, chrono::steady_clock::now() + d, pred); + } +#endif }; - + class condition_variable_any: private detail::basic_condition_variable { - private: - condition_variable_any(condition_variable_any&); - void operator=(condition_variable_any&); public: + BOOST_THREAD_NO_COPYABLE(condition_variable_any) condition_variable_any() {} - + using detail::basic_condition_variable::notify_one; using detail::basic_condition_variable::notify_all; - + template<typename lock_type> void wait(lock_type& m) { @@ -373,17 +427,17 @@ namespace boost { while(!pred()) wait(m); } - + template<typename lock_type> - bool timed_wait(lock_type& m,boost::system_time const& wait_until) + bool timed_wait(lock_type& m,boost::system_time const& abs_time) { - return do_wait(m,wait_until); + return do_wait(m,abs_time); } template<typename lock_type> - bool timed_wait(lock_type& m,boost::xtime const& wait_until) + bool timed_wait(lock_type& m,boost::xtime const& abs_time) { - return do_wait(m,system_time(wait_until)); + return do_wait(m,system_time(abs_time)); } template<typename lock_type,typename duration_type> @@ -393,15 +447,15 @@ namespace boost } template<typename lock_type,typename predicate_type> - bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred) + bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred) { - return do_wait(m,wait_until,pred); + return do_wait(m,abs_time,pred); } template<typename lock_type,typename predicate_type> - bool timed_wait(lock_type& m,boost::xtime const& wait_until,predicate_type pred) + bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred) { - return do_wait(m,system_time(wait_until),pred); + return do_wait(m,system_time(abs_time),pred); } template<typename lock_type,typename duration_type,typename predicate_type> @@ -409,8 +463,61 @@ namespace boost { return do_wait(m,wait_duration.total_milliseconds(),pred); } +#ifdef BOOST_THREAD_USES_CHRONO + + template <class lock_type, class Clock, class Duration> + cv_status + wait_until( + lock_type& lock, + const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + do_wait(lock, ceil<milliseconds>(t-Clock::now()).count()); + return Clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template <class lock_type, class Rep, class Period> + cv_status + wait_for( + lock_type& lock, + const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + steady_clock::time_point c_now = steady_clock::now(); + do_wait(lock, ceil<milliseconds>(d).count()); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + } + + template <class lock_type, class Clock, class Duration, class Predicate> + bool + wait_until( + lock_type& lock, + const chrono::time_point<Clock, Duration>& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + + template <class lock_type, class Rep, class Period, class Predicate> + bool + wait_for( + lock_type& lock, + const chrono::duration<Rep, Period>& d, + Predicate pred) + { + return wait_until(lock, chrono::steady_clock::now() + d, pred); + } +#endif }; + BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); } #include <boost/config/abi_suffix.hpp> diff --git a/3rdParty/Boost/src/boost/thread/win32/interlocked_read.hpp b/3rdParty/Boost/src/boost/thread/win32/interlocked_read.hpp index 133fb6f..4a96998 100644 --- a/3rdParty/Boost/src/boost/thread/win32/interlocked_read.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/interlocked_read.hpp @@ -3,13 +3,15 @@ // interlocked_read_win32.hpp // -// (C) Copyright 2005-8 Anthony Williams +// (C) Copyright 2005-8 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba // // 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 <boost/detail/interlocked.hpp> +#include <boost/thread/detail/config.hpp> #include <boost/config/abi_prefix.hpp> @@ -22,25 +24,25 @@ namespace boost { namespace detail { - inline long interlocked_read_acquire(long volatile* x) + inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT { long const res=*x; _ReadWriteBarrier(); return res; } - inline void* interlocked_read_acquire(void* volatile* x) + inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT { void* const res=*x; _ReadWriteBarrier(); return res; } - inline void interlocked_write_release(long volatile* x,long value) + inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT { _ReadWriteBarrier(); *x=value; } - inline void interlocked_write_release(void* volatile* x,void* value) + inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT { _ReadWriteBarrier(); *x=value; @@ -54,19 +56,19 @@ namespace boost { namespace detail { - inline long interlocked_read_acquire(long volatile* x) + inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT { return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0); } - inline void* interlocked_read_acquire(void* volatile* x) + inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT { return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0); } - inline void interlocked_write_release(long volatile* x,long value) + inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT { BOOST_INTERLOCKED_EXCHANGE(x,value); } - inline void interlocked_write_release(void* volatile* x,void* value) + inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT { BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value); } diff --git a/3rdParty/Boost/src/boost/thread/win32/mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/mutex.hpp index d59fbfa..85a00e2 100644 --- a/3rdParty/Boost/src/boost/thread/win32/mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/mutex.hpp @@ -1,12 +1,12 @@ #ifndef BOOST_THREAD_WIN32_MUTEX_HPP #define BOOST_THREAD_WIN32_MUTEX_HPP // (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // 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 "basic_timed_mutex.hpp" -#include <boost/utility.hpp> +#include <boost/thread/win32/basic_timed_mutex.hpp> #include <boost/thread/exceptions.hpp> #include <boost/thread/locks.hpp> @@ -22,10 +22,8 @@ namespace boost class mutex: public ::boost::detail::underlying_mutex { - private: - mutex(mutex const&); - mutex& operator=(mutex const&); public: + BOOST_THREAD_NO_COPYABLE(mutex) mutex() { initialize(); @@ -44,10 +42,8 @@ namespace boost class timed_mutex: public ::boost::detail::basic_timed_mutex { - private: - timed_mutex(timed_mutex const&); - timed_mutex& operator=(timed_mutex const&); public: + BOOST_THREAD_NO_COPYABLE(timed_mutex) timed_mutex() { initialize(); diff --git a/3rdParty/Boost/src/boost/thread/win32/once.hpp b/3rdParty/Boost/src/boost/thread/win32/once.hpp index e1b1843..3066b50 100644 --- a/3rdParty/Boost/src/boost/thread/win32/once.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/once.hpp @@ -3,8 +3,9 @@ // once.hpp // -// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2005-7 Anthony Williams // (C) Copyright 2005 John Maddock +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -30,6 +31,25 @@ namespace std namespace boost { +#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 + + struct once_flag + { + BOOST_THREAD_NO_COPYABLE(once_flag) + BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT + : status(0), count(0) + {} + private: + long status; + long count; + template<typename Function> + friend + void call_once(once_flag& flag,Function f); + }; + +#define BOOST_ONCE_INIT once_flag() +#else // BOOST_THREAD_PROVIDES_ONCE_CXX11 + struct once_flag { long status; @@ -37,6 +57,7 @@ namespace boost }; #define BOOST_ONCE_INIT {0,0} +#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11 namespace detail { @@ -71,29 +92,29 @@ namespace boost #else static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; #endif - BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) == + BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) == (sizeof(once_char_type)*(once_mutex_name_fixed_length+1))); - + std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name)); - detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), + detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), mutex_name + once_mutex_name_fixed_length); - detail::int_to_string(win32::GetCurrentProcessId(), + detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2); } - + inline void* open_once_event(once_char_type* mutex_name,void* flag_address) { if(!*mutex_name) { name_once_mutex(mutex_name,flag_address); } - -#ifdef BOOST_NO_ANSI_APIS + +#ifdef BOOST_NO_ANSI_APIS return ::boost::detail::win32::OpenEventW( #else return ::boost::detail::win32::OpenEventA( #endif - ::boost::detail::win32::synchronize | + ::boost::detail::win32::synchronize | ::boost::detail::win32::event_modify_state, false, mutex_name); @@ -105,7 +126,7 @@ namespace boost { name_once_mutex(mutex_name,flag_address); } -#ifdef BOOST_NO_ANSI_APIS +#ifdef BOOST_NO_ANSI_APIS return ::boost::detail::win32::CreateEventW( #else return ::boost::detail::win32::CreateEventA( @@ -115,7 +136,7 @@ namespace boost mutex_name); } } - + template<typename Function> void call_once(once_flag& flag,Function f) @@ -136,7 +157,9 @@ namespace boost status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,running_value,0); if(!status) { - try +#ifndef BOOST_NO_EXCEPTIONS + try // BOOST_NO_EXCEPTIONS protected +#endif { if(!event_handle) { @@ -153,7 +176,7 @@ namespace boost counted=true; } BOOST_INTERLOCKED_EXCHANGE(&flag.status,function_complete_flag_value); - if(!event_handle && + if(!event_handle && (::boost::detail::interlocked_read_acquire(&flag.count)>1)) { event_handle=detail::create_once_event(mutex_name,&flag); @@ -164,7 +187,8 @@ namespace boost } break; } - catch(...) +#ifndef BOOST_NO_EXCEPTIONS + catch(...) // BOOST_NO_EXCEPTIONS protected { BOOST_INTERLOCKED_EXCHANGE(&flag.status,0); if(!event_handle) @@ -175,8 +199,9 @@ namespace boost { ::boost::detail::win32::SetEvent(event_handle); } - throw; + throw; // BOOST_NO_EXCEPTIONS protected } +#endif } if(!counted) diff --git a/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp index e83d3bc..5144e77 100644 --- a/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp @@ -3,15 +3,14 @@ // recursive_mutex.hpp // -// (C) Copyright 2006-7 Anthony Williams +// (C) Copyright 2006-7 Anthony Williams // // 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 <boost/utility.hpp> -#include "basic_recursive_mutex.hpp" +#include <boost/thread/win32/basic_recursive_mutex.hpp> #include <boost/thread/exceptions.hpp> #include <boost/thread/locks.hpp> @@ -22,10 +21,8 @@ namespace boost class recursive_mutex: public ::boost::detail::basic_recursive_mutex { - private: - recursive_mutex(recursive_mutex const&); - recursive_mutex& operator=(recursive_mutex const&); public: + BOOST_THREAD_NO_COPYABLE(recursive_mutex) recursive_mutex() { ::boost::detail::basic_recursive_mutex::initialize(); @@ -44,10 +41,8 @@ namespace boost class recursive_timed_mutex: public ::boost::detail::basic_recursive_timed_mutex { - private: - recursive_timed_mutex(recursive_timed_mutex const&); - recursive_timed_mutex& operator=(recursive_timed_mutex const&); public: + BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex) recursive_timed_mutex() { ::boost::detail::basic_recursive_timed_mutex::initialize(); diff --git a/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp index 58fc622..fef2d5b 100644 --- a/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp @@ -2,6 +2,7 @@ #define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP // (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -12,8 +13,12 @@ #include <boost/thread/win32/thread_primitives.hpp> #include <boost/static_assert.hpp> #include <limits.h> -#include <boost/utility.hpp> #include <boost/thread/thread_time.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> +#endif +#include <boost/thread/detail/delete.hpp> #include <boost/config/abi_prefix.hpp> @@ -22,9 +27,6 @@ namespace boost class shared_mutex { private: - shared_mutex(shared_mutex const&); - shared_mutex& operator=(shared_mutex const&); - private: struct state_data { unsigned shared_count:11, @@ -39,7 +41,7 @@ namespace boost return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs); } }; - + template<typename T> T interlocked_compare_exchange(T* target,T new_value,T comparand) @@ -67,20 +69,32 @@ namespace boost { BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0); } - + if(old_state.shared_waiting || old_state.exclusive_waiting) { BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0); } } - + public: + BOOST_THREAD_NO_COPYABLE(shared_mutex) shared_mutex() { semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX); - semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX); - upgrade_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX); + semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); + if (!semaphores[exclusive_sem]) + { + detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); + boost::throw_exception(thread_resource_error()); + } + upgrade_sem=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); + if (!upgrade_sem) + { + detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); + detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX); + boost::throw_exception(thread_resource_error()); + } state_data state_={0}; state=state_; } @@ -106,7 +120,7 @@ namespace boost return false; } } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -165,7 +179,7 @@ namespace boost { return true; } - + unsigned long const res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until)); if(res==detail::win32::timeout) { @@ -202,11 +216,120 @@ namespace boost } return false; } - + BOOST_ASSERT(res==0); } } +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time) + { + return try_lock_shared_until(chrono::steady_clock::now() + rel_time); + } + template <class Clock, class Duration> + bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_shared_until(s_now + ceil<system_clock::duration>(t - c_now)); + } + template <class Duration> + bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt; + return try_lock_shared_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch()))); + } + bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp) + { + for(;;) + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + ++new_state.shared_waiting; + if(!new_state.shared_waiting) + { + boost::throw_exception(boost::lock_error()); + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + boost::throw_exception(boost::lock_error()); + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + + chrono::system_clock::time_point n = chrono::system_clock::now(); + unsigned long res; + if (tp>n) { + chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n); + res=detail::win32::WaitForSingleObject(semaphores[unlock_sem], + static_cast<unsigned long>(rel_time.count())); + } else { + res=detail::win32::timeout; + } + if(res==detail::win32::timeout) + { + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + if(new_state.shared_waiting) + { + --new_state.shared_waiting; + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + return false; + } + + BOOST_ASSERT(res==0); + } + } +#endif + void unlock_shared() { state_data old_state=state; @@ -214,7 +337,7 @@ namespace boost { state_data new_state=old_state; bool const last_reader=!--new_state.shared_count; - + if(last_reader) { if(new_state.upgrade) @@ -232,7 +355,7 @@ namespace boost new_state.shared_waiting=0; } } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -278,7 +401,7 @@ namespace boost { new_state.exclusive=true; } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -306,7 +429,7 @@ namespace boost { boost::throw_exception(boost::lock_error()); } - + new_state.exclusive_waiting_blocked=true; } else @@ -326,7 +449,12 @@ namespace boost { return true; } - unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,true,::boost::detail::get_milliseconds_until(wait_until)); + #ifndef UNDER_CE + const bool wait_all = true; + #else + const bool wait_all = false; + #endif + unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until)); if(wait_res==detail::win32::timeout) { for(;;) @@ -364,6 +492,116 @@ namespace boost } } +#ifdef BOOST_THREAD_USES_CHRONO + template <class Rep, class Period> + bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) + { + return try_lock_until(chrono::steady_clock::now() + rel_time); + } + template <class Clock, class Duration> + bool try_lock_until(const chrono::time_point<Clock, Duration>& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now)); + } + template <class Duration> + bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t) + { + using namespace chrono; + typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt; + return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp) + { + for(;;) + { + state_data old_state=state; + + for(;;) + { + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + ++new_state.exclusive_waiting; + if(!new_state.exclusive_waiting) + { + boost::throw_exception(boost::lock_error()); + } + + new_state.exclusive_waiting_blocked=true; + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + #ifndef UNDER_CE + const bool wait_all = true; + #else + const bool wait_all = false; + #endif + + chrono::system_clock::time_point n = chrono::system_clock::now(); + unsigned long wait_res; + if (tp>n) { + chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now()); + wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all, + static_cast<unsigned long>(rel_time.count())); + } else { + wait_res=detail::win32::timeout; + } + if(wait_res==detail::win32::timeout) + { + for(;;) + { + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + if(new_state.exclusive_waiting) + { + if(!--new_state.exclusive_waiting) + { + new_state.exclusive_waiting_blocked=false; + } + } + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + return false; + } + BOOST_ASSERT(wait_res<2); + } + } +#endif + void unlock() { state_data old_state=state; @@ -426,7 +664,7 @@ namespace boost { return; } - + BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite)); } } @@ -450,7 +688,7 @@ namespace boost } new_state.upgrade=true; } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -469,7 +707,7 @@ namespace boost state_data new_state=old_state; new_state.upgrade=false; bool const last_reader=!--new_state.shared_count; - + if(last_reader) { if(new_state.exclusive_waiting) @@ -479,13 +717,15 @@ namespace boost } new_state.shared_waiting=0; } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { if(last_reader) { release_waiters(old_state); + } else { + release_waiters(old_state); } break; } @@ -500,13 +740,13 @@ namespace boost { state_data new_state=old_state; bool const last_reader=!--new_state.shared_count; - + if(last_reader) { new_state.upgrade=false; new_state.exclusive=true; } - + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); if(current_state==old_state) { @@ -545,7 +785,28 @@ namespace boost } release_waiters(old_state); } - +// bool try_unlock_upgrade_and_lock() +// { +// return false; +// } +//#ifdef BOOST_THREAD_USES_CHRONO +// template <class Rep, class Period> +// bool +// try_unlock_upgrade_and_lock_for( +// const chrono::duration<Rep, Period>& rel_time) +// { +// return try_unlock_upgrade_and_lock_until( +// chrono::steady_clock::now() + rel_time); +// } +// template <class Clock, class Duration> +// bool +// try_unlock_upgrade_and_lock_until( +// const chrono::time_point<Clock, Duration>& abs_time) +// { +// return false; +// } +//#endif + void unlock_and_lock_shared() { state_data old_state=state; @@ -570,7 +831,6 @@ namespace boost } release_waiters(old_state); } - void unlock_upgrade_and_lock_shared() { state_data old_state=state; @@ -594,8 +854,10 @@ namespace boost } release_waiters(old_state); } - + }; + typedef shared_mutex upgrade_mutex; + } #include <boost/config/abi_suffix.hpp> diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp index c86b0fa..18fd7cb 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp @@ -4,51 +4,116 @@ // 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 <boost/thread/detail/config.hpp> -#include <boost/intrusive_ptr.hpp> #include <boost/thread/thread_time.hpp> -#include "thread_primitives.hpp" -#include "thread_heap_alloc.hpp" +#include <boost/thread/win32/thread_primitives.hpp> +#include <boost/thread/win32/thread_heap_alloc.hpp> + +#include <boost/intrusive_ptr.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/system_clocks.hpp> +#endif + +#include <map> +#include <vector> +#include <utility> #include <boost/config/abi_prefix.hpp> namespace boost { + class condition_variable; + class mutex; + + class thread_attributes { + public: + thread_attributes() BOOST_NOEXCEPT { + val_.stack_size = 0; + //val_.lpThreadAttributes=0; + } + ~thread_attributes() { + } + // stack size + void set_stack_size(std::size_t size) BOOST_NOEXCEPT { + val_.stack_size = size; + } + + std::size_t get_stack_size() const BOOST_NOEXCEPT { + return val_.stack_size; + } + + //void set_security(LPSECURITY_ATTRIBUTES lpThreadAttributes) + //{ + // val_.lpThreadAttributes=lpThreadAttributes; + //} + //LPSECURITY_ATTRIBUTES get_security() + //{ + // return val_.lpThreadAttributes; + //} + + struct win_attrs { + std::size_t stack_size; + //LPSECURITY_ATTRIBUTES lpThreadAttributes; + }; + typedef win_attrs native_handle_type; + native_handle_type* native_handle() {return &val_;} + const native_handle_type* native_handle() const {return &val_;} + + private: + win_attrs val_; + }; + namespace detail { + struct tss_cleanup_function; struct thread_exit_callback_node; - struct tss_data_node; + struct tss_data_node + { + boost::shared_ptr<boost::detail::tss_cleanup_function> func; + void* value; + + tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_, + void* value_): + func(func_),value(value_) + {} + }; struct thread_data_base; void intrusive_ptr_add_ref(thread_data_base * p); void intrusive_ptr_release(thread_data_base * p); - - struct thread_data_base + + struct BOOST_THREAD_DECL thread_data_base { long count; detail::win32::handle_manager thread_handle; detail::win32::handle_manager interruption_handle; boost::detail::thread_exit_callback_node* thread_exit_callbacks; - boost::detail::tss_data_node* tss_data; + std::map<void const*,boost::detail::tss_data_node> tss_data; bool interruption_enabled; unsigned id; + typedef std::vector<std::pair<condition_variable*, mutex*> + //, hidden_allocator<std::pair<condition_variable*, mutex*> > + > notify_list_t; + notify_list_t notify; + thread_data_base(): count(0),thread_handle(detail::win32::invalid_handle_value), interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)), - thread_exit_callbacks(0),tss_data(0), + thread_exit_callbacks(0),tss_data(), interruption_enabled(true), - id(0) - {} - virtual ~thread_data_base() + id(0), + notify() {} + virtual ~thread_data_base(); friend void intrusive_ptr_add_ref(thread_data_base * p) { BOOST_INTERLOCKED_INCREMENT(&p->count); } - + friend void intrusive_ptr_release(thread_data_base * p) { if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) @@ -61,15 +126,21 @@ namespace boost { BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0); } - + typedef detail::win32::handle native_handle_type; virtual void run()=0; + + void notify_all_at_thread_exit(condition_variable* cv, mutex* m) + { + notify.push_back(std::pair<condition_variable*, mutex*>(cv, m)); + } + }; typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr; - struct timeout + struct BOOST_SYMBOL_VISIBLE timeout { unsigned long start; uintmax_t milliseconds; @@ -92,7 +163,7 @@ namespace boost abs_time(abs_time_) {} - struct remaining_time + struct BOOST_SYMBOL_VISIBLE remaining_time { bool more; unsigned long milliseconds; @@ -130,7 +201,7 @@ namespace boost { return milliseconds==~uintmax_t(0); } - + static timeout sentinel() { @@ -139,43 +210,49 @@ namespace boost private: struct sentinel_type {}; - + explicit timeout(sentinel_type): start(0),milliseconds(~uintmax_t(0)),relative(true) {} }; - inline unsigned long pin_to_zero(long value) + inline uintmax_t pin_to_zero(intmax_t value) { - return (value<0)?0u:(unsigned long)value; + return (value<0)?0u:(uintmax_t)value; } } namespace this_thread { - void BOOST_THREAD_DECL yield(); + void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time); - inline void interruptible_wait(unsigned long milliseconds) + inline void interruptible_wait(uintmax_t milliseconds) { interruptible_wait(detail::win32::invalid_handle_value,milliseconds); } - inline void interruptible_wait(system_time const& abs_time) + inline BOOST_SYMBOL_VISIBLE void interruptible_wait(system_time const& abs_time) { interruptible_wait(detail::win32::invalid_handle_value,abs_time); } template<typename TimeDuration> - inline void sleep(TimeDuration const& rel_time) + inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); } - inline void sleep(system_time const& abs_time) + inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) { interruptible_wait(abs_time); } +#ifdef BOOST_THREAD_USES_CHRONO + inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) + { + interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count()); + } +#endif } - + } #include <boost/config/abi_suffix.hpp> diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp index c210a91..9b6d390 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp @@ -5,7 +5,7 @@ #ifndef THREAD_HEAP_ALLOC_HPP #define THREAD_HEAP_ALLOC_HPP #include <new> -#include "thread_primitives.hpp" +#include <boost/thread/win32/thread_primitives.hpp> #include <stdexcept> #include <boost/assert.hpp> #include <boost/throw_exception.hpp> @@ -56,7 +56,7 @@ namespace boost { namespace detail { - inline /*BOOST_THREAD_DECL*/ void* allocate_raw_heap_memory(unsigned size) + inline void* allocate_raw_heap_memory(unsigned size) { void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size); if(!heap_memory) @@ -66,153 +66,189 @@ namespace boost return heap_memory; } - inline /*BOOST_THREAD_DECL*/ void free_raw_heap_memory(void* heap_memory) + inline void free_raw_heap_memory(void* heap_memory) { BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0); } - + template<typename T> inline T* heap_new() { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); - try +#ifndef BOOST_NO_EXCEPTIONS + try // BOOST_NO_EXCEPTIONS protected +#endif { T* const data=new (heap_memory) T(); return data; } - catch(...) +#ifndef BOOST_NO_EXCEPTIONS + catch(...) // BOOST_NO_EXCEPTIONS protected { free_raw_heap_memory(heap_memory); - throw; + throw; // BOOST_NO_EXCEPTIONS protected } +#endif } -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template<typename T,typename A1> inline T* heap_new(A1&& a1) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); - try +#ifndef BOOST_NO_EXCEPTIONS + try // BOOST_NO_EXCEPTIONS protected +#endif { T* const data=new (heap_memory) T(static_cast<A1&&>(a1)); return data; } - catch(...) +#ifndef BOOST_NO_EXCEPTIONS + catch(...) // BOOST_NO_EXCEPTIONS protected { free_raw_heap_memory(heap_memory); - throw; + throw; // BOOST_NO_EXCEPTIONS protected } +#endif } template<typename T,typename A1,typename A2> inline T* heap_new(A1&& a1,A2&& a2) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); - try +#ifndef BOOST_NO_EXCEPTIONS + try // BOOST_NO_EXCEPTIONS protected +#endif { T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2)); return data; } - catch(...) +#ifndef BOOST_NO_EXCEPTIONS + catch(...) // BOOST_NO_EXCEPTIONS protected { free_raw_heap_memory(heap_memory); - throw; + throw; // BOOST_NO_EXCEPTIONS protected } +#endif } template<typename T,typename A1,typename A2,typename A3> inline T* heap_new(A1&& a1,A2&& a2,A3&& a3) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); - try +#ifndef BOOST_NO_EXCEPTIONS + try // BOOST_NO_EXCEPTIONS protected +#endif { T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2), static_cast<A3&&>(a3)); return data; } - catch(...) +#ifndef BOOST_NO_EXCEPTIONS + catch(...) // BOOST_NO_EXCEPTIONS protected { free_raw_heap_memory(heap_memory); - throw; + throw; // BOOST_NO_EXCEPTIONS protected } +#endif } template<typename T,typename A1,typename A2,typename A3,typename A4> inline T* heap_new(A1&& a1,A2&& a2,A3&& a3,A4&& a4) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); - try +#ifndef BOOST_NO_EXCEPTIONS + try // BOOST_NO_EXCEPTIONS protected +#endif { T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2), static_cast<A3&&>(a3),static_cast<A4&&>(a4)); return data; } - catch(...) +#ifndef BOOST_NO_EXCEPTIONS + catch(...) // BOOST_NO_EXCEPTIONS protected { free_raw_heap_memory(heap_memory); - throw; + throw; // BOOST_NO_EXCEPTIONS protected } +#endif } #else template<typename T,typename A1> inline T* heap_new_impl(A1 a1) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); - try +#ifndef BOOST_NO_EXCEPTIONS + try // BOOST_NO_EXCEPTIONS protected +#endif { T* const data=new (heap_memory) T(a1); return data; } - catch(...) +#ifndef BOOST_NO_EXCEPTIONS + catch(...) // BOOST_NO_EXCEPTIONS protected { free_raw_heap_memory(heap_memory); - throw; + throw; // BOOST_NO_EXCEPTIONS protected } +#endif } template<typename T,typename A1,typename A2> inline T* heap_new_impl(A1 a1,A2 a2) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); - try +#ifndef BOOST_NO_EXCEPTIONS + try // BOOST_NO_EXCEPTIONS protected +#endif { T* const data=new (heap_memory) T(a1,a2); return data; } - catch(...) +#ifndef BOOST_NO_EXCEPTIONS + catch(...) // BOOST_NO_EXCEPTIONS protected { free_raw_heap_memory(heap_memory); - throw; + throw; // BOOST_NO_EXCEPTIONS protected } +#endif } template<typename T,typename A1,typename A2,typename A3> inline T* heap_new_impl(A1 a1,A2 a2,A3 a3) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); - try +#ifndef BOOST_NO_EXCEPTIONS + try // BOOST_NO_EXCEPTIONS protected +#endif { T* const data=new (heap_memory) T(a1,a2,a3); return data; } - catch(...) +#ifndef BOOST_NO_EXCEPTIONS + catch(...) // BOOST_NO_EXCEPTIONS protected { free_raw_heap_memory(heap_memory); - throw; + throw; // BOOST_NO_EXCEPTIONS protected } +#endif } template<typename T,typename A1,typename A2,typename A3,typename A4> inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); - try +#ifndef BOOST_NO_EXCEPTIONS + try // BOOST_NO_EXCEPTIONS protected +#endif { T* const data=new (heap_memory) T(a1,a2,a3,a4); return data; } - catch(...) +#ifndef BOOST_NO_EXCEPTIONS + catch(...) // BOOST_NO_EXCEPTIONS protected { free_raw_heap_memory(heap_memory); - throw; + throw; // BOOST_NO_EXCEPTIONS protected } +#endif } @@ -226,7 +262,7 @@ namespace boost { return heap_new_impl<T,A1&>(a1); } - + template<typename T,typename A1,typename A2> inline T* heap_new(A1 const& a1,A2 const& a2) { @@ -372,8 +408,8 @@ namespace boost { return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4); } - -#endif + +#endif template<typename T> inline void heap_delete(T* data) { diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp index 9b20e86..c0dba11 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp @@ -3,14 +3,14 @@ // win32_thread_primitives.hpp // -// (C) Copyright 2005-7 Anthony Williams -// (C) Copyright 2007 David Deakins +// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2007 David Deakins // // 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 <boost/config.hpp> +#include <boost/thread/detail/config.hpp> #include <boost/throw_exception.hpp> #include <boost/assert.hpp> #include <boost/thread/exceptions.hpp> @@ -94,7 +94,7 @@ namespace boost { namespace win32 { - + # ifdef _WIN64 typedef unsigned __int64 ulong_ptr; # else @@ -170,20 +170,20 @@ namespace boost auto_reset_event=false, manual_reset_event=true }; - + enum initial_event_state { event_initially_reset=false, event_initially_set=true }; - + inline handle create_anonymous_event(event_type type,initial_event_state state) { -#if !defined(BOOST_NO_ANSI_APIS) +#if !defined(BOOST_NO_ANSI_APIS) handle const res=win32::CreateEventA(0,type,state,0); #else handle const res=win32::CreateEventW(0,type,state,0); -#endif +#endif if(!res) { boost::throw_exception(thread_resource_error()); @@ -193,17 +193,26 @@ namespace boost inline handle create_anonymous_semaphore(long initial_count,long max_count) { -#if !defined(BOOST_NO_ANSI_APIS) +#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 +#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); +#endif + return res; + } inline handle duplicate_handle(handle source) { @@ -237,7 +246,7 @@ namespace boost BOOST_VERIFY(CloseHandle(handle_to_manage)); } } - + public: explicit handle_manager(handle handle_to_manage_): handle_to_manage(handle_to_manage_) @@ -245,7 +254,7 @@ namespace boost handle_manager(): handle_to_manage(0) {} - + handle_manager& operator=(handle new_handle) { cleanup(); @@ -279,13 +288,13 @@ namespace boost { return !handle_to_manage; } - + ~handle_manager() { cleanup(); } }; - + } } } @@ -318,7 +327,7 @@ namespace boost { return _interlockedbittestandreset(x,bit)!=0; } - + } } } @@ -332,24 +341,50 @@ namespace boost { inline bool interlocked_bit_test_and_set(long* x,long bit) { +#ifndef BOOST_INTEL_CXX_VERSION __asm { mov eax,bit; mov edx,x; lock bts [edx],eax; setc al; - }; + }; +#else + bool ret; + __asm { + mov eax,bit + mov edx,x + lock bts [edx],eax + setc al + mov ret, al + }; + return ret; + +#endif } inline bool interlocked_bit_test_and_reset(long* x,long bit) { +#ifndef BOOST_INTEL_CXX_VERSION __asm { mov eax,bit; mov edx,x; lock btr [edx],eax; setc al; - }; + }; +#else + bool ret; + __asm { + mov eax,bit + mov edx,x + lock btr [edx],eax + setc al + mov ret, al + }; + return ret; + +#endif } - + } } } diff --git a/3rdParty/Boost/src/boost/thread/xtime.hpp b/3rdParty/Boost/src/boost/thread/xtime.hpp index 7cc6272..1ca996f 100644 --- a/3rdParty/Boost/src/boost/thread/xtime.hpp +++ b/3rdParty/Boost/src/boost/thread/xtime.hpp @@ -2,7 +2,7 @@ // William E. Kempf // Copyright (C) 2007-8 Anthony Williams // -// Distributed under the Boost Software License, Version 1.0. (See accompanying +// 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_XTIME_WEK070601_HPP @@ -20,7 +20,7 @@ namespace boost { enum xtime_clock_types { - TIME_UTC=1 + TIME_UTC_=1 // TIME_TAI, // TIME_MONOTONIC, // TIME_PROCESS, @@ -53,14 +53,14 @@ struct xtime boost::posix_time::microseconds((nsec+500)/1000); #endif } - + }; inline xtime get_xtime(boost::system_time const& abs_time) { xtime res; boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0); - + res.sec=static_cast<xtime::xtime_sec_t>(time_since_epoch.total_seconds()); res.nsec=static_cast<xtime::xtime_nsec_t>(time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second())); return res; @@ -68,7 +68,7 @@ inline xtime get_xtime(boost::system_time const& abs_time) inline int xtime_get(struct xtime* xtp, int clock_type) { - if (clock_type == TIME_UTC) + if (clock_type == TIME_UTC_) { *xtp=get_xtime(get_system_time()); return clock_type; @@ -81,7 +81,7 @@ inline int xtime_cmp(const xtime& xt1, const xtime& xt2) { if (xt1.sec == xt2.sec) return (int)(xt1.nsec - xt2.nsec); - else + else return (xt1.sec > xt2.sec) ? 1 : -1; } |