diff options
Diffstat (limited to '3rdParty/Boost/src/boost/thread')
62 files changed, 12667 insertions, 3130 deletions
diff --git a/3rdParty/Boost/src/boost/thread/barrier.hpp b/3rdParty/Boost/src/boost/thread/barrier.hpp index 4fd8988..acf0a01 100644 --- a/3rdParty/Boost/src/boost/thread/barrier.hpp +++ b/3rdParty/Boost/src/boost/thread/barrier.hpp @@ -1,6 +1,7 @@ // Copyright (C) 2002-2003 // David Moore, William E. Kempf // Copyright (C) 2007-8 Anthony Williams +// (C) Copyright 2013 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) @@ -9,55 +10,236 @@ #define BOOST_BARRIER_JDM030602_HPP #include <boost/thread/detail/config.hpp> -#include <boost/throw_exception.hpp> +#include <boost/thread/detail/delete.hpp> +#include <boost/throw_exception.hpp> #include <boost/thread/mutex.hpp> +#include <boost/thread/lock_types.hpp> #include <boost/thread/condition_variable.hpp> #include <string> #include <stdexcept> +#include <boost/thread/detail/nullary_function.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_void.hpp> +#include <boost/core/enable_if.hpp> +#include <boost/utility/result_of.hpp> #include <boost/config/abi_prefix.hpp> namespace boost { + namespace thread_detail + { + typedef detail::nullary_function<void()> void_completion_function; + typedef detail::nullary_function<size_t()> size_completion_function; + + struct default_barrier_reseter + { + unsigned int size_; + default_barrier_reseter(unsigned int size) : + size_(size) + { + } + BOOST_THREAD_MOVABLE(default_barrier_reseter) + + default_barrier_reseter(default_barrier_reseter const& other) BOOST_NOEXCEPT : + size_(other.size_) + { + } + default_barrier_reseter(BOOST_THREAD_RV_REF(default_barrier_reseter) other) BOOST_NOEXCEPT : + size_(BOOST_THREAD_RV(other).size_) + { + } + + unsigned int operator()() + { + return size_; + } + }; + + struct void_functor_barrier_reseter + { + unsigned int size_; + void_completion_function fct_; + template <typename F> + void_functor_barrier_reseter(unsigned int size, BOOST_THREAD_RV_REF(F) funct) + : size_(size), fct_(boost::move(funct)) + {} + template <typename F> + void_functor_barrier_reseter(unsigned int size, F& funct) + : size_(size), fct_(funct) + {} - class barrier + BOOST_THREAD_MOVABLE(void_functor_barrier_reseter) + + void_functor_barrier_reseter(void_functor_barrier_reseter const& other) BOOST_NOEXCEPT : + size_(other.size_), fct_(other.fct_) + { + } + void_functor_barrier_reseter(BOOST_THREAD_RV_REF(void_functor_barrier_reseter) other) BOOST_NOEXCEPT : + size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_) + { + } + + unsigned int operator()() + { + fct_(); + return size_; + } + }; + struct void_fct_ptr_barrier_reseter { - public: - barrier(unsigned int count) - : m_threshold(count), m_count(count), m_generation(0) - { - if (count == 0) - 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++; - m_count = m_threshold; - m_cond.notify_all(); - return true; - } - - while (gen == m_generation) - m_cond.wait(lock); - return false; - } - - private: - mutex m_mutex; - condition_variable m_cond; - unsigned int m_threshold; - unsigned int m_count; - unsigned int m_generation; + unsigned int size_; + void(*fct_)(); + void_fct_ptr_barrier_reseter(unsigned int size, void(*funct)()) : + size_(size), fct_(funct) + { + } + BOOST_THREAD_MOVABLE(void_fct_ptr_barrier_reseter) + + void_fct_ptr_barrier_reseter(void_fct_ptr_barrier_reseter const& other) BOOST_NOEXCEPT : + size_(other.size_), fct_(other.fct_) + { + } + void_fct_ptr_barrier_reseter(BOOST_THREAD_RV_REF(void_fct_ptr_barrier_reseter) other) BOOST_NOEXCEPT : + size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_) + { + } + unsigned int operator()() + { + fct_(); + return size_; + } }; + } + class barrier + { + static inline unsigned int check_counter(unsigned int count) + { + if (count == 0) boost::throw_exception( + thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero.")); + return count; + } + struct dummy + { + }; + + public: + BOOST_THREAD_NO_COPYABLE( barrier) + + explicit barrier(unsigned int count) : + m_count(check_counter(count)), m_generation(0), fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))) + { + } + + template <typename F> + barrier( + unsigned int count, + BOOST_THREAD_RV_REF(F) funct, + typename enable_if< + typename is_void<typename result_of<F>::type>::type, dummy* + >::type=0 + ) + : m_count(check_counter(count)), + m_generation(0), + fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count, + boost::move(funct))) + ) + { + } + template <typename F> + barrier( + unsigned int count, + F &funct, + typename enable_if< + typename is_void<typename result_of<F>::type>::type, dummy* + >::type=0 + ) + : m_count(check_counter(count)), + m_generation(0), + fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count, + funct)) + ) + { + } + + template <typename F> + barrier( + unsigned int count, + BOOST_THREAD_RV_REF(F) funct, + typename enable_if< + typename is_same<typename result_of<F>::type, unsigned int>::type, dummy* + >::type=0 + ) + : m_count(check_counter(count)), + m_generation(0), + fct_(boost::move(funct)) + { + } + template <typename F> + barrier( + unsigned int count, + F& funct, + typename enable_if< + typename is_same<typename result_of<F>::type, unsigned int>::type, dummy* + >::type=0 + ) + : m_count(check_counter(count)), + m_generation(0), + fct_(funct) + { + } + + barrier(unsigned int count, void(*funct)()) : + m_count(check_counter(count)), m_generation(0), + fct_(funct + ? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_fct_ptr_barrier_reseter(count, funct)))) + : BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count)))) + ) + { + } + barrier(unsigned int count, unsigned int(*funct)()) : + m_count(check_counter(count)), m_generation(0), + fct_(funct + ? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(funct)) + : BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count)))) + ) + { + } + + bool wait() + { + boost::unique_lock < boost::mutex > lock(m_mutex); + unsigned int gen = m_generation; + + if (--m_count == 0) + { + m_generation++; + m_count = static_cast<unsigned int>(fct_()); + BOOST_ASSERT(m_count != 0); + m_cond.notify_all(); + return true; + } + + while (gen == m_generation) + m_cond.wait(lock); + return false; + } + + void count_down_and_wait() + { + wait(); + } + + private: + mutex m_mutex; + condition_variable m_cond; + unsigned int m_count; + unsigned int m_generation; + thread_detail::size_completion_function fct_; + }; -} // namespace boost +} // namespace boost #include <boost/config/abi_suffix.hpp> diff --git a/3rdParty/Boost/src/boost/thread/csbl/memory/allocator_arg.hpp b/3rdParty/Boost/src/boost/thread/csbl/memory/allocator_arg.hpp new file mode 100644 index 0000000..354cdae --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/csbl/memory/allocator_arg.hpp @@ -0,0 +1,41 @@ +// Copyright (C) 2013 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) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP +#define BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP + +#include <boost/thread/csbl/memory/config.hpp> + +// 20.7.6, allocator argument tag +#if defined BOOST_NO_CXX11_ALLOCATOR +#include <boost/container/scoped_allocator.hpp> + +namespace boost +{ + namespace csbl + { + using ::boost::container::allocator_arg_t; + using ::boost::container::allocator_arg; + } +} +#else +namespace boost +{ + namespace csbl + { + using ::std::allocator_arg_t; + using ::std::allocator_arg; + } +} +#endif // BOOST_NO_CXX11_ALLOCATOR +namespace boost +{ + using ::boost::csbl::allocator_arg_t; + using ::boost::csbl::allocator_arg; +} +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/csbl/memory/allocator_traits.hpp b/3rdParty/Boost/src/boost/thread/csbl/memory/allocator_traits.hpp new file mode 100644 index 0000000..3737cd8 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/csbl/memory/allocator_traits.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2013 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) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_ALLOCATOR_TRAITS_HPP +#define BOOST_CSBL_MEMORY_ALLOCATOR_TRAITS_HPP + +#include <boost/thread/csbl/memory/config.hpp> + +// 20.7.8, allocator traits +#if defined BOOST_NO_CXX11_ALLOCATOR +#include <boost/container/allocator_traits.hpp> + +namespace boost +{ + namespace csbl + { + using ::boost::container::allocator_traits; + } +} +#else +namespace boost +{ + namespace csbl + { + using ::std::allocator_traits; + } +} +#endif // BOOST_NO_CXX11_POINTER_TRAITS + +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/csbl/memory/config.hpp b/3rdParty/Boost/src/boost/thread/csbl/memory/config.hpp new file mode 100644 index 0000000..7b0596a --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/csbl/memory/config.hpp @@ -0,0 +1,16 @@ +// Copyright (C) 2013 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) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_CONFIG_HPP +#define BOOST_CSBL_MEMORY_CONFIG_HPP + +#include <boost/config.hpp> + +#include <memory> + +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/csbl/memory/pointer_traits.hpp b/3rdParty/Boost/src/boost/thread/csbl/memory/pointer_traits.hpp new file mode 100644 index 0000000..320f8e9 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/csbl/memory/pointer_traits.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2013 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) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_POINTER_TRAITS_HPP +#define BOOST_CSBL_MEMORY_POINTER_TRAITS_HPP + +#include <boost/thread/csbl/memory/config.hpp> + +// 20.7.3, pointer traits +#if defined BOOST_NO_CXX11_ALLOCATOR +#include <boost/intrusive/pointer_traits.hpp> + +namespace boost +{ + namespace csbl + { + using ::boost::intrusive::pointer_traits; + } +} +#else +namespace boost +{ + namespace csbl + { + using ::std::pointer_traits; + } +} +#endif // BOOST_NO_CXX11_ALLOCATOR + +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/csbl/memory/scoped_allocator.hpp b/3rdParty/Boost/src/boost/thread/csbl/memory/scoped_allocator.hpp new file mode 100644 index 0000000..a92f3d8 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/csbl/memory/scoped_allocator.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2013 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) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_SCOPED_ALLOCATOR_HPP +#define BOOST_CSBL_MEMORY_SCOPED_ALLOCATOR_HPP + +#include <boost/thread/csbl/memory/config.hpp> + +// 20.7.7, uses_allocator +#if defined BOOST_NO_CXX11_ALLOCATOR +#include <boost/container/scoped_allocator.hpp> + +namespace boost +{ + namespace csbl + { + using ::boost::container::uses_allocator; + } +} +#else +namespace boost +{ + namespace csbl + { + using ::std::uses_allocator; + } +} +#endif // BOOST_NO_CXX11_POINTER_TRAITS + +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/csbl/tuple.hpp b/3rdParty/Boost/src/boost/thread/csbl/tuple.hpp new file mode 100644 index 0000000..146d1c1 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/csbl/tuple.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2013 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) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_TUPLE_HPP +#define BOOST_CSBL_TUPLE_HPP + +#include <boost/config.hpp> + +#if defined BOOST_THREAD_USES_BOOST_TUPLE || defined BOOST_NO_CXX11_HDR_TUPLE || defined BOOST_NO_CXX11_RVALUE_REFERENCES +#include <boost/tuple/tuple.hpp> +#ifndef BOOST_THREAD_USES_BOOST_TUPLE +#define BOOST_THREAD_USES_BOOST_TUPLE +#endif + +#else +#include <tuple> +#endif + +namespace boost +{ + namespace csbl + { +#if defined BOOST_THREAD_USES_BOOST_TUPLE + using ::boost::tuple; + using ::boost::get; +#else + // 20.4.2, class template tuple: + using ::std::tuple; + using ::std::get; + // 20.4.2.4, tuple creation functions: + // 20.4.2.5, tuple helper classes: + // 20.4.2.6, element access: + // 20.4.2.7, relational operators: + // 20.4.2.8, allocator-related traits + // 20.4.2.9, specialized algorithms: +#endif + + } +} +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/csbl/vector.hpp b/3rdParty/Boost/src/boost/thread/csbl/vector.hpp new file mode 100644 index 0000000..d39c87d --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/csbl/vector.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2013 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) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_VECTOR_HPP +#define BOOST_CSBL_VECTOR_HPP + +#include <boost/config.hpp> + +#if defined BOOST_THREAD_USES_BOOST_VECTOR || defined BOOST_NO_CXX11_HDR_VECTOR || defined BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_THREAD_USES_BOOST_VECTOR +#define BOOST_THREAD_USES_BOOST_VECTOR +#endif +#include <boost/container/vector.hpp> +#else +#include <vector> +#endif + +namespace boost +{ + namespace csbl + { +#if defined BOOST_THREAD_USES_BOOST_VECTOR + using ::boost::container::vector; +#else + using ::std::vector; +#endif + + } +} +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/cv_status.hpp b/3rdParty/Boost/src/boost/thread/cv_status.hpp index 99b3c0c..e52de4a 100644 --- a/3rdParty/Boost/src/boost/thread/cv_status.hpp +++ b/3rdParty/Boost/src/boost/thread/cv_status.hpp @@ -9,7 +9,7 @@ #ifndef BOOST_THREAD_CV_STATUS_HPP #define BOOST_THREAD_CV_STATUS_HPP -#include <boost/detail/scoped_enum_emulation.hpp> +#include <boost/core/scoped_enum.hpp> namespace boost { diff --git a/3rdParty/Boost/src/boost/thread/detail/config.hpp b/3rdParty/Boost/src/boost/thread/detail/config.hpp index 87bad34..5ffe5e4 100644 --- a/3rdParty/Boost/src/boost/thread/detail/config.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/config.hpp @@ -1,6 +1,6 @@ // Copyright (C) 2001-2003 // William E. Kempf -// Copyright (C) 2011-2012 Vicente J. Botet Escriba +// Copyright (C) 2011-2013 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) @@ -8,111 +8,192 @@ #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> +#include <boost/thread/detail/platform.hpp> + +//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS +// ATTRIBUTE_MAY_ALIAS -#ifdef BOOST_NO_NOEXCEPT -# define BOOST_THREAD_NOEXCEPT_OR_THROW throw() +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) + + // GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with + // regard to violation of the strict aliasing rules. + + #define BOOST_THREAD_DETAIL_USE_ATTRIBUTE_MAY_ALIAS + #define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__)) #else -# define BOOST_THREAD_NOEXCEPT_OR_THROW noexcept + #define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS +#endif + + +#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED +#define BOOST_THREAD_ASSERT_PRECONDITION(EXPR, EX) \ + if (EXPR) {} else boost::throw_exception(EX) +#define BOOST_THREAD_VERIFY_PRECONDITION(EXPR, EX) \ + if (EXPR) {} else boost::throw_exception(EX) +#define BOOST_THREAD_THROW_ELSE_RETURN(EX, RET) \ + boost::throw_exception(EX) +#else +#define BOOST_THREAD_ASSERT_PRECONDITION(EXPR, EX) +#define BOOST_THREAD_VERIFY_PRECONDITION(EXPR, EX) \ + (void)(EXPR) +#define BOOST_THREAD_THROW_ELSE_RETURN(EX, RET) \ + return (RET) #endif // This compiler doesn't support Boost.Chrono -#if defined __IBMCPP__ && (__IBMCPP__ < 1100) && ! defined BOOST_THREAD_DONT_USE_CHRONO +#if defined __IBMCPP__ && (__IBMCPP__ < 1100) \ + && ! defined BOOST_THREAD_DONT_USE_CHRONO #define BOOST_THREAD_DONT_USE_CHRONO +#if ! defined BOOST_THREAD_USES_DATETIME +#define BOOST_THREAD_USES_DATETIME +#endif #endif // This compiler doesn't support Boost.Move -#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) && ! defined BOOST_THREAD_DONT_USE_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 +#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 +#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 + +#if defined BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX || defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#define BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST +#define BOOST_THREAD_NO_MAKE_LOCK_GUARD +#define BOOST_THREAD_NO_MAKE_STRICT_LOCK +#define BOOST_THREAD_NO_MAKE_NESTED_STRICT_LOCK +#endif + +#if defined(BOOST_NO_CXX11_HDR_TUPLE) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#define BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS +#define BOOST_THREAD_NO_SYNCHRONIZE +#elif defined _MSC_VER && _MSC_VER <= 1600 +// C++ features supported by VC++ 10 (aka 2010) +#define BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS +#define BOOST_THREAD_NO_SYNCHRONIZE +#endif + +/// BASIC_THREAD_ID +#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 +/// RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR +//#if defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_MSVC +#define BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR +//#endif + +// Default version #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" +#if BOOST_THREAD_VERSION!=2 && BOOST_THREAD_VERSION!=3 && BOOST_THREAD_VERSION!=4 +#error "BOOST_THREAD_VERSION must be 2, 3 or 4" #endif #endif +// CHRONO // 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 +#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 +#if ! defined BOOST_THREAD_DONT_USE_ATOMIC \ + && ! defined BOOST_THREAD_USES_ATOMIC +#define BOOST_THREAD_USES_ATOMIC +//#define BOOST_THREAD_DONT_USE_ATOMIC #endif - +#if defined BOOST_THREAD_USES_ATOMIC +// Andrey Semashev +#define BOOST_THREAD_ONCE_ATOMIC +#else +//#elif ! defined BOOST_NO_CXX11_THREAD_LOCAL && ! defined BOOST_NO_THREAD_LOCAL && ! defined BOOST_THREAD_NO_UINT32_PSEUDO_ATOMIC +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html#Appendix +#define BOOST_THREAD_ONCE_FAST_EPOCH +#endif #if BOOST_THREAD_VERSION==2 -#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY && ! defined BOOST_THREAD_PROMISE_LAZY -#define BOOST_THREAD_PROMISE_LAZY + +// PROVIDE_PROMISE_LAZY +#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY \ + && ! defined BOOST_THREAD_PROVIDES_PROMISE_LAZY +#define BOOST_THREAD_PROVIDES_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 + +// PROVIDE_THREAD_EQ +#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_EQ \ + && ! defined BOOST_THREAD_PROVIDES_THREAD_EQ +#define BOOST_THREAD_PROVIDES_THREAD_EQ #endif + #endif -#if BOOST_THREAD_VERSION==3 +#if BOOST_THREAD_VERSION>=3 + +// ONCE_CXX11 +// fixme BOOST_THREAD_PROVIDES_ONCE_CXX11 doesn't works when thread.cpp is compiled BOOST_THREAD_VERSION 3 #if ! defined BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11 \ && ! defined BOOST_THREAD_PROVIDES_ONCE_CXX11 -#define BOOST_THREAD_PROVIDES_ONCE_CXX11 +#define BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11 #endif + +// THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE #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 + +// THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE #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 + +// PROVIDE_FUTURE #if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE \ && ! defined BOOST_THREAD_PROVIDES_FUTURE #define BOOST_THREAD_PROVIDES_FUTURE #endif + +// FUTURE_CTOR_ALLOCATORS #if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS \ && ! defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS #define BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS #endif + +// SHARED_MUTEX_UPWARDS_CONVERSIONS #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 + +// PROVIDE_EXPLICIT_LOCK_CONVERSION #if ! defined BOOST_THREAD_DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION \ && ! defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION #define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION #endif + +// GENERIC_SHARED_MUTEX_ON_WIN #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 + +// USE_MOVE #if ! defined BOOST_THREAD_DONT_USE_MOVE \ && ! defined BOOST_THREAD_USES_MOVE #define BOOST_THREAD_USES_MOVE @@ -120,17 +201,157 @@ #endif +// deprecated since version 4 +#if BOOST_THREAD_VERSION < 4 + +// NESTED_LOCKS +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS \ + && ! defined BOOST_THREAD_DONT_PROVIDE_NESTED_LOCKS +#define BOOST_THREAD_PROVIDES_NESTED_LOCKS +#endif + +// CONDITION +#if ! defined BOOST_THREAD_PROVIDES_CONDITION \ + && ! defined BOOST_THREAD_DONT_PROVIDE_CONDITION +#define BOOST_THREAD_PROVIDES_CONDITION +#endif + +// USE_DATETIME +#if ! defined BOOST_THREAD_DONT_USE_DATETIME \ + && ! defined BOOST_THREAD_USES_DATETIME +#define BOOST_THREAD_USES_DATETIME +#endif +#endif + +#if BOOST_THREAD_VERSION>=4 + +// SIGNATURE_PACKAGED_TASK +#if ! defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK \ + && ! defined BOOST_THREAD_DONT_PROVIDE_SIGNATURE_PACKAGED_TASK +#define BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#endif + +// VARIADIC_THREAD +#if ! defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD \ + && ! defined BOOST_THREAD_DONT_PROVIDE_VARIADIC_THREAD + +#if ! defined(BOOST_NO_SFINAE_EXPR) && \ + ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + ! defined(BOOST_NO_CXX11_DECLTYPE) && \ + ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \ + ! defined(BOOST_THREAD_NO_CXX11_DECLTYPE_N3276) && \ + ! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \ + ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ + ! defined(BOOST_NO_CXX11_HDR_TUPLE) + +#define BOOST_THREAD_PROVIDES_VARIADIC_THREAD +#endif +#endif + +#if ! defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY \ + && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_WHEN_ALL_WHEN_ANY + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + ! defined(BOOST_NO_CXX11_HDR_TUPLE) + +#define BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY +#endif +#endif + +// ! defined(BOOST_NO_SFINAE_EXPR) && +// ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && +// ! defined(BOOST_NO_CXX11_AUTO) && +// ! defined(BOOST_NO_CXX11_DECLTYPE) && +// ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && + + +// MAKE_READY_AT_THREAD_EXIT +#if ! defined BOOST_THREAD_PROVIDES_MAKE_READY_AT_THREAD_EXIT \ + && ! defined BOOST_THREAD_DONT_PROVIDE_MAKE_READY_AT_THREAD_EXIT + +//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#define BOOST_THREAD_PROVIDES_MAKE_READY_AT_THREAD_EXIT +//#endif +#endif + +// FUTURE_CONTINUATION +#if ! defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \ + && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CONTINUATION +#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION +#endif + +#if ! defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP \ + && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_UNWRAP +#define BOOST_THREAD_PROVIDES_FUTURE_UNWRAP +#endif + +// FUTURE_INVALID_AFTER_GET +#if ! defined BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET \ + && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET +#define BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET +#endif + +// NESTED_LOCKS +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS \ + && ! defined BOOST_THREAD_DONT_PROVIDE_NESTED_LOCKS +#define BOOST_THREAD_DONT_PROVIDE_NESTED_LOCKS +#endif + +// CONDITION +#if ! defined BOOST_THREAD_PROVIDES_CONDITION \ + && ! defined BOOST_THREAD_DONT_PROVIDE_CONDITION +#define BOOST_THREAD_DONT_PROVIDE_CONDITION +#endif + +#endif // BOOST_THREAD_VERSION>=4 + +// INTERRUPTIONS +#if ! defined BOOST_THREAD_PROVIDES_INTERRUPTIONS \ + && ! defined BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS +#endif + +// CORRELATIONS + +// EXPLICIT_LOCK_CONVERSION. +#if defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION explicit +#else +#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION +#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 +// For C++11 call_once interface the compiler MUST support constexpr. +// Otherwise once_flag would be initialized during dynamic initialization stage, which is not thread-safe. +#if defined(BOOST_THREAD_PROVIDES_ONCE_CXX11) +#if defined(BOOST_NO_CXX11_CONSTEXPR) +#undef BOOST_THREAD_PROVIDES_ONCE_CXX11 +#endif +#endif + +#if defined(BOOST_THREAD_PLATFORM_WIN32) && defined BOOST_THREAD_DONT_USE_DATETIME +#undef BOOST_THREAD_DONT_USE_DATETIME +#define BOOST_THREAD_USES_DATETIME +#endif + +#if defined(BOOST_THREAD_PLATFORM_WIN32) && defined BOOST_THREAD_DONT_USE_CHRONO +#undef BOOST_THREAD_DONT_USE_CHRONO +#define BOOST_THREAD_USES_CHRONO +#endif + +// BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.55 // 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 +#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 + +#if ! defined BOOST_THREAD_PROVIDES_THREAD_EQ +#define BOOST_THREAD_PROVIDES_THREAD_EQ +#endif + #endif #if BOOST_WORKAROUND(__BORLANDC__, < 0x600) @@ -142,6 +363,13 @@ #include <boost/thread/detail/platform.hpp> +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#else + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) || defined(BOOST_HAS_NANOSLEEP) + # define BOOST_THREAD_SLEEP_FOR_IS_STEADY + # endif +#endif + // provided for backwards compatibility, since this // macro was used for several releases by mistake. #if defined(BOOST_THREAD_DYN_DLL) && ! defined BOOST_THREAD_DYN_LINK @@ -151,7 +379,9 @@ // compatibility with the rest of Boost's auto-linking code: #if defined(BOOST_THREAD_DYN_LINK) || defined(BOOST_ALL_DYN_LINK) # undef BOOST_THREAD_USE_LIB -# define BOOST_THREAD_USE_DLL +# if !defined(BOOST_THREAD_USE_DLL) +# define BOOST_THREAD_USE_DLL +# endif #endif #if defined(BOOST_THREAD_BUILD_DLL) //Build dll @@ -160,8 +390,9 @@ #elif defined(BOOST_THREAD_USE_LIB) //Use lib #else //Use default # if defined(BOOST_THREAD_PLATFORM_WIN32) -# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN) - //For compilers supporting auto-tss cleanup +# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN) \ + || defined(__MINGW32__) || defined(MINGW32) || defined(BOOST_MINGW32) + //For compilers supporting auto-tss cleanup //with Boost.Threads lib, use Boost.Threads lib # define BOOST_THREAD_USE_LIB # else diff --git a/3rdParty/Boost/src/boost/thread/detail/delete.hpp b/3rdParty/Boost/src/boost/thread/detail/delete.hpp index 30e7c93..4caa340 100644 --- a/3rdParty/Boost/src/boost/thread/detail/delete.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/delete.hpp @@ -15,6 +15,7 @@ * 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; \ @@ -23,6 +24,17 @@ CLASS& operator=(CLASS const&) = delete; #else // BOOST_NO_CXX11_DELETED_FUNCTIONS +#if defined(BOOST_MSVC) && _MSC_VER >= 1600 +#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \ + private: \ + CLASS(CLASS const&); \ + public: + +#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \ + private: \ + CLASS& operator=(CLASS const&); \ + public: +#else #define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \ private: \ CLASS(CLASS&); \ @@ -32,6 +44,7 @@ private: \ CLASS& operator=(CLASS&); \ public: +#endif #endif // BOOST_NO_CXX11_DELETED_FUNCTIONS /** diff --git a/3rdParty/Boost/src/boost/thread/detail/invoke.hpp b/3rdParty/Boost/src/boost/thread/detail/invoke.hpp new file mode 100644 index 0000000..c81f50f --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/detail/invoke.hpp @@ -0,0 +1,1606 @@ +// Copyright (C) 2012-2013 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) + +// 2013/04 Vicente J. Botet Escriba +// Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined. +// Make use of Boost.Move +// Make use of Boost.Tuple (movable) +// 2012 Vicente J. Botet Escriba +// Provide implementation _RET using bind when BOOST_NO_CXX11_HDR_FUNCTIONAL and BOOST_NO_SFINAE_EXPR are not defined +// 2012 Vicente J. Botet Escriba +// Adapt to boost libc++ implementation + +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// The invoke code is based on the one from libcxx. +//===----------------------------------------------------------------------===// + +#ifndef BOOST_THREAD_DETAIL_INVOKE_HPP +#define BOOST_THREAD_DETAIL_INVOKE_HPP + +#include <boost/config.hpp> +#include <boost/static_assert.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/core/enable_if.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/type_traits/is_base_of.hpp> +#include <boost/type_traits/is_pointer.hpp> +#include <boost/type_traits/is_member_function_pointer.hpp> +#include <boost/type_traits/remove_reference.hpp> +#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL +#include <functional> +#endif + +namespace boost +{ + namespace detail + { + + +#if ! defined(BOOST_NO_SFINAE_EXPR) && \ + ! defined(BOOST_NO_CXX11_DECLTYPE) && \ + ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \ + ! defined(BOOST_THREAD_NO_CXX11_DECLTYPE_N3276) && \ + ! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) + +#define BOOST_THREAD_PROVIDES_INVOKE + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + // bullets 1 and 2 + + template <class Fp, class A0, class ...Args> + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + -> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...)) + { + return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...); + } + template <class R, class Fp, class A0, class ...Args> + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + -> decltype((boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...)) + { + return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...); + } + + template <class Fp, class A0, class ...Args> + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...)) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...); + } + template <class R, class Fp, class A0, class ...Args> + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...)) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...); + } + + // bullets 3 and 4 + + template <class Fp, class A0> + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype(boost::forward<A0>(a0).*f) + { + return boost::forward<A0>(a0).*f; + } + + template <class Fp, class A0> + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype((*boost::forward<A0>(a0)).*f) + { + return (*boost::forward<A0>(a0)).*f; + } + + template <class R, class Fp, class A0> + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype(boost::forward<A0>(a0).*f) + { + return boost::forward<A0>(a0).*f; + } + + template <class R, class Fp, class A0> + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype((*boost::forward<A0>(a0)).*f) + { + return (*boost::forward<A0>(a0)).*f; + } + + + // bullet 5 + + template <class R, class Fp, class ...Args> + inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args) + -> decltype(boost::forward<Fp>(f)(boost::forward<Args>(args)...)) + { + return boost::forward<Fp>(f)(boost::forward<Args>(args)...); + } + template <class Fp, class ...Args> + inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args) + -> decltype(boost::forward<Fp>(f)(boost::forward<Args>(args)...)) + { + return boost::forward<Fp>(f)(boost::forward<Args>(args)...); + } + +#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES + + // bullets 1 and 2 + + template <class Fp, class A0> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype((boost::forward<A0>(a0).*f)()) + { + return (boost::forward<A0>(a0).*f)(); + } + template <class R, class Fp, class A0> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype((boost::forward<A0>(a0).*f)()) + { + return (boost::forward<A0>(a0).*f)(); + } + template <class Fp, class A0, class A1> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + -> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1))) + { + return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)); + } + template <class R, class Fp, class A0, class A1> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + -> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1))) + { + return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)); + } + template <class Fp, class A0, class A1, class A2> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + -> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2))) + { + return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class R, class Fp, class A0, class A1, class A2> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + -> decltype((boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2))) + { + return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + + template <class Fp, class A0> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype(((*boost::forward<A0>(a0)).*f)()) + { + return ((*boost::forward<A0>(a0)).*f)(); + } + template <class R, class Fp, class A0> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype(((*boost::forward<A0>(a0)).*f)()) + { + return ((*boost::forward<A0>(a0)).*f)(); + } + template <class Fp, class A0, class A1> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1))) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)); + } + template <class R, class Fp, class A0, class A1> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1))) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)); + } + template <class Fp, class A0, class A1, class A2> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2))) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class R, class Fp, class A0, class A1, class A2> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + -> decltype(((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2))) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + + // bullets 3 and 4 + + template <class Fp, class A0> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype(boost::forward<A0>(a0).*f) + { + return boost::forward<A0>(a0).*f; + } + template <class R, class Fp, class A0> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype(boost::forward<A0>(a0).*f) + { + return boost::forward<A0>(a0).*f; + } + + template <class Fp, class A0> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype((*boost::forward<A0>(a0)).*f) + { + return (*boost::forward<A0>(a0)).*f; + } + template <class R, class Fp, class A0> + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype((*boost::forward<A0>(a0)).*f) + { + return (*boost::forward<A0>(a0)).*f; + } + + // bullet 5 + + template <class Fp> + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f) + -> decltype(boost::forward<Fp>(f)()) + { + return boost::forward<Fp>(f)(); + } + template <class Fp, class A1> + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1) + -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1))) + { + return boost::forward<Fp>(f)(boost::forward<A1>(a1)); + } template <class Fp, class A1, class A2> + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2))) + { + return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class Fp, class A1, class A2, class A3> + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3))) + { + return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + + + template <class R, class Fp> + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f) + -> decltype(boost::forward<Fp>(f)()) + { + return boost::forward<Fp>(f)(); + } + template <class R, class Fp, class A1> + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1) + -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1))) + { + return boost::forward<Fp>(f)(boost::forward<A1>(a1)); + } + template <class R, class Fp, class A1, class A2> + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2))) + { + return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class R, class Fp, class A1, class A2, class A3> + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + -> decltype(boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3))) + { + return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + +#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES + +#elif ! defined(BOOST_NO_SFINAE_EXPR) && \ + ! defined BOOST_NO_CXX11_HDR_FUNCTIONAL && \ + defined BOOST_MSVC + +//#error + template <class Ret, class Fp> + inline + Ret invoke(BOOST_THREAD_RV_REF(Fp) f) + { + return f(); + } + template <class Ret, class Fp, class A1> + inline + Ret invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1) + { + return std::bind(boost::forward<Fp>(f), boost::forward<A1>(a1))(); + } + template <class Ret, class Fp, class A1, class A2> + inline + Ret invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return std::bind(boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2))(); + } + template <class Ret, class Fp, class A1, class A2, class A3> + inline + Ret invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return std::bind(boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3))(); + } + +#define BOOST_THREAD_PROVIDES_INVOKE_RET + +#elif ! defined BOOST_MSVC +//!!!!! WARNING !!!!! THIS DOESN'T WORKS YET +#define BOOST_THREAD_PROVIDES_INVOKE_RET + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + // bullet 1 + // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of + // type T or a reference to an object of type T or a reference to an object of a type derived from T + template <class Ret, class A, class A0, class ...Args> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...); + } + + template <class Ret, class A, class A0, class ...Args> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...) const, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...); + } + + template <class Ret, class A, class A0, class ...Args> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...) volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...); + } + + template <class Ret, class A, class A0, class ...Args> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...) const volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return (boost::forward<A0>(a0).*f)(boost::forward<Args>(args)...); + } + + // bullet 2 + // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of + // the types described in the previous item; + template <class Ret, class A, class A0, class ...Args> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...); + } + + template <class Ret, class A, class A0, class ...Args> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...) const, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...); + } + + template <class Ret, class A, class A0, class ...Args> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...) volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...); + } + + template <class Ret, class A, class A0, class ...Args> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...) const volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<Args>(args)...); + } + + // bullet 3 + // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a + // reference to an object of type T or a reference to an object of a type derived from T; +// template <class Ret, class A, class A0> +// inline +// typename enable_if_c +// < +// is_base_of<A, typename remove_reference<A0>::type>::value, +// typename detail::apply_cv<A0, A>::type& +// >::type +// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0) +// { +// return boost::forward<A0>(a0).*f; +// } + + // bullet 4 + // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types + //described in the previous item; + +// template <class A0, class Ret, bool> +// struct d4th_helper +// { +// }; +// +// template <class A0, class Ret> +// struct d4th_helper<A0, Ret, true> +// { +// typedef typename apply_cv<decltype(*declval<A0>()), Ret>::type type; +// }; +// +// template <class Ret, class A, class A0> +// inline +// typename detail::4th_helper<A, Ret, +// !is_base_of<A, +// typename remove_reference<A0>::type +// >::value +// >::type& +// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0) +// { +// return (*boost::forward<A0>(a0)).*f; +// } + +// template <class Ret, class A, class A0> +// inline +// typename enable_if_c +// < +// !is_base_of<A, typename remove_reference<A0>::type>::value, +// typename detail::ref_return1<Ret A::*, A0>::type +// >::type +// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0) +// { +// return (*boost::forward<A0>(a0)).*f; +// } + + // bullet 5 + // f(t1, t2, ..., tN) in all other cases. + + template <class Ret, class Fp, class ...Args> + inline Ret do_invoke(mpl::false_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args) + { + return boost::forward<Fp>(f)(boost::forward<Args>(args)...); + } + + template <class Ret, class Fp, class ...Args> + inline Ret do_invoke(mpl::true_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args) + { + return f(boost::forward<Args>(args)...); + } + + template <class Ret, class Fp, class ...Args> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args) + { + return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<Args>(args)...); + } +#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES + // bullet 1 + // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of + // type T or a reference to an object of type T or a reference to an object of a type derived from T + + template <class Ret, class A, class A0> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(), A0& a0) + { + return (a0.*f)(); + } + template <class Ret, class A, class A0> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(), A0* a0) + { + return ((*a0).*f)(); + } + + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1), + A0& a0, BOOST_THREAD_RV_REF(A1) a1 + ) + { + return (a0.*f)(boost::forward<A1>(a1)); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1), A0& a0, A1 a1) + { + return (a0.*f)(a1); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1), A0* a0, BOOST_THREAD_RV_REF(A1) a1 + ) + { + return (*(a0).*f)(boost::forward<A1>(a1)); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1), A0* a0, A1 a1) + { + return (*a0.*f)(a1); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2), + A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2 + ) + { + return (a0.*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2), A0* a0, A1 a1, A2 a2) + { + return ((*a0).*f)(a1, a2); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3), + A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return (a0.*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3), A0* a0, A1 a1, A2 a2, A3 a3) + { + return ((*a0).*f)(a1, a2, a3); + } + +/// + template <class Ret, class A, class A0> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)() const, A0 const& a0) + { + return (a0.*f)(); + } + template <class Ret, class A, class A0> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)() const, A0 const* a0) + { + return ((*a0).*f)(); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const, A0 const& a0, BOOST_THREAD_RV_REF(A1) a1) + { + return (a0.*f)(boost::forward<A1>(a1)); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const, A0 const* a0, BOOST_THREAD_RV_REF(A1) a1) + { + return ((*a0).*f)(boost::forward<A1>(a1)); + } + + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const, A0 const& a0, A1 a1) + { + return (a0.*f)(a1); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const, + A0 const& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2 + ) + { + return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2) + ); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const, A0 const& a0, A1 a1, A2 a2) + { + return (a0.*f)(a1, a2); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3 + ) + { + return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const, A0 a0, A1 a1, A2 a2, A3 a3) + { + return (a0.*f)(a1, a2, a3); + } + /// + template <class Ret, class A, class A0> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)() volatile, BOOST_THREAD_RV_REF(A0) a0) + { + return (boost::forward<A0>(a0).*f)(); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + { + return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) volatile, A0 a0, A1 a1) + { + return (a0.*f)(a1); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) volatile, A0 a0, A1 a1, A2 a2 ) + { + return (a0.*f)(a1, a2); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3 + ) + { + return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) volatile, A0 a0, A1 a1, A2 a2, A3 a3) + { + return (a0.*f)(a1, a2, a3); + } + /// + template <class Ret, class A, class A0> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)() const volatile, BOOST_THREAD_RV_REF(A0) a0) + { + return (boost::forward<A0>(a0).*f)(); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + { + return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1)); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const volatile, A0 a0, A1 a1) + { + return (a0.*f)(a1); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2 + ) + { + return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const volatile, + A0 a0, A1 a1, A2 a2 + ) + { + return (a0.*f)(a1, a2); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3 + ) + { + return (boost::forward<A0>(a0).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const volatile, + A0 a0, A1 a1, A2 a2, A3 a3 + ) + { + return (a0.*f)(a1, a2, a3); + } + + // bullet 2 + // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of + // the types described in the previous item; + template <class Ret, class A, class A0> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(), BOOST_THREAD_RV_REF(A0) a0) + { + return ((*boost::forward<A0>(a0)).*f)(); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1), A0 a0, A1 a1) + { + return ((*a0).*f)(a1); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, BOOST_THREAD_RV_REF(A2)), + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2), A0 a0, A1 a1, A2 a2) + { + return ((*a0).*f)(a1, a2); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, BOOST_THREAD_RV_REF(A2), BOOST_THREAD_RV_REF(A3)), + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3) + ); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3), A0 a0, A1 a1, A2 a2, A3 a3) + { + return ((*a0).*f)(a1, a2, a3); + } + +/// + template <class Ret, class A, class A0> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)() const, BOOST_THREAD_RV_REF(A0) a0) + { + return ((*boost::forward<A0>(a0)).*f)(); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const, BOOST_THREAD_RV_REF(A0) a0, A1 a1) + { + return ((*boost::forward<A0>(a0)).*f)(a1); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const, A0 a0, A1 a1) + { + return ((*a0).*f)(a1); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const, A0 a0, A1 a1, A2 a2) + { + return ((*a0).*f)(a1, a2); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const, + A0 a0, A1 a1, A2 a2, A3 a3) + { + return ((*a0).*f)(a1, a2, a3); + } + /// + template <class Ret, class A, class A0> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)() volatile, BOOST_THREAD_RV_REF(A0) a0) + { + return ((*boost::forward<A0>(a0)).*f)(); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) volatile, A0 a0, A1 a1) + { + return ((*a0).*f)(a1); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) volatile, A0 a0, A1 a1, A2 a2) + { + return ((*a0).*f)(a1, a2); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) volatile, A0 a0, A1 a1, A2 a2, A3 a3) + { + return ((*a0).*f)(a1, a2, a3); + } + /// + template <class Ret, class A, class A0> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)() const volatile, BOOST_THREAD_RV_REF(A0) a0) + { + return ((*boost::forward<A0>(a0)).*f)(); + } + template <class Ret, class A, class A0> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)() const volatile, A0 a0) + { + return ((*a0).*f)(); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1)); + } + template <class Ret, class A, class A0, class A1> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const volatile, A0 a0, A1 a1) + { + return ((*a0).*f)(a1); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class Ret, class A, class A0, class A1, class A2> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const volatile, + A0 a0, A1 a1, A2 a2) + { + return ((*a0).*f)(a1, a2); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return ((*boost::forward<A0>(a0)).*f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + template <class Ret, class A, class A0, class A1, class A2, class A3> + inline + typename enable_if_c + < + ! is_base_of<A, typename remove_reference<A0>::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const volatile, + A0 a0, A1 a1, A2 a2, A3 a3) + { + return ((*a0).*f)(a1, a2, a3); + } + // bullet 3 + // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a + // reference to an object of type T or a reference to an object of a type derived from T; +// template <class Ret, class A, class A0> +// inline +// typename enable_if_c +// < +// is_base_of<A, typename remove_reference<A0>::type>::value, +// typename detail::apply_cv<A0, A>::type& +// >::type +// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0) +// { +// return boost::forward<A0>(a0).*f; +// } + + // bullet 4 + // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types + //described in the previous item; + +// template <class A0, class Ret, bool> +// struct d4th_helper +// { +// }; +// +// template <class A0, class Ret> +// struct d4th_helper<A0, Ret, true> +// { +// typedef typename apply_cv<decltype(*declval<A0>()), Ret>::type type; +// }; +// +// template <class Ret, class A, class A0> +// inline +// typename detail::4th_helper<A, Ret, +// !is_base_of<A, +// typename remove_reference<A0>::type +// >::value +// >::type& +// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0) +// { +// return (*boost::forward<A0>(a0)).*f; +// } + +// template <class Ret, class A, class A0> +// inline +// typename enable_if_c +// < +// !is_base_of<A, typename remove_reference<A0>::type>::value, +// typename detail::ref_return1<Ret A::*, A0>::type +// >::type +// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0) +// { +// return (*boost::forward<A0>(a0)).*f; +// } + + // bullet 5 + // f(t1, t2, ..., tN) in all other cases. + + template <class Ret, class Fp> + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f) + { + return boost::forward<Fp>(f)(); + } + template <class Ret, class Fp> + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f) + { + return f(); + } + template <class Ret, class Fp> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f) + { + return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f)); + } + + template <class Ret, class Fp, class A1> + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1) + { + return boost::forward<Fp>(f)(boost::forward<A1>(a1)); + } + template <class Ret, class Fp, class A1> + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1) + { + return f(boost::forward<A1>(a1)); + } + template <class Ret, class Fp, class A1> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1) + { + return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1)); + } + + template <class Ret, class Fp, class A1, class A2> + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class Ret, class Fp, class A1, class A2> + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return f(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class Ret, class Fp, class A1, class A2> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + + template <class Ret, class Fp, class A1, class A2, class A3> + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return boost::forward<Fp>(f)(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + template <class Ret, class Fp, class A1, class A2, class A3> + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + template <class Ret, class Fp, class A1, class A2, class A3> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + + + template <class Ret, class Fp, class A1> + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1) + { + return boost::forward<Fp>(f)(a1); + } + template <class Ret, class Fp, class A1> + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1) + { + return f(a1); + } + template <class Ret, class Fp, class A1> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1) + { + return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1); + } + + template <class Ret, class Fp, class A1, class A2> + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2) + { + return boost::forward<Fp>(f)(a1, a2); + } + template <class Ret, class Fp, class A1, class A2> + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2) + { + return f(a1, a2); + } + template <class Ret, class Fp, class A1, class A2> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2) + { + return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1, a2); + } + + template <class Ret, class Fp, class A1, class A2, class A3> + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3) + { + return boost::forward<Fp>(f)(a1, a2, a3); + } + template <class Ret, class Fp, class A1, class A2, class A3> + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3) + { + return f(a1, a2, a3); + } + template <class Ret, class Fp, class A1, class A2, class A3> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3) + { + return boost::detail::do_invoke<Ret>(boost::is_pointer<Fp>(), boost::forward<Fp>(f), a1, a2, a3); + } + + + /// + template <class Ret, class Fp> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(Fp &f) + { + return f(); + } + template <class Ret, class Fp, class A1> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1) + { + return f(boost::forward<A1>(a1)); + } + template <class Ret, class Fp, class A1> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(Fp &f, A1 a1) + { + return f(a1); + } + template <class Ret, class Fp, class A1, class A2> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return f(boost::forward<A1>(a1), boost::forward<A2>(a2)); + } + template <class Ret, class Fp, class A1, class A2> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(Fp &f, A1 a1, A2 a2) + { + return f(a1, a2); + } + template <class Ret, class Fp, class A1, class A2, class A3> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return f(boost::forward<A1>(a1), boost::forward<A2>(a2), boost::forward<A3>(a3)); + } + template <class Ret, class Fp, class A1, class A2, class A3> + inline + typename disable_if_c + < + is_member_function_pointer<Fp>::value, + Ret + >::type + invoke(Fp &f, A1 a1, A2 a2, A3 a3) + { + return f(a1, a2, a3); + } + /// + +#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES + +#endif // all + } + } + +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/detail/invoker.hpp b/3rdParty/Boost/src/boost/thread/detail/invoker.hpp new file mode 100644 index 0000000..aeac530 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/detail/invoker.hpp @@ -0,0 +1,738 @@ +// 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) + +// 2013/04 Vicente J. Botet Escriba +// Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined. +// Make use of Boost.Move +// Make use of Boost.Tuple (movable) +// 2012/11 Vicente J. Botet Escriba +// Adapt to boost libc++ implementation + +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// The invoker code is based on the one from libcxx. +//===----------------------------------------------------------------------===// + +#ifndef BOOST_THREAD_DETAIL_ASYNC_FUNCT_HPP +#define BOOST_THREAD_DETAIL_ASYNC_FUNCT_HPP + +#include <boost/config.hpp> + +#include <boost/utility/result_of.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/detail/invoke.hpp> +#include <boost/thread/detail/make_tuple_indices.hpp> +#include <boost/thread/csbl/tuple.hpp> +#include <boost/tuple/tuple.hpp> + +#include <boost/thread/detail/variadic_header.hpp> + +namespace boost +{ + namespace detail + { + +#if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE) + + template <class Fp, class ... Args> + class invoker + { + //typedef typename decay<Fp>::type Fpd; + //typedef tuple<typename decay<Args>::type...> Argsd; + + //csbl::tuple<Fpd, Argsd...> f_; + csbl::tuple<Fp, Args...> f_; + + public: + BOOST_THREAD_MOVABLE_ONLY( invoker) + //typedef typename invoke_of<_Fp, _Args...>::type Rp; + typedef typename result_of<Fp(Args...)>::type result_type; + + template <class F, class ... As> + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(As)... args) + : f_(boost::forward<F>(f), boost::forward<As>(args)...) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) : f_(boost::move(BOOST_THREAD_RV(f).f_)) + {} + + result_type operator()() + { + typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index; + return execute(Index()); + } + private: + template <size_t ...Indices> + result_type + execute(tuple_indices<Indices...>) + { + return invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...); + } + }; + + template <class R, class Fp, class ... Args> + class invoker_ret + { + //typedef typename decay<Fp>::type Fpd; + //typedef tuple<typename decay<Args>::type...> Argsd; + + //csbl::tuple<Fpd, Argsd...> f_; + csbl::tuple<Fp, Args...> f_; + + public: + BOOST_THREAD_MOVABLE_ONLY( invoker_ret) + typedef R result_type; + + template <class F, class ... As> + BOOST_SYMBOL_VISIBLE + explicit invoker_ret(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(As)... args) + : f_(boost::forward<F>(f), boost::forward<As>(args)...) + {} + + BOOST_SYMBOL_VISIBLE + invoker_ret(BOOST_THREAD_RV_REF(invoker_ret) f) : f_(boost::move(BOOST_THREAD_RV(f).f_)) + {} + + result_type operator()() + { + typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index; + return execute(Index()); + } + private: + template <size_t ...Indices> + result_type + execute(tuple_indices<Indices...>) + { + return invoke<R>(boost::move(csbl::get<0>(f_)), boost::move(csbl::get<Indices>(f_))...); + } + }; + //BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker<Fp> BOOST_THREAD_DCL_MOVABLE_END +#else + +#if ! defined BOOST_MSVC + +#define BOOST_THREAD_RV_REF_ARG_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(Arg##n) +#define BOOST_THREAD_RV_REF_A_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(A##n) +#define BOOST_THREAD_RV_REF_ARG(z, n, unused) , BOOST_THREAD_RV_REF(Arg##n) arg##n +#define BOOST_THREAD_FWD_REF_A(z, n, unused) , BOOST_THREAD_FWD_REF(A##n) arg##n +#define BOOST_THREAD_FWD_REF_ARG(z, n, unused) , BOOST_THREAD_FWD_REF(Arg##n) arg##n +#define BOOST_THREAD_FWD_PARAM(z, n, unused) , boost::forward<Arg##n>(arg##n) +#define BOOST_THREAD_FWD_PARAM_A(z, n, unused) , boost::forward<A##n>(arg##n) +#define BOOST_THREAD_DCL(z, n, unused) Arg##n v##n; +#define BOOST_THREAD_MOVE_PARAM(z, n, unused) , v##n(boost::move(arg##n)) +#define BOOST_THREAD_FORWARD_PARAM_A(z, n, unused) , v##n(boost::forward<A##n>(arg##n)) +#define BOOST_THREAD_MOVE_RHS_PARAM(z, n, unused) , v##n(boost::move(x.v##n)) +#define BOOST_THREAD_MOVE_DCL(z, n, unused) , boost::move(v##n) +#define BOOST_THREAD_MOVE_DCL_T(z, n, unused) BOOST_PP_COMMA_IF(n) boost::move(v##n) +#define BOOST_THREAD_ARG_DEF(z, n, unused) , class Arg##n = tuples::null_type + + template <class Fp, class Arg = tuples::null_type + BOOST_PP_REPEAT(BOOST_THREAD_MAX_ARGS, BOOST_THREAD_ARG_DEF, ~) + > + class invoker; + +#define BOOST_THREAD_ASYNC_FUNCT(z, n, unused) \ + template <class Fp BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class Arg) > \ + class invoker<Fp BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Arg)> \ + { \ + Fp fp_; \ + BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \ + public: \ + BOOST_THREAD_MOVABLE_ONLY(invoker) \ + typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \ + \ + template <class F BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \ + BOOST_SYMBOL_VISIBLE \ + explicit invoker(BOOST_THREAD_FWD_REF(F) f \ + BOOST_PP_REPEAT(n, BOOST_THREAD_FWD_REF_A, ~) \ + ) \ + : fp_(boost::forward<F>(f)) \ + BOOST_PP_REPEAT(n, BOOST_THREAD_FORWARD_PARAM_A, ~) \ + {} \ + \ + BOOST_SYMBOL_VISIBLE \ + invoker(BOOST_THREAD_FWD_REF(invoker) x) \ + : fp_(boost::move(x.fp_)) \ + BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \ + {} \ + \ + result_type operator()() { \ + return invoke(boost::move(fp_) \ + BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL, ~) \ + ); \ + } \ + }; \ + \ + template <class R BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class Arg) > \ + class invoker<R(*)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_ARG_T, ~)) BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, Arg)> \ + { \ + typedef R(*Fp)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_ARG_T, ~)); \ + Fp fp_; \ + BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \ + public: \ + BOOST_THREAD_MOVABLE_ONLY(invoker) \ + typedef typename result_of<Fp(BOOST_PP_ENUM_PARAMS(n, Arg))>::type result_type; \ + \ + template <class R2 BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, class A) > \ + BOOST_SYMBOL_VISIBLE \ + explicit invoker(R2(*f)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_A_T, ~)) \ + BOOST_PP_REPEAT(n, BOOST_THREAD_FWD_REF_A, ~) \ + ) \ + : fp_(f) \ + BOOST_PP_REPEAT(n, BOOST_THREAD_FORWARD_PARAM_A, ~) \ + {} \ + \ + BOOST_SYMBOL_VISIBLE \ + invoker(BOOST_THREAD_FWD_REF(invoker) x) \ + : fp_(x.fp_) \ + BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \ + {} \ + \ + result_type operator()() { \ + return fp_( \ + BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL_T, ~) \ + ); \ + } \ + }; + + BOOST_PP_REPEAT(BOOST_THREAD_MAX_ARGS, BOOST_THREAD_ASYNC_FUNCT, ~) + + #undef BOOST_THREAD_RV_REF_ARG_T + #undef BOOST_THREAD_RV_REF_ARG + #undef BOOST_THREAD_FWD_REF_ARG + #undef BOOST_THREAD_FWD_REF_A + #undef BOOST_THREAD_FWD_PARAM + #undef BOOST_THREAD_FWD_PARAM_A + #undef BOOST_THREAD_DCL + #undef BOOST_THREAD_MOVE_PARAM + #undef BOOST_THREAD_MOVE_RHS_PARAM + #undef BOOST_THREAD_MOVE_DCL + #undef BOOST_THREAD_ARG_DEF + #undef BOOST_THREAD_ASYNC_FUNCT + +#else + + template <class Fp, + class T0 = tuples::null_type, class T1 = tuples::null_type, class T2 = tuples::null_type, + class T3 = tuples::null_type, class T4 = tuples::null_type, class T5 = tuples::null_type, + class T6 = tuples::null_type, class T7 = tuples::null_type, class T8 = tuples::null_type + , class T9 = tuples::null_type + > + class invoker; + + template <class Fp, + class T0 , class T1 , class T2 , + class T3 , class T4 , class T5 , + class T6 , class T7 , class T8 > + class invoker<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8> + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + T3 v3_; + T4 v4_; + T5 v5_; + T6 v6_; + T7 v7_; + T8 v8_; + //::boost::tuple<Fp, T0, T1, T2, T3, T4, T5, T6, T7, T8> f_; + + public: + BOOST_THREAD_MOVABLE_ONLY(invoker) + typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7, T8)>::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + , BOOST_THREAD_RV_REF(T3) a3 + , BOOST_THREAD_RV_REF(T4) a4 + , BOOST_THREAD_RV_REF(T5) a5 + , BOOST_THREAD_RV_REF(T6) a6 + , BOOST_THREAD_RV_REF(T7) a7 + , BOOST_THREAD_RV_REF(T8) a8 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + , v3_(boost::move(a3)) + , v4_(boost::move(a4)) + , v5_(boost::move(a5)) + , v6_(boost::move(a6)) + , v7_(boost::move(a7)) + , v8_(boost::move(a8)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_FWD_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + , v3_(boost::move(BOOST_THREAD_RV(f).v3_)) + , v4_(boost::move(BOOST_THREAD_RV(f).v4_)) + , v5_(boost::move(BOOST_THREAD_RV(f).v5_)) + , v6_(boost::move(BOOST_THREAD_RV(f).v6_)) + , v7_(boost::move(BOOST_THREAD_RV(f).v7_)) + , v8_(boost::move(BOOST_THREAD_RV(f).v8_)) + {} + + result_type operator()() + { + return invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + , boost::move(v3_) + , boost::move(v4_) + , boost::move(v5_) + , boost::move(v6_) + , boost::move(v7_) + , boost::move(v8_) + ); + } + }; + template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7 > + class invoker<Fp, T0, T1, T2, T3, T4, T5, T6, T7> + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + T3 v3_; + T4 v4_; + T5 v5_; + T6 v6_; + T7 v7_; + public: + BOOST_THREAD_MOVABLE_ONLY(invoker) + typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6, T7)>::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + , BOOST_THREAD_RV_REF(T3) a3 + , BOOST_THREAD_RV_REF(T4) a4 + , BOOST_THREAD_RV_REF(T5) a5 + , BOOST_THREAD_RV_REF(T6) a6 + , BOOST_THREAD_RV_REF(T7) a7 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + , v3_(boost::move(a3)) + , v4_(boost::move(a4)) + , v5_(boost::move(a5)) + , v6_(boost::move(a6)) + , v7_(boost::move(a7)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_FWD_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + , v3_(boost::move(BOOST_THREAD_RV(f).v3_)) + , v4_(boost::move(BOOST_THREAD_RV(f).v4_)) + , v5_(boost::move(BOOST_THREAD_RV(f).v5_)) + , v6_(boost::move(BOOST_THREAD_RV(f).v6_)) + , v7_(boost::move(BOOST_THREAD_RV(f).v7_)) + {} + + result_type operator()() + { + return invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + , boost::move(v3_) + , boost::move(v4_) + , boost::move(v5_) + , boost::move(v6_) + , boost::move(v7_) + ); + } + }; + template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5, class T6> + class invoker<Fp, T0, T1, T2, T3, T4, T5, T6> + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + T3 v3_; + T4 v4_; + T5 v5_; + T6 v6_; + public: + BOOST_THREAD_MOVABLE_ONLY(invoker) + typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5, T6)>::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + , BOOST_THREAD_RV_REF(T3) a3 + , BOOST_THREAD_RV_REF(T4) a4 + , BOOST_THREAD_RV_REF(T5) a5 + , BOOST_THREAD_RV_REF(T6) a6 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + , v3_(boost::move(a3)) + , v4_(boost::move(a4)) + , v5_(boost::move(a5)) + , v6_(boost::move(a6)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_FWD_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + , v3_(boost::move(BOOST_THREAD_RV(f).v3_)) + , v4_(boost::move(BOOST_THREAD_RV(f).v4_)) + , v5_(boost::move(BOOST_THREAD_RV(f).v5_)) + , v6_(boost::move(BOOST_THREAD_RV(f).v6_)) + {} + + result_type operator()() + { + return invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + , boost::move(v3_) + , boost::move(v4_) + , boost::move(v5_) + , boost::move(v6_) + ); + } + }; + template <class Fp, class T0, class T1, class T2, class T3, class T4, class T5> + class invoker<Fp, T0, T1, T2, T3, T4, T5> + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + T3 v3_; + T4 v4_; + T5 v5_; + public: + BOOST_THREAD_MOVABLE_ONLY(invoker) + typedef typename result_of<Fp(T0, T1, T2, T3, T4, T5)>::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + , BOOST_THREAD_RV_REF(T3) a3 + , BOOST_THREAD_RV_REF(T4) a4 + , BOOST_THREAD_RV_REF(T5) a5 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + , v3_(boost::move(a3)) + , v4_(boost::move(a4)) + , v5_(boost::move(a5)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_FWD_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + , v3_(boost::move(BOOST_THREAD_RV(f).v3_)) + , v4_(boost::move(BOOST_THREAD_RV(f).v4_)) + , v5_(boost::move(BOOST_THREAD_RV(f).v5_)) + {} + + result_type operator()() + { + return invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + , boost::move(v3_) + , boost::move(v4_) + , boost::move(v5_) + ); + } + }; + template <class Fp, class T0, class T1, class T2, class T3, class T4> + class invoker<Fp, T0, T1, T2, T3, T4> + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + T3 v3_; + T4 v4_; + public: + BOOST_THREAD_MOVABLE_ONLY(invoker) + typedef typename result_of<Fp(T0, T1, T2, T3, T4)>::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + , BOOST_THREAD_RV_REF(T3) a3 + , BOOST_THREAD_RV_REF(T4) a4 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + , v3_(boost::move(a3)) + , v4_(boost::move(a4)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_FWD_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + , v3_(boost::move(BOOST_THREAD_RV(f).v3_)) + , v4_(boost::move(BOOST_THREAD_RV(f).v4_)) + {} + + result_type operator()() + { + return invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + , boost::move(v3_) + , boost::move(v4_) + ); + } + }; + template <class Fp, class T0, class T1, class T2, class T3> + class invoker<Fp, T0, T1, T2, T3> + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + T3 v3_; + public: + BOOST_THREAD_MOVABLE_ONLY(invoker) + typedef typename result_of<Fp(T0, T1, T2, T3)>::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + , BOOST_THREAD_RV_REF(T3) a3 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + , v3_(boost::move(a3)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_FWD_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + , v3_(boost::move(BOOST_THREAD_RV(f).v3_)) + {} + + result_type operator()() + { + return invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + , boost::move(v3_) + ); + } + }; + template <class Fp, class T0, class T1, class T2> + class invoker<Fp, T0, T1, T2> + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + public: + BOOST_THREAD_MOVABLE_ONLY(invoker) + typedef typename result_of<Fp(T0, T1, T2)>::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_FWD_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + {} + + result_type operator()() + { + return invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + ); + } + }; + template <class Fp, class T0, class T1> + class invoker<Fp, T0, T1> + { + Fp fp_; + T0 v0_; + T1 v1_; + public: + BOOST_THREAD_MOVABLE_ONLY(invoker) + typedef typename result_of<Fp(T0, T1)>::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_FWD_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + {} + + result_type operator()() + { + return invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + ); + } + }; + template <class Fp, class T0> + class invoker<Fp, T0> + { + Fp fp_; + T0 v0_; + public: + BOOST_THREAD_MOVABLE_ONLY(invoker) + typedef typename result_of<Fp(T0)>::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_FWD_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + {} + + result_type operator()() + { + return invoke(boost::move(fp_) + , boost::move(v0_) + ); + } + }; + template <class Fp> + class invoker<Fp> + { + Fp fp_; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of<Fp()>::type result_type; + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f) + : fp_(boost::move(f)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_FWD_REF(invoker) f) + : fp_(boost::move(f.fp_)) + {} + result_type operator()() + { + return fp_(); + } + }; + template <class R> + class invoker<R(*)()> + { + typedef R(*Fp)(); + Fp fp_; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of<Fp()>::type result_type; + BOOST_SYMBOL_VISIBLE + explicit invoker(Fp f) + : fp_(f) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_FWD_REF(invoker) f) + : fp_(f.fp_) + {} + result_type operator()() + { + return fp_(); + } + }; +#endif +#endif + + } +} + +#include <boost/thread/detail/variadic_footer.hpp> + +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/detail/is_convertible.hpp b/3rdParty/Boost/src/boost/thread/detail/is_convertible.hpp new file mode 100644 index 0000000..b77620c --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/detail/is_convertible.hpp @@ -0,0 +1,49 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2013 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) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_THREAD_DETAIL_IS_CONVERTIBLE_HPP +#define BOOST_THREAD_DETAIL_IS_CONVERTIBLE_HPP + +#include <boost/type_traits/is_convertible.hpp> +#include <boost/thread/detail/move.hpp> + +namespace boost +{ + namespace thread_detail + { + template <typename T1, typename T2> + struct is_convertible : boost::is_convertible<T1,T2> {}; + +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES + +#if defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION <= 1300) + +#if defined BOOST_THREAD_USES_MOVE + template <typename T1, typename T2> + struct is_convertible< + rv<T1> &, + rv<rv<T2> > & + > : false_type {}; +#endif + +#elif defined __GNUC__ && (__GNUC__ < 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ <= 4 )) + + template <typename T1, typename T2> + struct is_convertible<T1&, T2&> : boost::is_convertible<T1, T2> {}; +#endif + +#endif + } + +} // namespace boost + + +#endif // BOOST_THREAD_DETAIL_MEMORY_HPP diff --git a/3rdParty/Boost/src/boost/thread/detail/lockable_wrapper.hpp b/3rdParty/Boost/src/boost/thread/detail/lockable_wrapper.hpp new file mode 100644 index 0000000..8dc5a6c --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/detail/lockable_wrapper.hpp @@ -0,0 +1,45 @@ +// 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 2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_DETAIL_LOCKABLE_WRAPPER_HPP +#define BOOST_THREAD_DETAIL_LOCKABLE_WRAPPER_HPP + +#include <boost/thread/detail/config.hpp> + +#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST +#include <initializer_list> +#endif +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + +#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST + namespace thread_detail + { + template <typename Mutex> + struct lockable_wrapper + { + Mutex* m; + explicit lockable_wrapper(Mutex& m_) : + m(&m_) + {} + }; + template <typename Mutex> + struct lockable_adopt_wrapper + { + Mutex* m; + explicit lockable_adopt_wrapper(Mutex& m_) : + m(&m_) + {} + }; + } +#endif + +} + +#include <boost/config/abi_suffix.hpp> + +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/detail/make_tuple_indices.hpp b/3rdParty/Boost/src/boost/thread/detail/make_tuple_indices.hpp new file mode 100644 index 0000000..73d54f1 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/detail/make_tuple_indices.hpp @@ -0,0 +1,224 @@ +// Copyright (C) 2012-2013 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) + +// 2013/04 Vicente J. Botet Escriba +// Provide implementation up to 10 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined. +// 2012/11 Vicente J. Botet Escriba +// Adapt to boost libc++ implementation + +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// The make_tuple_indices C++11 code is based on the one from libcxx. +//===----------------------------------------------------------------------===// + +#ifndef BOOST_THREAD_DETAIL_MAKE_TUPLE_INDICES_HPP +#define BOOST_THREAD_DETAIL_MAKE_TUPLE_INDICES_HPP + +#include <boost/config.hpp> +#include <boost/static_assert.hpp> + +namespace boost +{ + namespace detail + { + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + // make_tuple_indices + + template <std::size_t...> struct tuple_indices + {}; + + template <std::size_t Sp, class IntTuple, std::size_t Ep> + struct make_indices_imp; + + template <std::size_t Sp, std::size_t ...Indices, std::size_t Ep> + struct make_indices_imp<Sp, tuple_indices<Indices...>, Ep> + { + typedef typename make_indices_imp<Sp+1, tuple_indices<Indices..., Sp>, Ep>::type type; + }; + + template <std::size_t Ep, std::size_t ...Indices> + struct make_indices_imp<Ep, tuple_indices<Indices...>, Ep> + { + typedef tuple_indices<Indices...> type; + }; + + template <std::size_t Ep, std::size_t Sp = 0> + struct make_tuple_indices + { + BOOST_STATIC_ASSERT_MSG(Sp <= Ep, "make_tuple_indices input error"); + typedef typename make_indices_imp<Sp, tuple_indices<>, Ep>::type type; + }; +#else + + // - tuple forward declaration ----------------------------------------------- + template < + std::size_t T0 = 0, std::size_t T1 = 0, std::size_t T2 = 0, + std::size_t T3 = 0, std::size_t T4 = 0, std::size_t T5 = 0, + std::size_t T6 = 0, std::size_t T7 = 0, std::size_t T8 = 0, + std::size_t T9 = 0> + class tuple_indices {}; + + template <std::size_t Sp, class IntTuple, std::size_t Ep> + struct make_indices_imp; + + template <std::size_t Sp, std::size_t Ep> + struct make_indices_imp<Sp, tuple_indices<>, Ep> + { + typedef typename make_indices_imp<Sp+1, tuple_indices<Sp>, Ep>::type type; + }; + template <std::size_t Sp, std::size_t I0, std::size_t Ep> + struct make_indices_imp<Sp, tuple_indices<I0>, Ep> + { + typedef typename make_indices_imp<Sp+1, tuple_indices<I0, Sp>, Ep>::type type; + }; + template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t Ep> + struct make_indices_imp<Sp, tuple_indices<I0, I1>, Ep> + { + typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, Sp>, Ep>::type type; + }; + template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t Ep> + struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2>, Ep> + { + typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, Sp>, Ep>::type type; + }; + template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t Ep> + struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3>, Ep> + { + typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, Sp>, Ep>::type type; + }; + template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t Ep> + struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3, I4>, Ep> + { + typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, I4, Sp>, Ep>::type type; + }; + template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5, std::size_t Ep> + struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3, I4, I5>, Ep> + { + typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, I4, I5, Sp>, Ep>::type type; + }; + template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5 + , std::size_t I6 + , std::size_t Ep> + struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3, I4, I5, I6>, Ep> + { + typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, I4, I5, I6, Sp>, Ep>::type type; + }; + template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5 + , std::size_t I6 + , std::size_t I7 + , std::size_t Ep> + struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3, I4, I5, I6, I7>, Ep> + { + typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, Sp>, Ep>::type type; + }; + template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5 + , std::size_t I6 + , std::size_t I7 + , std::size_t I8 + , std::size_t Ep> + struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3, I4, I5, I6, I7, I8>, Ep> + { + typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, I8, Sp>, Ep>::type type; + }; +// template <std::size_t Sp, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5 +// , std::size_t I6 +// , std::size_t I7 +// , std::size_t I8 +// , std::size_t I9 +// , std::size_t Ep> +// struct make_indices_imp<Sp, tuple_indices<I0, I1 , I2, I3, I4, I5, I6, I7, I8, I9>, Ep> +// { +// typedef typename make_indices_imp<Sp+1, tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, Sp>, Ep>::type type; +// }; + + template <std::size_t Ep> + struct make_indices_imp<Ep, tuple_indices<>, Ep> + { + typedef tuple_indices<> type; + }; + template <std::size_t Ep, std::size_t I0> + struct make_indices_imp<Ep, tuple_indices<I0>, Ep> + { + typedef tuple_indices<I0> type; + }; + template <std::size_t Ep, std::size_t I0, std::size_t I1> + struct make_indices_imp<Ep, tuple_indices<I0, I1>, Ep> + { + typedef tuple_indices<I0, I1> type; + }; + template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2> + struct make_indices_imp<Ep, tuple_indices<I0, I1, I2>, Ep> + { + typedef tuple_indices<I0, I1, I2> type; + }; + template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3> + struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3>, Ep> + { + typedef tuple_indices<I0, I1, I2, I3> type; + }; + template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4> + struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3, I4>, Ep> + { + typedef tuple_indices<I0, I1, I2, I3, I4> type; + }; + template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5> + struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3, I4, I5>, Ep> + { + typedef tuple_indices<I0, I1, I2, I3, I4, I5> type; + }; + template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5 + , std::size_t I6 + > + struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3, I4, I5, I6>, Ep> + { + typedef tuple_indices<I0, I1, I2, I3, I4, I5, I6> type; + }; + template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5 + , std::size_t I6 + , std::size_t I7 + > + struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7>, Ep> + { + typedef tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7> type; + }; + template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5 + , std::size_t I6 + , std::size_t I7 + , std::size_t I8 + > + struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, I8>, Ep> + { + typedef tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, I8> type; + }; + + template <std::size_t Ep, std::size_t I0, std::size_t I1, std::size_t I2, std::size_t I3, std::size_t I4, std::size_t I5 + , std::size_t I6 + , std::size_t I7 + , std::size_t I8 + , std::size_t I9 + > + struct make_indices_imp<Ep, tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, I8, I9>, Ep> + { + typedef tuple_indices<I0, I1, I2, I3, I4, I5, I6, I7, I8, I9> type; + }; + + template <std::size_t Ep, std::size_t Sp = 0> + struct make_tuple_indices + { + BOOST_STATIC_ASSERT_MSG(Sp <= Ep, "make_tuple_indices input error"); + typedef typename make_indices_imp<Sp, tuple_indices<>, Ep>::type type; + }; + +#endif + } +} + +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/detail/memory.hpp b/3rdParty/Boost/src/boost/thread/detail/memory.hpp index 3c1692d..51ce84f 100644 --- a/3rdParty/Boost/src/boost/thread/detail/memory.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/memory.hpp @@ -1,8 +1,9 @@ ////////////////////////////////////////////////////////////////////////////// // -// (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) +// Copyright (C) 2011-2013 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) // // See http://www.boost.org/libs/thread for documentation. // @@ -12,14 +13,11 @@ #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> + +#include <boost/thread/csbl/memory/pointer_traits.hpp> +#include <boost/thread/csbl/memory/allocator_arg.hpp> +#include <boost/thread/csbl/memory/allocator_traits.hpp> +#include <boost/thread/csbl/memory/scoped_allocator.hpp> namespace boost { @@ -28,7 +26,7 @@ namespace boost template <class _Alloc> class allocator_destructor { - typedef container::allocator_traits<_Alloc> alloc_traits; + typedef csbl::allocator_traits<_Alloc> alloc_traits; public: typedef typename alloc_traits::pointer pointer; typedef typename alloc_traits::size_type size_type; @@ -46,111 +44,5 @@ namespace boost } }; } //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 f2665e6..c3339ef 100644 --- a/3rdParty/Boost/src/boost/thread/detail/move.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/move.hpp @@ -9,24 +9,34 @@ #include <boost/thread/detail/config.hpp> #ifndef BOOST_NO_SFINAE -#include <boost/utility/enable_if.hpp> +#include <boost/core/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> +#include <boost/type_traits/conditional.hpp> +#include <boost/type_traits/remove_extent.hpp> +#include <boost/type_traits/is_array.hpp> +#include <boost/type_traits/is_function.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/add_pointer.hpp> +#include <boost/type_traits/decay.hpp> #endif #include <boost/thread/detail/delete.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility.hpp> +#include <boost/move/traits.hpp> #include <boost/config/abi_prefix.hpp> - +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#include <type_traits> +#endif namespace boost { namespace detail { template <typename T> - struct has_move_emulation_enabled_aux_dummy_specialization; + struct enable_move_utility_emulation_dummy_specialization; template<typename T> struct thread_move_t { @@ -49,6 +59,7 @@ namespace boost }; } +#if !defined BOOST_THREAD_USES_MOVE #ifndef BOOST_NO_SFINAE template<typename T> @@ -63,11 +74,14 @@ namespace boost { return t; } + +#endif //#if !defined BOOST_THREAD_USES_MOVE } #if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES #define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE) +#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(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 @@ -77,16 +91,17 @@ namespace boost #define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ namespace detail { \ template <typename T> \ - struct has_move_emulation_enabled_aux_dummy_specialization< + struct enable_move_utility_emulation_dummy_specialization< #define BOOST_THREAD_DCL_MOVABLE_END > \ - : integral_constant<bool, true> \ + : integral_constant<bool, false> \ {}; \ } #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_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(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 @@ -96,10 +111,10 @@ namespace boost #define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ namespace detail { \ template <typename T> \ - struct has_move_emulation_enabled_aux_dummy_specialization< + struct enable_move_utility_emulation_dummy_specialization< #define BOOST_THREAD_DCL_MOVABLE_END > \ - : integral_constant<bool, true> \ + : integral_constant<bool, false> \ {}; \ } @@ -107,6 +122,7 @@ namespace boost #if defined BOOST_THREAD_USES_MOVE #define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE) +#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(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 @@ -115,10 +131,10 @@ namespace boost #define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ namespace detail { \ template <typename T> \ - struct has_move_emulation_enabled_aux_dummy_specialization< + struct enable_move_utility_emulation_dummy_specialization< #define BOOST_THREAD_DCL_MOVABLE_END > \ - : integral_constant<bool, true> \ + : integral_constant<bool, false> \ {}; \ } @@ -132,17 +148,19 @@ namespace boost #define BOOST_THREAD_DCL_MOVABLE(TYPE) \ template <> \ -struct has_move_emulation_enabled_aux< TYPE > \ - : BOOST_MOVE_BOOST_NS::integral_constant<bool, true> \ -{}; +struct enable_move_utility_emulation< TYPE > \ +{ \ + static const bool value = false; \ +}; #define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ template <typename T> \ -struct has_move_emulation_enabled_aux< +struct enable_move_utility_emulation< #define BOOST_THREAD_DCL_MOVABLE_END > \ - : BOOST_MOVE_BOOST_NS::integral_constant<bool, true> \ -{}; +{ \ + static const bool value = false; \ +}; #endif @@ -227,19 +245,69 @@ namespace detail -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES namespace boost -{ namespace thread_detail +{ + namespace thread_detail + { +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template <class Tp> + struct remove_reference : boost::remove_reference<Tp> {}; + template <class Tp> + struct decay : boost::decay<Tp> {}; +#else + template <class Tp> + struct remove_reference { + typedef Tp type; + }; + template <class Tp> + struct remove_reference<Tp&> + { + typedef Tp type; + }; + template <class Tp> + struct remove_reference< rv<Tp> > { + typedef Tp type; + }; + + template <class Tp> + struct decay + { + private: + typedef typename boost::move_detail::remove_rvalue_reference<Tp>::type Up0; + typedef typename boost::remove_reference<Up0>::type Up; + public: + typedef typename conditional + < + is_array<Up>::value, + typename remove_extent<Up>::type*, + typename conditional + < + is_function<Up>::value, + typename add_pointer<Up>::type, + typename remove_cv<Up>::type + >::type + >::type type; + }; +#endif + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES template <class T> typename decay<T>::type decay_copy(T&& t) { return boost::forward<T>(t); } +#else + template <class T> + typename decay<T>::type + decay_copy(BOOST_THREAD_FWD_REF(T) t) + { + return boost::forward<T>(t); } -} #endif + } +} #include <boost/config/abi_suffix.hpp> diff --git a/3rdParty/Boost/src/boost/thread/detail/nullary_function.hpp b/3rdParty/Boost/src/boost/thread/detail/nullary_function.hpp new file mode 100644 index 0000000..26d1390 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/detail/nullary_function.hpp @@ -0,0 +1,213 @@ +// Copyright (C) 2013 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) +// +// 2013/09 Vicente J. Botet Escriba +// Adapt to boost from CCIA C++11 implementation +// Make use of Boost.Move + +#ifndef BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP +#define BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP + +#include <boost/config.hpp> +#include <boost/thread/detail/memory.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/type_traits/decay.hpp> + +namespace boost +{ + namespace detail + { + + template <typename F> + class nullary_function; + template <> + class nullary_function<void()> + { + struct impl_base + { + virtual void call()=0; + virtual ~impl_base() + { + } + }; + shared_ptr<impl_base> impl; + template <typename F> + struct impl_type: impl_base + { + F f; +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + impl_type(F &f_) + : f(f_) + {} +#endif + impl_type(BOOST_THREAD_RV_REF(F) f_) + : f(boost::move(f_)) + {} + + void call() + { + f(); + } + }; + struct impl_type_ptr: impl_base + { + void (*f)(); + impl_type_ptr(void (*f_)()) + : f(f_) + {} + void call() + { + f(); + } + }; + public: + BOOST_THREAD_MOVABLE(nullary_function) + + explicit nullary_function(void (*f)()): + impl(new impl_type_ptr(f)) + {} + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + template<typename F> + explicit nullary_function(F& f): + impl(new impl_type<F>(f)) + {} +#endif + template<typename F> + nullary_function(BOOST_THREAD_RV_REF(F) f): + impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f)))) + {} + + nullary_function() + : impl() + { + } + nullary_function(nullary_function const& other) BOOST_NOEXCEPT : + impl(other.impl) + { + } + nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT : + impl(BOOST_THREAD_RV(other).impl) + { + BOOST_THREAD_RV(other).impl.reset(); + } + ~nullary_function() + { + } + + nullary_function& operator=(nullary_function const& other) BOOST_NOEXCEPT + { + impl=other.impl; + return *this; + } + nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT + { + impl=BOOST_THREAD_RV(other).impl; + BOOST_THREAD_RV(other).impl.reset(); + return *this; + } + + + void operator()() + { impl->call();} + + }; + + template <typename R> + class nullary_function<R()> + { + struct impl_base + { + virtual R call()=0; + virtual ~impl_base() + { + } + }; + shared_ptr<impl_base> impl; + template <typename F> + struct impl_type: impl_base + { + F f; +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + impl_type(F &f_) + : f(f_) + {} +#endif + impl_type(BOOST_THREAD_RV_REF(F) f_) + : f(boost::move(f_)) + {} + + R call() + { + return f(); + } + }; + struct impl_type_ptr: impl_base + { + R (*f)(); + impl_type_ptr(R (*f_)()) + : f(f_) + {} + + R call() + { + return f(); + } + }; + public: + BOOST_THREAD_MOVABLE(nullary_function) + + nullary_function(R (*f)()): + impl(new impl_type_ptr(f)) + {} +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + template<typename F> + nullary_function(F& f): + impl(new impl_type<F>(f)) + {} +#endif + template<typename F> + nullary_function(BOOST_THREAD_RV_REF(F) f): + impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f)))) + {} + + nullary_function(nullary_function const& other) BOOST_NOEXCEPT : + impl(other.impl) + { + } + nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT : + impl(BOOST_THREAD_RV(other).impl) + { + BOOST_THREAD_RV(other).impl.reset(); + } + nullary_function() + : impl() + { + } + ~nullary_function() + { + } + + nullary_function& operator=(nullary_function const& other) BOOST_NOEXCEPT + { + impl=other.impl; + return *this; + } + nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT + { + impl=BOOST_THREAD_RV(other).impl; + BOOST_THREAD_RV(other).impl.reset(); + return *this; + } + + R operator()() + { return impl->call();} + + }; + } +} + +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/detail/thread.hpp b/3rdParty/Boost/src/boost/thread/detail/thread.hpp index 2590f45..520ca26 100644 --- a/3rdParty/Boost/src/boost/thread/detail/thread.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/thread.hpp @@ -3,29 +3,33 @@ // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// (C) Copyright 2007-10 Anthony Williams -// (C) Copyright 20011-12 Vicente J. Botet Escriba +// (C) Copyright 2007-2010 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba #include <boost/thread/detail/config.hpp> + #include <boost/thread/exceptions.hpp> #ifndef BOOST_NO_IOSTREAM #include <ostream> #endif #include <boost/thread/detail/move.hpp> #include <boost/thread/mutex.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/thread/xtime.hpp> +#endif #include <boost/thread/detail/thread_heap_alloc.hpp> +#include <boost/thread/detail/make_tuple_indices.hpp> +#include <boost/thread/detail/invoke.hpp> +#include <boost/thread/detail/is_convertible.hpp> #include <boost/assert.hpp> #include <list> #include <algorithm> -#include <boost/ref.hpp> +#include <boost/core/ref.hpp> #include <boost/cstdint.hpp> #include <boost/bind.hpp> #include <stdlib.h> #include <memory> -//#include <vector> -//#include <utility> -#include <boost/utility/enable_if.hpp> +#include <boost/core/enable_if.hpp> #include <boost/type_traits/remove_reference.hpp> #include <boost/io/ios_state.hpp> #include <boost/type_traits/is_same.hpp> @@ -36,6 +40,9 @@ #include <boost/chrono/ceil.hpp> #endif +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#include <tuple> +#endif #include <boost/config/abi_prefix.hpp> #ifdef BOOST_MSVC @@ -48,6 +55,36 @@ namespace boost namespace detail { + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + + template<typename F, class ...ArgTypes> + class thread_data: + public detail::thread_data_base + { + public: + BOOST_THREAD_NO_COPYABLE(thread_data) + thread_data(BOOST_THREAD_RV_REF(F) f_, BOOST_THREAD_RV_REF(ArgTypes)... args_): + fp(boost::forward<F>(f_), boost::forward<ArgTypes>(args_)...) + {} + template <std::size_t ...Indices> + void run2(tuple_indices<Indices...>) + { + + invoke(std::move(std::get<0>(fp)), std::move(std::get<Indices>(fp))...); + } + void run() + { + typedef typename make_tuple_indices<std::tuple_size<std::tuple<F, ArgTypes...> >::value, 1>::type index_type; + + run2(index_type()); + } + + private: + std::tuple<typename decay<F>::type, typename decay<ArgTypes>::type...> fp; + }; +#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template<typename F> class thread_data: public detail::thread_data_base @@ -115,6 +152,7 @@ namespace boost f(); } }; +#endif } class BOOST_THREAD_DECL thread @@ -125,24 +163,55 @@ namespace boost BOOST_THREAD_MOVABLE_ONLY(thread) private: + struct dummy; + void release_handle(); detail::thread_data_ptr thread_info; - void start_thread(); - void start_thread(const attributes& attr); + private: + bool start_thread_noexcept(); + bool start_thread_noexcept(const attributes& attr); + //public: + void start_thread() + { + if (!start_thread_noexcept()) + { + boost::throw_exception(thread_resource_error()); + } + } + void start_thread(const attributes& attr) + { + if (!start_thread_noexcept(attr)) + { + boost::throw_exception(thread_resource_error()); + } + } explicit thread(detail::thread_data_ptr data); detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template<typename F, class ...ArgTypes> + static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_RV_REF(ArgTypes)... args) + { + return detail::thread_data_ptr(detail::heap_new< + detail::thread_data<typename boost::remove_reference<F>::type, ArgTypes...> + >( + boost::forward<F>(f), boost::forward<ArgTypes>(args)... + ) + ); + } +#else template<typename 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> >( boost::forward<F>(f))); } +#endif static inline detail::thread_data_ptr make_thread_info(void (*f)()) { return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >( @@ -150,7 +219,12 @@ namespace boost } #else template<typename F> - static inline detail::thread_data_ptr make_thread_info(F f) + static inline detail::thread_data_ptr make_thread_info(F f + , typename disable_if_c< + //boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value || + is_same<typename decay<F>::type, thread>::value, + dummy* >::type=0 + ) { return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f)); } @@ -161,7 +235,6 @@ 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) @@ -171,6 +244,7 @@ namespace boost thread() BOOST_NOEXCEPT; ~thread() { + #if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE if (joinable()) { std::terminate(); @@ -184,7 +258,7 @@ namespace boost class F > explicit thread(BOOST_THREAD_RV_REF(F) f - , typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0 + //, 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)))) { @@ -193,7 +267,7 @@ namespace boost template < class F > - thread(attributes& attrs, BOOST_THREAD_RV_REF(F) f): + thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f): thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f)))) { start_thread(attrs); @@ -208,7 +282,7 @@ namespace boost start_thread(); } template <class F> - thread(attributes& attrs, F f): + thread(attributes const& attrs, F f): thread_info(make_thread_info(f)) { start_thread(attrs); @@ -216,15 +290,19 @@ namespace boost #else template <class F> 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): + , typename disable_if_c< + boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F)>::value + //|| is_same<typename decay<F>::type, thread>::value + , 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(attributes const& attrs, F f + , typename disable_if<boost::thread_detail::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0 + ): thread_info(make_thread_info(f)) { start_thread(attrs); @@ -234,19 +312,27 @@ namespace boost 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)) +#ifdef BOOST_THREAD_USES_MOVE + thread_info(make_thread_info(boost::move<F>(f))) // todo : Add forward +#else + thread_info(make_thread_info(f)) // todo : Add forward +#endif { start_thread(); } template <class F> - thread(attributes& attrs, BOOST_THREAD_RV_REF(F) f): - thread_info(make_thread_info(f)) + thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f): +#ifdef BOOST_THREAD_USES_MOVE + thread_info(make_thread_info(boost::move<F>(f))) // todo : Add forward +#else + thread_info(make_thread_info(f)) // todo : Add forward +#endif { start_thread(attrs); } #endif - thread(BOOST_THREAD_RV_REF(thread) x) + thread(BOOST_THREAD_RV_REF(thread) x) BOOST_NOEXCEPT { thread_info=BOOST_THREAD_RV(x).thread_info; BOOST_THREAD_RV(x).thread_info.reset(); @@ -272,8 +358,32 @@ namespace boost return *this; } +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template <class F, class Arg, class ...Args> + thread(F&& f, Arg&& arg, Args&&... args) : + thread_info(make_thread_info( + thread_detail::decay_copy(boost::forward<F>(f)), + thread_detail::decay_copy(boost::forward<Arg>(arg)), + thread_detail::decay_copy(boost::forward<Args>(args))...) + ) + + { + start_thread(); + } + template <class F, class Arg, class ...Args> + thread(attributes const& attrs, F&& f, Arg&& arg, Args&&... args) : + thread_info(make_thread_info( + thread_detail::decay_copy(boost::forward<F>(f)), + thread_detail::decay_copy(boost::forward<Arg>(arg)), + thread_detail::decay_copy(boost::forward<Args>(args))...) + ) + + { + start_thread(attrs); + } +#else template <class F,class A1> - thread(F f,A1 a1,typename disable_if<boost::is_convertible<F&,thread_attributes >, dummy* >::type=0): + thread(F f,A1 a1,typename disable_if<boost::thread_detail::is_convertible<F&,thread_attributes >, dummy* >::type=0): thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1))) { start_thread(); @@ -333,31 +443,53 @@ namespace boost { start_thread(); } - +#endif void swap(thread& x) BOOST_NOEXCEPT { thread_info.swap(x.thread_info); } - class BOOST_SYMBOL_VISIBLE id; + class id; +#ifdef BOOST_THREAD_PLATFORM_PTHREAD + inline id get_id() const BOOST_NOEXCEPT; +#else id get_id() const BOOST_NOEXCEPT; +#endif bool joinable() const BOOST_NOEXCEPT; - void join(); + private: + bool join_noexcept(); + public: + inline void join(); + #ifdef BOOST_THREAD_USES_CHRONO +#if defined(BOOST_THREAD_PLATFORM_WIN32) + template <class Rep, class Period> + bool try_join_for(const chrono::duration<Rep, Period>& rel_time) + { + chrono::milliseconds rel_time2= chrono::ceil<chrono::milliseconds>(rel_time); + return do_try_join_until(rel_time2.count()); + } +#else 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); } +#endif 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)); + bool joined= false; + do { + typename Clock::duration d = ceil<nanoseconds>(t-Clock::now()); + if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached + joined = try_join_until(s_now + d); + } while (! joined); + return true; } template <class Duration> bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t) @@ -368,10 +500,15 @@ namespace boost } #endif #if defined(BOOST_THREAD_PLATFORM_WIN32) - bool timed_join(const system_time& abs_time); private: - bool do_try_join_until(uintmax_t milli); + bool do_try_join_until_noexcept(uintmax_t milli, bool& res); + inline bool do_try_join_until(uintmax_t milli); public: + bool timed_join(const system_time& abs_time); + //{ + // return do_try_join_until(get_milliseconds_until(wait_until)); + //} + #ifdef BOOST_THREAD_USES_CHRONO bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp) { @@ -382,49 +519,53 @@ namespace boost #else + private: + bool do_try_join_until_noexcept(struct timespec const &timeout, bool& res); + inline bool do_try_join_until(struct timespec const &timeout); + public: +#if defined BOOST_THREAD_USES_DATETIME bool timed_join(const system_time& abs_time) { - struct timespec const ts=detail::get_timespec(abs_time); + struct timespec const ts=detail::to_timespec(abs_time); return do_try_join_until(ts); } +#endif #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()); + timespec ts = boost::detail::to_timespec(d); return do_try_join_until(ts); } #endif - private: - bool do_try_join_until(struct timespec const &timeout); - public: #endif + public: +#if defined BOOST_THREAD_USES_DATETIME template<typename TimeDuration> inline bool timed_join(TimeDuration const& rel_time) { return timed_join(get_system_time()+rel_time); } - +#endif void detach(); static unsigned hardware_concurrency() BOOST_NOEXCEPT; + static unsigned physical_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 +#if defined BOOST_THREAD_PROVIDES_THREAD_EQ // Use thread::id when comparisions are needed // backwards compatibility bool operator==(const thread& other) const; bool operator!=(const thread& other) const; #endif +#if defined BOOST_THREAD_USES_DATETIME static inline void yield() BOOST_NOEXCEPT { this_thread::yield(); @@ -434,10 +575,13 @@ namespace boost { this_thread::sleep(xt); } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS // extensions void interrupt(); bool interruption_requested() const BOOST_NOEXCEPT; +#endif }; inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT @@ -456,16 +600,24 @@ namespace boost namespace this_thread { +#ifdef BOOST_THREAD_PLATFORM_PTHREAD + inline thread::id get_id() BOOST_NOEXCEPT; +#else thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT; +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void BOOST_THREAD_DECL interruption_point(); bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT; bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT; +#endif +#if defined BOOST_THREAD_USES_DATETIME inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time) { sleep(system_time(abs_time)); } +#endif } class BOOST_SYMBOL_VISIBLE thread::id @@ -501,11 +653,7 @@ namespace boost public: 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 @@ -583,6 +731,61 @@ namespace boost #endif }; +#ifdef BOOST_THREAD_PLATFORM_PTHREAD + thread::id thread::get_id() const BOOST_NOEXCEPT + { + #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID + return const_cast<thread*>(this)->native_handle(); + #else + detail::thread_data_ptr const local_thread_info=(get_thread_info)(); + return (local_thread_info? id(local_thread_info) : id()); + #endif + } + + namespace this_thread + { + inline thread::id get_id() BOOST_NOEXCEPT + { + #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID + return pthread_self(); + #else + boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data(); + return (thread_info?thread::id(thread_info->shared_from_this()):thread::id()); + #endif + } + } +#endif + void thread::join() { + if (this_thread::get_id() == get_id()) + boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself")); + + BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(), + thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable") + ); + } + +#ifdef BOOST_THREAD_PLATFORM_PTHREAD + bool thread::do_try_join_until(struct timespec const &timeout) +#else + bool thread::do_try_join_until(uintmax_t timeout) +#endif + { + if (this_thread::get_id() == get_id()) + boost::throw_exception(thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself")); + bool res; + if (do_try_join_until_noexcept(timeout, res)) + { + return res; + } + else + { + BOOST_THREAD_THROW_ELSE_RETURN( + (thread_resource_error(static_cast<int>(system::errc::invalid_argument), "boost thread: thread not joinable")), + false + ); + } + } + #if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template<class charT, class traits> BOOST_SYMBOL_VISIBLE @@ -593,7 +796,7 @@ namespace boost } #endif -#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 +#if defined BOOST_THREAD_PROVIDES_THREAD_EQ inline bool thread::operator==(const thread& other) const { return get_id()==other.get_id(); @@ -631,6 +834,19 @@ namespace boost }; void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*); + struct shared_state_base; +#if defined(BOOST_THREAD_PLATFORM_WIN32) + inline void make_ready_at_thread_exit(shared_ptr<shared_state_base> as) + { + detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); + if(current_thread_data) + { + current_thread_data->make_ready_at_thread_exit(as); + } + } +#else + void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr<shared_state_base> as); +#endif } namespace this_thread diff --git a/3rdParty/Boost/src/boost/thread/detail/thread_group.hpp b/3rdParty/Boost/src/boost/thread/detail/thread_group.hpp index f1ccdf8..69ce991 100644 --- a/3rdParty/Boost/src/boost/thread/detail/thread_group.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/thread_group.hpp @@ -8,6 +8,7 @@ #include <list> #include <boost/thread/shared_mutex.hpp> #include <boost/thread/mutex.hpp> +#include <boost/thread/lock_guard.hpp> #include <boost/config/abi_prefix.hpp> @@ -22,7 +23,7 @@ namespace boost { private: thread_group(thread_group const&); - thread_group& operator=(thread_group const&); + thread_group& operator=(thread_group const&); public: thread_group() {} ~thread_group() @@ -35,6 +36,41 @@ namespace boost } } + bool is_this_thread_in() + { + thread::id id = this_thread::get_id(); + boost::shared_lock<shared_mutex> guard(m); + for(std::list<thread*>::iterator it=threads.begin(),end=threads.end(); + it!=end; + ++it) + { + if ((*it)->get_id() == id) + return true; + } + return false; + } + + bool is_thread_in(thread* thrd) + { + if(thrd) + { + thread::id id = thrd->get_id(); + boost::shared_lock<shared_mutex> guard(m); + for(std::list<thread*>::iterator it=threads.begin(),end=threads.end(); + it!=end; + ++it) + { + if ((*it)->get_id() == id) + return true; + } + return false; + } + else + { + return false; + } + } + template<typename F> thread* create_thread(F threadfunc) { @@ -43,16 +79,20 @@ namespace boost threads.push_back(new_thread.get()); return new_thread.release(); } - + void add_thread(thread* thrd) { if(thrd) { + BOOST_THREAD_ASSERT_PRECONDITION( ! is_thread_in(thrd) , + thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost::thread_group: trying to add a duplicated thread") + ); + boost::lock_guard<shared_mutex> guard(m); threads.push_back(thrd); } } - + void remove_thread(thread* thrd) { boost::lock_guard<shared_mutex> guard(m); @@ -62,23 +102,28 @@ namespace boost threads.erase(it); } } - + void join_all() { + BOOST_THREAD_ASSERT_PRECONDITION( ! is_this_thread_in() , + thread_resource_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost::thread_group: trying joining itself") + ); boost::shared_lock<shared_mutex> guard(m); - + for(std::list<thread*>::iterator it=threads.begin(),end=threads.end(); it!=end; ++it) { + if ((*it)->joinable()) (*it)->join(); } } - + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void interrupt_all() { boost::shared_lock<shared_mutex> guard(m); - + for(std::list<thread*>::iterator it=threads.begin(),end=threads.end(); it!=end; ++it) @@ -86,13 +131,14 @@ namespace boost (*it)->interrupt(); } } - +#endif + size_t size() const { boost::shared_lock<shared_mutex> guard(m); return threads.size(); } - + private: std::list<thread*> threads; mutable shared_mutex m; diff --git a/3rdParty/Boost/src/boost/thread/detail/thread_interruption.hpp b/3rdParty/Boost/src/boost/thread/detail/thread_interruption.hpp index f1a165c..5d7d10f 100644 --- a/3rdParty/Boost/src/boost/thread/detail/thread_interruption.hpp +++ b/3rdParty/Boost/src/boost/thread/detail/thread_interruption.hpp @@ -9,6 +9,8 @@ #include <boost/thread/detail/config.hpp> #include <boost/thread/detail/delete.hpp> +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + namespace boost { namespace this_thread @@ -33,4 +35,5 @@ namespace boost } } -#endif +#endif // BOOST_THREAD_PROVIDES_INTERRUPTIONS +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/detail/variadic_footer.hpp b/3rdParty/Boost/src/boost/thread/detail/variadic_footer.hpp new file mode 100644 index 0000000..9ae25a8 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/detail/variadic_footer.hpp @@ -0,0 +1,10 @@ +// Copyright (C) 2013 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) + + +#if defined BOOST_NO_CXX11_VARIADIC_TEMPLATES + + +#endif diff --git a/3rdParty/Boost/src/boost/thread/detail/variadic_header.hpp b/3rdParty/Boost/src/boost/thread/detail/variadic_header.hpp new file mode 100644 index 0000000..8015ae3 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/detail/variadic_header.hpp @@ -0,0 +1,19 @@ +// Copyright (C) 2013 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/config.hpp> + +//#if defined BOOST_NO_CXX11_VARIADIC_TEMPLATES + +#include <boost/preprocessor/facilities/intercept.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> + +#ifndef BOOST_THREAD_MAX_ARGS +#define BOOST_THREAD_MAX_ARGS 9 +#endif + +//#endif + diff --git a/3rdParty/Boost/src/boost/thread/exceptional_ptr.hpp b/3rdParty/Boost/src/boost/thread/exceptional_ptr.hpp new file mode 100644 index 0000000..4954792 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/exceptional_ptr.hpp @@ -0,0 +1,44 @@ +// 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 2014 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_EXCEPTIONAL_PTR_HPP +#define BOOST_THREAD_EXCEPTIONAL_PTR_HPP + +#include <boost/thread/detail/move.hpp> +#include <boost/exception_ptr.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + struct exceptional_ptr { + exception_ptr ptr_; + + exceptional_ptr() : ptr_() {} + explicit exceptional_ptr(exception_ptr ex) : ptr_(ex) {} + template <class E> + explicit exceptional_ptr(BOOST_FWD_REF(E) ex) : ptr_(boost::copy_exception(boost::forward<E>(ex))) {} + }; + + template <class E> + inline exceptional_ptr make_exceptional(BOOST_FWD_REF(E) ex) { + return exceptional_ptr(boost::forward<E>(ex)); + } + + inline exceptional_ptr make_exceptional(exception_ptr ex) + { + return exceptional_ptr(ex); + } + + inline exceptional_ptr make_exceptional() + { + return exceptional_ptr(); + } + +} // namespace boost + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/3rdParty/Boost/src/boost/thread/exceptions.hpp b/3rdParty/Boost/src/boost/thread/exceptions.hpp index 08c28d3..d97465b 100644 --- a/3rdParty/Boost/src/boost/thread/exceptions.hpp +++ b/3rdParty/Boost/src/boost/thread/exceptions.hpp @@ -28,8 +28,10 @@ namespace boost { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS class BOOST_SYMBOL_VISIBLE thread_interrupted {}; +#endif class BOOST_SYMBOL_VISIBLE thread_exception: public system::system_error @@ -122,7 +124,7 @@ namespace boost typedef thread_exception base_type; public: thread_resource_error() - : base_type(system::errc::resource_unavailable_try_again, "boost::thread_resource_error") + : base_type(static_cast<int>(system::errc::resource_unavailable_try_again), "boost::thread_resource_error") {} thread_resource_error( int ev ) @@ -150,7 +152,7 @@ namespace boost typedef thread_exception base_type; public: unsupported_thread_option() - : base_type(system::errc::invalid_argument, "boost::unsupported_thread_option") + : base_type(static_cast<int>(system::errc::invalid_argument), "boost::unsupported_thread_option") {} unsupported_thread_option( int ev ) @@ -174,7 +176,7 @@ namespace boost typedef thread_exception base_type; public: invalid_thread_argument() - : base_type(system::errc::invalid_argument, "boost::invalid_thread_argument") + : base_type(static_cast<int>(system::errc::invalid_argument), "boost::invalid_thread_argument") {} invalid_thread_argument( int ev ) @@ -198,7 +200,7 @@ namespace boost typedef thread_exception base_type; public: thread_permission_error() - : base_type(system::errc::permission_denied, "boost::thread_permission_error") + : base_type(static_cast<int>(system::errc::permission_denied), "boost::thread_permission_error") {} thread_permission_error( int ev ) diff --git a/3rdParty/Boost/src/boost/thread/future.hpp b/3rdParty/Boost/src/boost/thread/future.hpp index 6bf5cf6..5f55707 100644 --- a/3rdParty/Boost/src/boost/thread/future.hpp +++ b/3rdParty/Boost/src/boost/thread/future.hpp @@ -1,5 +1,5 @@ // (C) Copyright 2008-10 Anthony Williams -// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// (C) Copyright 2011-2014 Vicente J. Botet Escriba // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -15,42 +15,58 @@ #ifndef BOOST_NO_EXCEPTIONS -#include <boost/detail/scoped_enum_emulation.hpp> +#include <boost/core/scoped_enum.hpp> #include <stdexcept> +#include <boost/thread/exceptional_ptr.hpp> #include <boost/thread/detail/move.hpp> +#include <boost/thread/detail/invoker.hpp> #include <boost/thread/thread_time.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/condition_variable.hpp> +#include <boost/thread/lock_algorithms.hpp> +#include <boost/thread/lock_types.hpp> #include <boost/exception_ptr.hpp> #include <boost/shared_ptr.hpp> #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/thread/detail/is_convertible.hpp> +#include <boost/type_traits/decay.hpp> +#include <boost/type_traits/is_void.hpp> +#include <boost/type_traits/conditional.hpp> #include <boost/config.hpp> #include <boost/throw_exception.hpp> #include <algorithm> #include <boost/function.hpp> #include <boost/bind.hpp> -#include <boost/ref.hpp> +#include <boost/core/ref.hpp> #include <boost/scoped_array.hpp> -#include <boost/utility/enable_if.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <boost/core/enable_if.hpp> + #include <list> #include <boost/next_prior.hpp> #include <vector> -#include <boost/system/error_code.hpp> + +#include <boost/thread/future_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> +#include <boost/container/scoped_allocator.hpp> +#if ! defined BOOST_NO_CXX11_ALLOCATOR +#include <memory> +#endif #endif #include <boost/utility/result_of.hpp> -#include <boost/thread/thread.hpp> +#include <boost/thread/thread_only.hpp> + +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY +#include <boost/thread/csbl/tuple.hpp> +#include <boost/thread/csbl/vector.hpp> +#endif #if defined BOOST_THREAD_PROVIDES_FUTURE #define BOOST_THREAD_FUTURE future @@ -58,36 +74,18 @@ #define BOOST_THREAD_FUTURE unique_future #endif - namespace boost { - //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) { + none = 0, async = 1, deferred = 2, +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + executor = 4, +#endif any = async | deferred } BOOST_SCOPED_ENUM_DECLARE_END(launch) @@ -101,26 +99,6 @@ namespace boost } 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 { @@ -136,11 +114,6 @@ namespace boost { return ec_; } - const char* what() const BOOST_THREAD_NOEXCEPT_OR_THROW - { - return code().message().c_str(); - } - }; class BOOST_SYMBOL_VISIBLE future_uninitialized: @@ -185,49 +158,111 @@ namespace boost {} }; - class BOOST_SYMBOL_VISIBLE task_moved: - public future_error - { - public: - task_moved(): - future_error(system::make_error_code(future_errc::no_state)) - {} - }; + 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)) - {} - }; + class promise_moved: + public future_error + { + public: + promise_moved(): + future_error(system::make_error_code(future_errc::no_state)) + {} + }; namespace future_state { - enum state { uninitialized, waiting, ready, moved }; + enum state { uninitialized, waiting, ready, moved, deferred }; } namespace detail { - struct future_object_base + struct relocker + { + boost::unique_lock<boost::mutex>& lock_; + bool unlocked_; + + relocker(boost::unique_lock<boost::mutex>& lk): + lock_(lk) + { + lock_.unlock(); + unlocked_=true; + } + ~relocker() + { + if (unlocked_) { + lock_.lock(); + } + } + void lock() { + if (unlocked_) { + lock_.lock(); + unlocked_=false; + } + } + private: + relocker& operator=(relocker const&); + }; + + struct shared_state_base : enable_shared_from_this<shared_state_base> { + typedef std::list<boost::condition_variable_any*> waiter_list; + // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout. + typedef shared_ptr<shared_state_base> continuation_ptr_type; + boost::exception_ptr exception; bool done; - bool thread_was_interrupted; - boost::mutex mutex; + bool is_deferred_; + launch policy_; + bool is_constructed; + mutable boost::mutex mutex; boost::condition_variable waiters; - typedef std::list<boost::condition_variable_any*> waiter_list; waiter_list external_waiters; boost::function<void()> callback; + // This declaration should be only included conditionally if interruptions are allowed, but is included to maintain the same layout. + bool thread_was_interrupted; + // This declaration should be only included conditionally, but is included to maintain the same layout. + continuation_ptr_type continuation_ptr; - future_object_base(): + // This declaration should be only included conditionally, but is included to maintain the same layout. + virtual void launch_continuation(boost::unique_lock<boost::mutex>&) + { + } + + shared_state_base(): done(false), - thread_was_interrupted(false) + is_deferred_(false), + policy_(launch::none), + is_constructed(false), + thread_was_interrupted(false), + continuation_ptr() {} - virtual ~future_object_base() + virtual ~shared_state_base() {} + void set_deferred() + { + is_deferred_ = true; + policy_ = launch::deferred; + } + void set_async() + { + is_deferred_ = false; + policy_ = launch::async; + } +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + void set_executor() + { + is_deferred_ = false; + policy_ = launch::executor; + } +#endif waiter_list::iterator register_external_waiter(boost::condition_variable_any& cv) { boost::unique_lock<boost::mutex> lock(mutex); @@ -241,7 +276,32 @@ namespace boost external_waiters.erase(it); } - void mark_finished_internal() +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + void do_continuation(boost::unique_lock<boost::mutex>& lock) + { + if (continuation_ptr) { + continuation_ptr_type this_continuation_ptr = continuation_ptr; + continuation_ptr.reset(); + this_continuation_ptr->launch_continuation(lock); + //if (! lock.owns_lock()) + // lock.lock(); + } + } +#else + void do_continuation(boost::unique_lock<boost::mutex>&) + { + } +#endif +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock<boost::mutex>& lock) + { + continuation_ptr= continuation; + if (done) { + do_continuation(lock); + } + } +#endif + void mark_finished_internal(boost::unique_lock<boost::mutex>& lock) { done=true; waiters.notify_all(); @@ -250,24 +310,13 @@ namespace boost { (*it)->notify_all(); } + do_continuation(lock); } - - struct relocker + void make_ready() { - boost::unique_lock<boost::mutex>& lock; - - relocker(boost::unique_lock<boost::mutex>& lock_): - lock(lock_) - { - lock.unlock(); - } - ~relocker() - { - lock.lock(); - } - private: - relocker& operator=(relocker const&); - }; + boost::unique_lock<boost::mutex> lock(mutex); + mark_finished_internal(lock); + } void do_callback(boost::unique_lock<boost::mutex>& lock) { @@ -279,28 +328,50 @@ namespace boost } } - - void wait(bool rethrow=true) + void wait_internal(boost::unique_lock<boost::mutex> &lk, bool rethrow=true) { - boost::unique_lock<boost::mutex> lock(mutex); - do_callback(lock); - while(!done) - { - waiters.wait(lock); - } - if(rethrow && thread_was_interrupted) + do_callback(lk); + //if (!done) // fixme why this doesn't work? + { + if (is_deferred_) { - throw boost::thread_interrupted(); + is_deferred_=false; + execute(lk); + //lk.unlock(); } - if(rethrow && exception) + else { - boost::rethrow_exception(exception); + while(!done) + { + waiters.wait(lk); + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + if(rethrow && thread_was_interrupted) + { + throw boost::thread_interrupted(); + } +#endif + if(rethrow && exception) + { + boost::rethrow_exception(exception); + } } + } } + virtual void wait(bool rethrow=true) + { + boost::unique_lock<boost::mutex> lock(mutex); + wait_internal(lock, rethrow); + } + +#if defined BOOST_THREAD_USES_DATETIME bool timed_wait_until(boost::system_time const& target_time) { boost::unique_lock<boost::mutex> lock(mutex); + if (is_deferred_) + return false; + do_callback(lock); while(!done) { @@ -312,7 +383,7 @@ namespace boost } return true; } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Clock, class Duration> @@ -320,6 +391,8 @@ namespace boost wait_until(const chrono::time_point<Clock, Duration>& abs_time) { boost::unique_lock<boost::mutex> lock(mutex); + if (is_deferred_) + return future_status::deferred; do_callback(lock); while(!done) { @@ -332,63 +405,166 @@ namespace boost return future_status::ready; } #endif - void mark_exceptional_finish_internal(boost::exception_ptr const& e) + void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock<boost::mutex>& lock) { exception=e; - mark_finished_internal(); + mark_finished_internal(lock); } + void mark_exceptional_finish() { - boost::lock_guard<boost::mutex> lock(mutex); - mark_exceptional_finish_internal(boost::current_exception()); + boost::unique_lock<boost::mutex> lock(mutex); + mark_exceptional_finish_internal(boost::current_exception(), lock); } + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void mark_interrupted_finish() { - boost::lock_guard<boost::mutex> lock(mutex); + boost::unique_lock<boost::mutex> lock(mutex); thread_was_interrupted=true; - mark_finished_internal(); + mark_finished_internal(lock); } - bool has_value() + + void set_interrupted_at_thread_exit() + { + unique_lock<boost::mutex> lk(mutex); + thread_was_interrupted=true; + if (has_value(lk)) + { + throw_exception(promise_already_satisfied()); + } + detail::make_ready_at_thread_exit(shared_from_this()); + } +#endif + + void set_exception_at_thread_exit(exception_ptr e) + { + unique_lock<boost::mutex> lk(mutex); + if (has_value(lk)) + { + throw_exception(promise_already_satisfied()); + } + exception=e; + this->is_constructed = true; + detail::make_ready_at_thread_exit(shared_from_this()); + + } + + bool has_value() const { boost::lock_guard<boost::mutex> lock(mutex); - return done && !(exception || thread_was_interrupted); + return done && !(exception +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + || thread_was_interrupted +#endif + ); + } + + bool has_value(unique_lock<boost::mutex>& ) const + { + return done && !(exception +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + || thread_was_interrupted +#endif + ); } - bool has_exception() + + bool has_exception() const { boost::lock_guard<boost::mutex> lock(mutex); - return done && (exception || thread_was_interrupted); + return done && (exception +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + || thread_was_interrupted +#endif + ); + } + + bool has_exception(unique_lock<boost::mutex>&) const + { + return done && (exception +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + || thread_was_interrupted +#endif + ); + } + + bool is_deferred(boost::lock_guard<boost::mutex>&) const { + return is_deferred_; + } + + launch launch_policy(boost::unique_lock<boost::mutex>&) const + { + return policy_; + } + + future_state::state get_state() const + { + boost::lock_guard<boost::mutex> guard(mutex); + if(!done) + { + return future_state::waiting; + } + else + { + return future_state::ready; + } + } + + exception_ptr get_exception_ptr() + { + boost::unique_lock<boost::mutex> lock(mutex); + return get_exception_ptr(lock); + } + exception_ptr get_exception_ptr(boost::unique_lock<boost::mutex>& lock) + { + wait_internal(lock, false); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + if(thread_was_interrupted) + { + return copy_exception(boost::thread_interrupted()); + } +#endif + return exception; } template<typename F,typename U> void set_wait_callback(F f,U* u) { + boost::lock_guard<boost::mutex> lock(mutex); callback=boost::bind(f,boost::ref(*u)); } + virtual void execute(boost::unique_lock<boost::mutex>&) {} + private: - future_object_base(future_object_base const&); - future_object_base& operator=(future_object_base const&); + shared_state_base(shared_state_base const&); + shared_state_base& operator=(shared_state_base const&); }; template<typename T> struct future_traits { - typedef boost::scoped_ptr<T> storage_type; + typedef boost::scoped_ptr<T> storage_type; + struct dummy; #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - typedef T const& source_reference_type; - struct dummy; - 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; + typedef T const& source_reference_type; + //typedef typename conditional<boost::is_fundamental<T>::value,dummy&,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type; + typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; + //typedef typename conditional<boost::is_fundamental<T>::value,T,BOOST_THREAD_RV_REF(T)>::type move_dest_type; + typedef T 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; + typedef typename conditional<boost::is_fundamental<T>::value,T,T&>::type source_reference_type; + //typedef typename conditional<boost::is_fundamental<T>::value,T,BOOST_THREAD_RV_REF(T)>::type rvalue_source_type; + //typedef typename conditional<boost::enable_move_utility_emulation<T>::value,BOOST_THREAD_RV_REF(T),T>::type move_dest_type; + typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; + typedef T move_dest_type; #else - typedef T& source_reference_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; + typedef T& source_reference_type; + typedef typename conditional<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >::value, BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type; + typedef typename conditional<boost::thread_detail::is_convertible<T&,BOOST_THREAD_RV_REF(T) >::value, 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) @@ -398,7 +574,11 @@ namespace boost static void init(storage_type& storage,rvalue_source_type t) { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + storage.reset(new T(boost::forward<T>(t))); +#else storage.reset(new T(static_cast<rvalue_source_type>(t))); +#endif } static void cleanup(storage_type& storage) @@ -412,8 +592,8 @@ namespace boost { typedef T* storage_type; typedef T& source_reference_type; - struct rvalue_source_type - {}; + //struct rvalue_source_type + //{}; typedef T& move_dest_type; typedef T& shared_future_get_result_type; @@ -447,9 +627,10 @@ namespace boost }; + // Used to create stand-alone futures template<typename T> - struct future_object: - detail::future_object_base + struct shared_state: + detail::shared_state_base { typedef typename future_traits<T>::storage_type storage_type; typedef typename future_traits<T>::source_reference_type source_reference_type; @@ -459,117 +640,424 @@ namespace boost storage_type result; - future_object(): + shared_state(): result(0) {} - void mark_finished_with_result_internal(source_reference_type result_) + ~shared_state() + {} + + void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock) { future_traits<T>::init(result,result_); - mark_finished_internal(); + this->mark_finished_internal(lock); } - void mark_finished_with_result_internal(rvalue_source_type result_) + void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock<boost::mutex>& lock) { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + future_traits<T>::init(result,boost::forward<T>(result_)); +#else future_traits<T>::init(result,static_cast<rvalue_source_type>(result_)); - mark_finished_internal(); +#endif + this->mark_finished_internal(lock); } void mark_finished_with_result(source_reference_type result_) { - boost::lock_guard<boost::mutex> lock(mutex); - mark_finished_with_result_internal(result_); + boost::unique_lock<boost::mutex> lock(mutex); + this->mark_finished_with_result_internal(result_, lock); } void mark_finished_with_result(rvalue_source_type result_) { - boost::lock_guard<boost::mutex> lock(mutex); - mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_)); + boost::unique_lock<boost::mutex> lock(mutex); + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + mark_finished_with_result_internal(boost::forward<T>(result_), lock); +#else + mark_finished_with_result_internal(static_cast<rvalue_source_type>(result_), lock); +#endif } - move_dest_type get() + virtual move_dest_type get() { - wait(); - return static_cast<move_dest_type>(*result); + boost::unique_lock<boost::mutex> lock(mutex); + wait_internal(lock); + return boost::move(*result); } - shared_future_get_result_type get_sh() + virtual shared_future_get_result_type get_sh() { - wait(); - return static_cast<shared_future_get_result_type>(*result); + boost::unique_lock<boost::mutex> lock(mutex); + wait_internal(lock); + return *result; } - future_state::state get_state() + //void set_value_at_thread_exit(const T & result_) + void set_value_at_thread_exit(source_reference_type result_) { - boost::lock_guard<boost::mutex> guard(mutex); - if(!done) - { - return future_state::waiting; - } - else - { - return future_state::ready; - } + unique_lock<boost::mutex> lk(this->mutex); + if (this->has_value(lk)) + { + throw_exception(promise_already_satisfied()); + } + //future_traits<T>::init(result,result_); + result.reset(new T(result_)); + + this->is_constructed = true; + detail::make_ready_at_thread_exit(shared_from_this()); + } + //void set_value_at_thread_exit(BOOST_THREAD_RV_REF(T) result_) + void set_value_at_thread_exit(rvalue_source_type result_) + { + unique_lock<boost::mutex> lk(this->mutex); + if (this->has_value(lk)) + throw_exception(promise_already_satisfied()); + result.reset(new T(boost::move(result_))); + //future_traits<T>::init(result,static_cast<rvalue_source_type>(result_)); + this->is_constructed = true; + detail::make_ready_at_thread_exit(shared_from_this()); + } + + + private: + shared_state(shared_state const&); + shared_state& operator=(shared_state const&); + }; + + template<typename T> + struct shared_state<T&>: + detail::shared_state_base + { + typedef typename future_traits<T&>::storage_type storage_type; + typedef typename future_traits<T&>::source_reference_type source_reference_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; + + T* result; + + shared_state(): + result(0) + {} + + ~shared_state() + { + } + + void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock<boost::mutex>& lock) + { + //future_traits<T>::init(result,result_); + result= &result_; + mark_finished_internal(lock); + } + + void mark_finished_with_result(source_reference_type result_) + { + boost::unique_lock<boost::mutex> lock(mutex); + mark_finished_with_result_internal(result_, lock); + } + + virtual T& get() + { + boost::unique_lock<boost::mutex> lock(mutex); + wait_internal(lock); + return *result; + } + + virtual T& get_sh() + { + boost::unique_lock<boost::mutex> lock(mutex); + wait_internal(lock); + return *result; + } + + void set_value_at_thread_exit(T& result_) + { + unique_lock<boost::mutex> lk(this->mutex); + if (this->has_value(lk)) + throw_exception(promise_already_satisfied()); + //future_traits<T>::init(result,result_); + result= &result_; + this->is_constructed = true; + detail::make_ready_at_thread_exit(shared_from_this()); } private: - future_object(future_object const&); - future_object& operator=(future_object const&); + shared_state(shared_state const&); + shared_state& operator=(shared_state const&); }; template<> - struct future_object<void>: - detail::future_object_base + struct shared_state<void>: + detail::shared_state_base { typedef void shared_future_get_result_type; - future_object() + shared_state() {} - void mark_finished_with_result_internal() + void mark_finished_with_result_internal(boost::unique_lock<boost::mutex>& lock) { - mark_finished_internal(); + mark_finished_internal(lock); } void mark_finished_with_result() { - boost::lock_guard<boost::mutex> lock(mutex); - mark_finished_with_result_internal(); + boost::unique_lock<boost::mutex> lock(mutex); + mark_finished_with_result_internal(lock); } - void get() + virtual void get() { - wait(); + boost::unique_lock<boost::mutex> lock(mutex); + this->wait_internal(lock); } - void get_sh() + + virtual void get_sh() { - wait(); + boost::unique_lock<boost::mutex> lock(mutex); + this->wait_internal(lock); } - future_state::state get_state() + + void set_value_at_thread_exit() { - boost::lock_guard<boost::mutex> guard(mutex); - if(!done) - { - return future_state::waiting; - } - else - { - return future_state::ready; - } + unique_lock<boost::mutex> lk(this->mutex); + if (this->has_value(lk)) + { + throw_exception(promise_already_satisfied()); + } + this->is_constructed = true; + detail::make_ready_at_thread_exit(shared_from_this()); } private: - future_object(future_object const&); - future_object& operator=(future_object const&); + shared_state(shared_state const&); + shared_state& operator=(shared_state const&); + }; + + ///////////////////////// + /// future_async_shared_state_base + ///////////////////////// + template<typename Rp> + struct future_async_shared_state_base: shared_state<Rp> + { + typedef shared_state<Rp> base_type; + protected: + boost::thread thr_; + void join() + { + if (thr_.joinable()) thr_.join(); + } + public: + future_async_shared_state_base() + { + this->set_async(); + } + explicit future_async_shared_state_base(BOOST_THREAD_RV_REF(boost::thread) th) : + thr_(boost::move(th)) + { + this->set_async(); + } + + ~future_async_shared_state_base() + { + join(); + } + + virtual void wait(bool rethrow) + { + join(); + this->base_type::wait(rethrow); + } + }; + + ///////////////////////// + /// future_async_shared_state + ///////////////////////// + template<typename Rp, typename Fp> + struct future_async_shared_state: future_async_shared_state_base<Rp> + { + typedef future_async_shared_state_base<Rp> base_type; + + public: + explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) : + base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f))) + { + } + + static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f) + { + try + { + that->mark_finished_with_result(f()); + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + that->mark_interrupted_finish(); + } +#endif + catch(...) + { + that->mark_exceptional_finish(); + } + } + }; + + template<typename Fp> + struct future_async_shared_state<void, Fp>: public future_async_shared_state_base<void> + { + typedef future_async_shared_state_base<void> base_type; + + public: + explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) : + base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f))) + { + } + + static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f) + { + try + { + f(); + that->mark_finished_with_result(); + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + that->mark_interrupted_finish(); + } +#endif + catch(...) + { + that->mark_exceptional_finish(); + } + } + }; + + template<typename Rp, typename Fp> + struct future_async_shared_state<Rp&, Fp>: future_async_shared_state_base<Rp&> + { + typedef future_async_shared_state_base<Rp&> base_type; + + public: + explicit future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) : + base_type(thread(&future_async_shared_state::run, this, boost::forward<Fp>(f))) + { + } + + static void run(future_async_shared_state* that, BOOST_THREAD_FWD_REF(Fp) f) + { + try + { + that->mark_finished_with_result(f()); + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + that->mark_interrupted_finish(); + } +#endif + catch(...) + { + that->mark_exceptional_finish(); + } + } + }; + + ////////////////////////// + /// future_deferred_shared_state + ////////////////////////// + template<typename Rp, typename Fp> + struct future_deferred_shared_state: shared_state<Rp> + { + typedef shared_state<Rp> base_type; + Fp func_; + + public: + explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) + : func_(boost::forward<Fp>(f)) + { + this->set_deferred(); + } + + virtual void execute(boost::unique_lock<boost::mutex>& lck) { + try + { + Fp local_fuct=boost::move(func_); + relocker relock(lck); + Rp res = local_fuct(); + relock.lock(); + this->mark_finished_with_result_internal(boost::move(res), lck); + } + catch (...) + { + this->mark_exceptional_finish_internal(current_exception(), lck); + } + } + }; + template<typename Rp, typename Fp> + struct future_deferred_shared_state<Rp&,Fp>: shared_state<Rp&> + { + typedef shared_state<Rp&> base_type; + Fp func_; + + public: + explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) + : func_(boost::forward<Fp>(f)) + { + this->set_deferred(); + } + + virtual void execute(boost::unique_lock<boost::mutex>& lck) { + try + { + this->mark_finished_with_result_internal(func_(), lck); + } + catch (...) + { + this->mark_exceptional_finish_internal(current_exception(), lck); + } + } + }; + + template<typename Fp> + struct future_deferred_shared_state<void,Fp>: shared_state<void> + { + typedef shared_state<void> base_type; + Fp func_; + + public: + explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) + : func_(boost::forward<Fp>(f)) + { + this->set_deferred(); + } + + virtual void execute(boost::unique_lock<boost::mutex>& lck) { + try + { + Fp local_fuct=boost::move(func_); + relocker relock(lck); + local_fuct(); + relock.lock(); + this->mark_finished_with_result_internal(lck); + } + catch (...) + { + this->mark_exceptional_finish_internal(current_exception(), lck); + } + } }; // template<typename T, typename Allocator> -// struct future_object_alloc: public future_object<T> +// struct shared_state_alloc: public shared_state<T> // { -// typedef future_object<T> base; +// typedef shared_state<T> base; // Allocator alloc_; // // public: -// explicit future_object_alloc(const Allocator& a) +// explicit shared_state_alloc(const Allocator& a) // : alloc_(a) {} // // }; @@ -580,38 +1068,33 @@ namespace boost struct registered_waiter { - boost::shared_ptr<detail::future_object_base> future_; - detail::future_object_base::waiter_list::iterator wait_iterator; + boost::shared_ptr<detail::shared_state_base> future_; + detail::shared_state_base::waiter_list::iterator wait_iterator; count_type index; - registered_waiter(boost::shared_ptr<detail::future_object_base> const& a_future, - detail::future_object_base::waiter_list::iterator wait_iterator_, + registered_waiter(boost::shared_ptr<detail::shared_state_base> const& a_future, + detail::shared_state_base::waiter_list::iterator wait_iterator_, count_type index_): future_(a_future),wait_iterator(wait_iterator_),index(index_) {} - }; struct all_futures_lock { #ifdef _MANAGED - typedef std::ptrdiff_t count_type_portable; + typedef std::ptrdiff_t count_type_portable; #else - typedef count_type count_type_portable; + typedef count_type count_type_portable; #endif - count_type_portable count; - boost::scoped_array<boost::unique_lock<boost::mutex> > locks; + 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_portable i=0;i<count;++i) { -#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 + locks[i]=BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(futures[i].future_->mutex)); } } @@ -643,11 +1126,25 @@ namespace boost { if(f.future_) { - futures.push_back(registered_waiter(f.future_,f.future_->register_external_waiter(cv),future_count)); + registered_waiter waiter(f.future_,f.future_->register_external_waiter(cv),future_count); + try { + futures.push_back(waiter); + } catch(...) { + f.future_->remove_external_waiter(waiter.wait_iterator); + throw; + } } ++future_count; } +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES + template<typename F1, typename... Fs> + void add(F1& f1, Fs&... fs) + { + add(f1); add(fs...); + } +#endif + count_type wait() { all_futures_lock lk(futures); @@ -686,18 +1183,21 @@ namespace boost struct is_future_type { BOOST_STATIC_CONSTANT(bool, value=false); + typedef void type; }; template<typename T> struct is_future_type<BOOST_THREAD_FUTURE<T> > { BOOST_STATIC_CONSTANT(bool, value=true); + typedef T type; }; template<typename T> struct is_future_type<shared_future<T> > { BOOST_STATIC_CONSTANT(bool, value=true); + typedef T type; }; template<typename Iterator> @@ -709,6 +1209,7 @@ namespace boost } } +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES template<typename F1,typename F2> typename boost::enable_if<is_future_type<F1>,void>::type wait_for_all(F1& f1,F2& f2) { @@ -742,6 +1243,16 @@ namespace boost f4.wait(); f5.wait(); } +#else + template<typename F1, typename... Fs> + void wait_for_all(F1& f1, Fs&... fs) + { + bool dummy[] = { (f1.wait(), true), (fs.wait(), true)... }; + + // prevent unused parameter warning + (void) dummy; + } +#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template<typename Iterator> typename boost::disable_if<is_future_type<Iterator>,Iterator>::type wait_for_any(Iterator begin,Iterator end) @@ -757,6 +1268,7 @@ namespace boost return boost::next(begin,waiter.wait()); } +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES template<typename F1,typename F2> typename boost::enable_if<is_future_type<F1>,unsigned>::type wait_for_any(F1& f1,F2& f2) { @@ -798,6 +1310,15 @@ namespace boost waiter.add(f5); return waiter.wait(); } +#else + template<typename F1, typename... Fs> + typename boost::enable_if<is_future_type<F1>, unsigned>::type wait_for_any(F1& f1, Fs&... fs) + { + detail::future_waiter waiter; + waiter.add(f1, fs...); + return waiter.wait(); + } +#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template <typename R> class promise; @@ -805,72 +1326,70 @@ namespace boost template <typename R> class packaged_task; - template <typename R> - class BOOST_THREAD_FUTURE + namespace detail { - private: + /// Common implementation for all the futures independently of the return type + class base_future + { + //BOOST_THREAD_MOVABLE(base_future) - typedef boost::shared_ptr<detail::future_object<R> > future_ptr; + }; + /// Common implementation for future and shared_future. + template <typename R> + class basic_future : public base_future + { + protected: + public: + + typedef boost::shared_ptr<detail::shared_state<R> > future_ptr; + static //BOOST_CONSTEXPR + future_ptr make_exceptional_future_ptr(exceptional_ptr const& ex) { + promise<R> p; + p.set_exception(ex.ptr_); + return p.get_future().future_; + } future_ptr future_; - friend class shared_future<R>; - friend class promise<R>; - friend class packaged_task<R>; - friend class detail::future_waiter; + basic_future(future_ptr a_future): + future_(a_future) + { + } + // Copy construction from a shared_future + explicit basic_future(const shared_future<R>&) BOOST_NOEXCEPT; - typedef typename detail::future_traits<R>::move_dest_type move_dest_type; + public: + typedef future_state::state state; - BOOST_THREAD_FUTURE(future_ptr a_future): - future_(a_future) - {} + BOOST_THREAD_MOVABLE(basic_future) + basic_future(): future_() {} - public: - BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) - typedef future_state::state state; - BOOST_THREAD_FUTURE() - {} + //BOOST_CONSTEXPR + basic_future(exceptional_ptr const& ex) + : future_(make_exceptional_future_ptr(ex)) + { + } - ~BOOST_THREAD_FUTURE() - {} + ~basic_future() {} - BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: - future_(BOOST_THREAD_RV(other).future_) + basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT: + future_(BOOST_THREAD_RV(other).future_) { BOOST_THREAD_RV(other).future_.reset(); } - - BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT + basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT { future_=BOOST_THREAD_RV(other).future_; BOOST_THREAD_RV(other).future_.reset(); return *this; } - - shared_future<R> share() + void swap(basic_future& that) BOOST_NOEXCEPT { - return shared_future<R>(::boost::move(*this)); - } - - void swap(BOOST_THREAD_FUTURE& other) - { - future_.swap(other.future_); - } - - // retrieving the value - move_dest_type get() - { - if(!future_) - { - boost::throw_exception(future_uninitialized()); - } - - return future_->get(); + future_.swap(that.future_); } - // functions to check state, and wait for ready - state get_state() const BOOST_NOEXCEPT + state get_state() const { if(!future_) { @@ -879,21 +1398,34 @@ namespace boost return future_->get_state(); } - bool is_ready() const BOOST_NOEXCEPT + bool is_ready() const { return get_state()==future_state::ready; } - bool has_exception() const BOOST_NOEXCEPT + bool has_exception() const { return future_ && future_->has_exception(); } - bool has_value() const BOOST_NOEXCEPT + bool has_value() const { return future_ && future_->has_value(); } + launch launch_policy(boost::unique_lock<boost::mutex>& lk) const + { + if ( future_ ) return future_->launch_policy(lk); + else return launch(launch::none); + } + + exception_ptr get_exception_ptr() + { + return future_ + ? future_->get_exception_ptr() + : exception_ptr(); + } + bool valid() const BOOST_NOEXCEPT { return future_ != 0; @@ -909,6 +1441,7 @@ namespace boost future_->wait(false); } +#if defined BOOST_THREAD_USES_DATETIME template<typename Duration> bool timed_wait(Duration const& rel_time) const { @@ -923,6 +1456,7 @@ namespace boost } return future_->timed_wait_until(abs_time); } +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> future_status @@ -942,177 +1476,776 @@ namespace boost return future_->wait_until(abs_time); } #endif + + }; + + } // detail + BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future<R> BOOST_THREAD_DCL_MOVABLE_END + + namespace detail + { +#if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005 + template <class Rp, class Fp> + BOOST_THREAD_FUTURE<Rp> + make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f); + + template <class Rp, class Fp> + BOOST_THREAD_FUTURE<Rp> + make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); +#endif // #if (!defined _MSC_VER || _MSC_VER >= 1400) +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + template<typename F, typename Rp, typename Fp> + struct future_deferred_continuation_shared_state; + template<typename F, typename Rp, typename Fp> + struct future_async_continuation_shared_state; + + template <class F, class Rp, class Fp> + BOOST_THREAD_FUTURE<Rp> + make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template <class F, class Rp, class Fp> + BOOST_THREAD_FUTURE<Rp> + make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); +#endif +#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP + template<typename F, typename Rp> + struct future_unwrap_shared_state; + template <class F, class Rp> + inline BOOST_THREAD_FUTURE<Rp> + make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f); +#endif + } + + template <typename R> + class BOOST_THREAD_FUTURE : public detail::basic_future<R> + { + private: + typedef detail::basic_future<R> base_type; + typedef typename base_type::future_ptr future_ptr; + + friend class shared_future<R>; + friend class promise<R>; +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + template <typename, typename, typename> + friend struct detail::future_async_continuation_shared_state; + template <typename, typename, typename> + friend struct detail::future_deferred_continuation_shared_state; + + template <class F, class Rp, class Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template <class F, class Rp, class Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); +#endif +#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP + template<typename F, typename Rp> + friend struct detail::future_unwrap_shared_state; + template <class F, class Rp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f); +#endif +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + template <class> friend class packaged_task; // todo check if this works in windows +#else + friend class packaged_task<R>; +#endif + friend class detail::future_waiter; + + template <class Rp, class Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f); + + template <class Rp, class Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); + + + typedef typename detail::future_traits<R>::move_dest_type move_dest_type; + public: // when_all + + BOOST_THREAD_FUTURE(future_ptr a_future): + base_type(a_future) + { + } + + public: + BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) + typedef future_state::state state; + typedef R value_type; // EXTENSION + + BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {} + //BOOST_CONSTEXPR + BOOST_THREAD_FUTURE(exceptional_ptr const& ex): + base_type(ex) {} + + ~BOOST_THREAD_FUTURE() {} + + BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: + base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) + { + } + inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other); // EXTENSION + + BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT + { + this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))); + return *this; + } + +// BOOST_THREAD_FUTURE& operator=(exceptional_ptr const& ex) +// { +// this->future_=base_type::make_exceptional_future_ptr(ex); +// return *this; +// } + + shared_future<R> share() + { + return shared_future<R>(::boost::move(*this)); + } + + void swap(BOOST_THREAD_FUTURE& other) + { + static_cast<base_type*>(this)->swap(other); + } + + // todo this function must be private and friendship provided to the internal users. + void set_async() + { + this->future_->set_async(); + } + // todo this function must be private and friendship provided to the internal users. + void set_deferred() + { + this->future_->set_deferred(); + } + + // retrieving the value + move_dest_type get() + { + if(!this->future_) + { + boost::throw_exception(future_uninitialized()); + } + future_ptr fut_=this->future_; +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_.reset(); +#endif + return fut_->get(); + } + + template <typename R2> + typename boost::disable_if< is_void<R2>, move_dest_type>::type + get_or(BOOST_THREAD_RV_REF(R2) v) + { + if(!this->future_) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(false); + future_ptr fut_=this->future_; +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_.reset(); +#endif + if (fut_->has_value()) { + return fut_->get(); + } + else { + return boost::move(v); + } + } + + template <typename R2> + typename boost::disable_if< is_void<R2>, move_dest_type>::type + get_or(R2 const& v) // EXTENSION + { + if(!this->future_) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(false); + future_ptr fut_=this->future_; +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_.reset(); +#endif + if (fut_->has_value()) { + return fut_->get(); + } + else { + return v; + } + } + + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + +// template<typename F> +// auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + +//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) +// template<typename RF> +// inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&)); +// template<typename RF> +// inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&)); +//#endif + template<typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> + then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION + template<typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> + then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION + + template <typename R2> + inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type + fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION + template <typename R2> + inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type + fallback_to(R2 const& v); // EXTENSION + +#endif + +//#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP +// inline +// typename boost::enable_if< +// is_future_type<value_type>, +// value_type +// //BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type> +// >::type +// unwrap(); +//#endif + }; BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE<T> BOOST_THREAD_DCL_MOVABLE_END + template <typename R2> + class BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> > : public detail::basic_future<BOOST_THREAD_FUTURE<R2> > + { + typedef BOOST_THREAD_FUTURE<R2> R; + + private: + typedef detail::basic_future<R> base_type; + typedef typename base_type::future_ptr future_ptr; + + friend class shared_future<R>; + friend class promise<R>; + #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + template <typename, typename, typename> + friend struct detail::future_async_continuation_shared_state; + template <typename, typename, typename> + friend struct detail::future_deferred_continuation_shared_state; + + template <class F, class Rp, class Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template <class F, class Rp, class Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + #endif +#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP + template<typename F, typename Rp> + friend struct detail::future_unwrap_shared_state; + template <class F, class Rp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f); +#endif + #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + template <class> friend class packaged_task; // todo check if this works in windows + #else + friend class packaged_task<R>; + #endif + friend class detail::future_waiter; + + template <class Rp, class Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f); + + template <class Rp, class Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); + + + typedef typename detail::future_traits<R>::move_dest_type move_dest_type; + + BOOST_THREAD_FUTURE(future_ptr a_future): + base_type(a_future) + { + } + + public: + BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) + typedef future_state::state state; + typedef R value_type; // EXTENSION + + BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {} + //BOOST_CONSTEXPR + BOOST_THREAD_FUTURE(exceptional_ptr const& ex): + base_type(ex) {} + + ~BOOST_THREAD_FUTURE() {} + + BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: + base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) + { + } + + BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT + { + this->base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))); + return *this; + } +// BOOST_THREAD_FUTURE& operator=(exceptional_ptr const& ex) +// { +// this->future_=base_type::make_exceptional_future_ptr(ex); +// return *this; +// } + + shared_future<R> share() + { + return shared_future<R>(::boost::move(*this)); + } + + void swap(BOOST_THREAD_FUTURE& other) + { + static_cast<base_type*>(this)->swap(other); + } + + // todo this function must be private and friendship provided to the internal users. + void set_async() + { + this->future_->set_async(); + } + // todo this function must be private and friendship provided to the internal users. + void set_deferred() + { + this->future_->set_deferred(); + } + + // retrieving the value + move_dest_type get() + { + if(!this->future_) + { + boost::throw_exception(future_uninitialized()); + } + future_ptr fut_=this->future_; + #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_.reset(); + #endif + return fut_->get(); + } + move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION + { + if(!this->future_) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(false); + future_ptr fut_=this->future_; + #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_.reset(); + #endif + if (fut_->has_value()) return fut_->get(); + else return boost::move(v); + } + + move_dest_type get_or(R const& v) // EXTENSION + { + if(!this->future_) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(false); + future_ptr fut_=this->future_; + #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_.reset(); + #endif + if (fut_->has_value()) return fut_->get(); + else return v; + } + + + #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + + // template<typename F> + // auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + + //#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + // template<typename RF> + // inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(BOOST_THREAD_FUTURE&)); + // template<typename RF> + // inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(BOOST_THREAD_FUTURE&)); + //#endif + template<typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> + then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION + template<typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE)>::type> + then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION + #endif + + #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP + inline + BOOST_THREAD_FUTURE<R2> + unwrap(); // EXTENSION + #endif + + }; + template <typename R> - class shared_future + class shared_future : public detail::basic_future<R> { - typedef boost::shared_ptr<detail::future_object<R> > future_ptr; - future_ptr future_; + typedef detail::basic_future<R> base_type; + typedef typename base_type::future_ptr future_ptr; friend class detail::future_waiter; friend class promise<R>; - friend class packaged_task<R>; +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + template <typename, typename, typename> + friend struct detail::future_async_continuation_shared_state; + template <typename, typename, typename> + friend struct detail::future_deferred_continuation_shared_state; + + template <class F, class Rp, class Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_async_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template <class F, class Rp, class Fp> + friend BOOST_THREAD_FUTURE<Rp> + detail::make_future_deferred_continuation_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); +#endif +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + template <class> friend class packaged_task;// todo check if this works in windows +#else + friend class packaged_task<R>; +#endif shared_future(future_ptr a_future): - future_(a_future) + base_type(a_future) {} public: BOOST_THREAD_MOVABLE(shared_future) + typedef R value_type; // EXTENSION shared_future(shared_future const& other): - future_(other.future_) + base_type(other) {} typedef future_state::state state; - shared_future() + BOOST_CONSTEXPR shared_future() {} - + //BOOST_CONSTEXPR + shared_future(exceptional_ptr const& ex): + base_type(ex) {} ~shared_future() {} shared_future& operator=(shared_future const& other) { - future_=other.future_; + shared_future(other).swap(*this); return *this; } +// shared_future& operator=(exceptional_ptr const& ex) +// { +// this->future_=base_type::make_exceptional_future_ptr(ex); +// return *this; +// } + shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT : - future_(BOOST_THREAD_RV(other).future_) + base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) { BOOST_THREAD_RV(other).future_.reset(); } - 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_) + shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT : + base_type(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))) { - BOOST_THREAD_RV(other).future_.reset(); } + shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT { - future_.swap(BOOST_THREAD_RV(other).future_); - BOOST_THREAD_RV(other).future_.reset(); + base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))); return *this; } - shared_future& operator=(BOOST_THREAD_RV_REF_BEG BOOST_THREAD_FUTURE<R> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT + shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE<R> ) other) BOOST_NOEXCEPT { - future_.swap(BOOST_THREAD_RV(other).future_); - BOOST_THREAD_RV(other).future_.reset(); + base_type::operator=(boost::move(static_cast<base_type&>(BOOST_THREAD_RV(other)))); return *this; } void swap(shared_future& other) BOOST_NOEXCEPT { - future_.swap(other.future_); + static_cast<base_type*>(this)->swap(other); } // retrieving the value - typename detail::future_object<R>::shared_future_get_result_type get() + typename detail::shared_state<R>::shared_future_get_result_type get() { - if(!future_) + if(!this->future_) { boost::throw_exception(future_uninitialized()); } - return future_->get_sh(); + return this->future_->get_sh(); } - // functions to check state, and wait for ready - state get_state() const BOOST_NOEXCEPT + template <typename R2> + typename boost::disable_if< is_void<R2>, typename detail::shared_state<R>::shared_future_get_result_type>::type + get_or(BOOST_THREAD_RV_REF(R2) v) // EXTENSION { - if(!future_) + if(!this->future_) { - return future_state::uninitialized; + boost::throw_exception(future_uninitialized()); } - return future_->get_state(); + future_ptr fut_=this->future_; + fut_->wait(); + if (fut_->has_value()) return fut_->get_sh(); + else return boost::move(v); } - bool valid() const BOOST_NOEXCEPT +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + +// template<typename F> +// auto then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; +// template<typename F> +// auto then(launch, F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + +//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) +// template<typename RF> +// inline BOOST_THREAD_FUTURE<RF> then(RF(*func)(shared_future&)); +// template<typename RF> +// inline BOOST_THREAD_FUTURE<RF> then(launch policy, RF(*func)(shared_future&)); +//#endif + template<typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type> + then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION + template<typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future)>::type> + then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION +#endif +//#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP +// inline +// typename boost::enable_if_c< +// is_future_type<value_type>::value, +// BOOST_THREAD_FUTURE<typename is_future_type<value_type>::type> +// >::type +// unwrap(); +//#endif + + }; + + BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END + + namespace detail + { + /// Copy construction from a shared_future + template <typename R> + inline basic_future<R>::basic_future(const shared_future<R>& other) BOOST_NOEXCEPT + : future_(other.future_) + { + } + } + + template <typename R> + class promise + { + typedef boost::shared_ptr<detail::shared_state<R> > future_ptr; + + future_ptr future_; + bool future_obtained; + + void lazy_init() { - return future_ != 0; +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY +#include <boost/detail/atomic_undef_macros.hpp> + if(!atomic_load(&future_)) + { + future_ptr blank; + atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state<R>)); + } +#include <boost/detail/atomic_redef_macros.hpp> +#endif } - bool is_ready() const BOOST_NOEXCEPT + public: + BOOST_THREAD_MOVABLE_ONLY(promise) +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template <class Allocator> + promise(boost::allocator_arg_t, Allocator a) { - return get_state()==future_state::ready; + typedef typename Allocator::template rebind<detail::shared_state<R> >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor<A2> D; + + future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R>(), D(a2, 1) ); + future_obtained = false; } +#endif + promise(): +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY + future_(), +#else + future_(new detail::shared_state<R>()), +#endif + future_obtained(false) + {} - bool has_exception() const BOOST_NOEXCEPT + ~promise() { - return future_ && future_->has_exception(); + if(future_) + { + boost::unique_lock<boost::mutex> lock(future_->mutex); + + if(!future_->done && !future_->is_constructed) + { + future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock); + } + } } - bool has_value() const BOOST_NOEXCEPT + // Assignment + promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) { - return future_ && future_->has_value(); + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; + } + promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT + { + 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; } - void wait() const + void swap(promise& other) { - if(!future_) + future_.swap(other.future_); + std::swap(future_obtained,other.future_obtained); + } + + // Result retrieval + BOOST_THREAD_FUTURE<R> get_future() + { + lazy_init(); + if (future_.get()==0) { - boost::throw_exception(future_uninitialized()); + boost::throw_exception(promise_moved()); } - future_->wait(false); + if (future_obtained) + { + boost::throw_exception(future_already_retrieved()); + } + future_obtained=true; + return BOOST_THREAD_FUTURE<R>(future_); } - template<typename Duration> - bool timed_wait(Duration const& rel_time) const + void set_value(typename detail::future_traits<R>::source_reference_type r) { - return timed_wait_until(boost::get_system_time()+rel_time); + lazy_init(); + boost::unique_lock<boost::mutex> lock(future_->mutex); + if(future_->done) + { + boost::throw_exception(promise_already_satisfied()); + } + future_->mark_finished_with_result_internal(r, lock); } - bool timed_wait_until(boost::system_time const& abs_time) const +// void set_value(R && r); + void set_value(typename detail::future_traits<R>::rvalue_source_type r) { - if(!future_) + lazy_init(); + boost::unique_lock<boost::mutex> lock(future_->mutex); + if(future_->done) { - boost::throw_exception(future_uninitialized()); + boost::throw_exception(promise_already_satisfied()); } - return future_->timed_wait_until(abs_time); +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + future_->mark_finished_with_result_internal(boost::forward<R>(r), lock); +#else + future_->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r), lock); +#endif } -#ifdef BOOST_THREAD_USES_CHRONO - template <class Rep, class Period> - future_status - wait_for(const chrono::duration<Rep, Period>& rel_time) const + void set_exception(boost::exception_ptr p) { - return wait_until(chrono::steady_clock::now() + rel_time); + lazy_init(); + boost::unique_lock<boost::mutex> lock(future_->mutex); + if(future_->done) + { + boost::throw_exception(promise_already_satisfied()); + } + future_->mark_exceptional_finish_internal(p, lock); + } + template <typename E> + void set_exception(E ex) + { + set_exception(copy_exception(ex)); + } + // setting the result with deferred notification + void set_value_at_thread_exit(const R& r) + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_value_at_thread_exit(r); + } + void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r) + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_value_at_thread_exit(boost::move(r)); } - template <class Clock, class Duration> - future_status - wait_until(const chrono::time_point<Clock, Duration>& abs_time) const + void set_exception_at_thread_exit(exception_ptr e) { - if(!future_) + if (future_.get()==0) { - boost::throw_exception(future_uninitialized()); + boost::throw_exception(promise_moved()); } - return future_->wait_until(abs_time); + future_->set_exception_at_thread_exit(e); + } + template <typename E> + void set_exception_at_thread_exit(E ex) + { + set_exception_at_thread_exit(copy_exception(ex)); } -#endif - }; - BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future<T> BOOST_THREAD_DCL_MOVABLE_END + template<typename F> + void set_wait_callback(F f) + { + lazy_init(); + future_->set_wait_callback(f,this); + } + + }; template <typename R> - class promise + class promise<R&> { - typedef boost::shared_ptr<detail::future_object<R> > future_ptr; + typedef boost::shared_ptr<detail::shared_state<R&> > future_ptr; future_ptr future_; bool future_obtained; void lazy_init() { -#if defined BOOST_THREAD_PROMISE_LAZY +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY +#include <boost/detail/atomic_undef_macros.hpp> 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::shared_state<R&>)); } +#include <boost/detail/atomic_redef_macros.hpp> #endif } @@ -1122,19 +2255,19 @@ namespace boost template <class Allocator> promise(boost::allocator_arg_t, Allocator a) { - typedef typename Allocator::template rebind<detail::future_object<R> >::other A2; + typedef typename Allocator::template rebind<detail::shared_state<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_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<R&>(), D(a2, 1) ); future_obtained = false; } #endif promise(): -#if defined BOOST_THREAD_PROMISE_LAZY +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY future_(), #else - future_(new detail::future_object<R>()), + future_(new detail::shared_state<R&>()), #endif future_obtained(false) {} @@ -1143,11 +2276,11 @@ namespace boost { if(future_) { - boost::lock_guard<boost::mutex> lock(future_->mutex); + boost::unique_lock<boost::mutex> lock(future_->mutex); - if(!future_->done) + if(!future_->done && !future_->is_constructed) { - future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise())); + future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock); } } } @@ -1175,7 +2308,7 @@ namespace boost } // Result retrieval - BOOST_THREAD_FUTURE<R> get_future() + BOOST_THREAD_FUTURE<R&> get_future() { lazy_init(); if (future_.get()==0) @@ -1187,47 +2320,59 @@ namespace boost boost::throw_exception(future_already_retrieved()); } future_obtained=true; - return BOOST_THREAD_FUTURE<R>(future_); + return BOOST_THREAD_FUTURE<R&>(future_); } - void set_value(typename detail::future_traits<R>::source_reference_type r) + void set_value(R& r) { lazy_init(); - boost::lock_guard<boost::mutex> lock(future_->mutex); + boost::unique_lock<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, lock); } -// void set_value(R && r); - void set_value(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); + boost::unique_lock<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_exceptional_finish_internal(p, lock); } - - void set_exception(boost::exception_ptr p) + template <typename E> + void set_exception(E ex) { - lazy_init(); - boost::lock_guard<boost::mutex> lock(future_->mutex); - if(future_->done) - { - boost::throw_exception(promise_already_satisfied()); - } - future_->mark_exceptional_finish_internal(p); + set_exception(copy_exception(ex)); } // 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 + void set_value_at_thread_exit(R& r) + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_value_at_thread_exit(r); + } + + void set_exception_at_thread_exit(exception_ptr e) + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_exception_at_thread_exit(e); + } + template <typename E> + void set_exception_at_thread_exit(E ex) + { + set_exception_at_thread_exit(copy_exception(ex)); + } template<typename F> void set_wait_callback(F f) @@ -1237,22 +2382,21 @@ namespace boost } }; - template <> class promise<void> { - typedef boost::shared_ptr<detail::future_object<void> > future_ptr; + typedef boost::shared_ptr<detail::shared_state<void> > future_ptr; future_ptr future_; bool future_obtained; void lazy_init() { -#if defined BOOST_THREAD_PROMISE_LAZY +#if defined BOOST_THREAD_PROVIDES_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::shared_state<void>)); } #endif } @@ -1263,19 +2407,19 @@ namespace boost template <class Allocator> promise(boost::allocator_arg_t, Allocator a) { - typedef typename Allocator::template rebind<detail::future_object<void> >::other A2; + typedef typename Allocator::template rebind<detail::shared_state<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_ = future_ptr(::new(a2.allocate(1)) detail::shared_state<void>(), D(a2, 1) ); future_obtained = false; } #endif promise(): -#if defined BOOST_THREAD_PROMISE_LAZY +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY future_(), #else - future_(new detail::future_object<void>), + future_(new detail::shared_state<void>), #endif future_obtained(false) {} @@ -1284,11 +2428,11 @@ namespace boost { if(future_) { - boost::lock_guard<boost::mutex> lock(future_->mutex); + boost::unique_lock<boost::mutex> lock(future_->mutex); - if(!future_->done) + if(!future_->done && !future_->is_constructed) { - future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise())); + future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock); } } } @@ -1331,29 +2475,59 @@ namespace boost boost::throw_exception(future_already_retrieved()); } future_obtained=true; + //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<void>(future_)); return BOOST_THREAD_FUTURE<void>(future_); } void set_value() { lazy_init(); - boost::lock_guard<boost::mutex> lock(future_->mutex); + boost::unique_lock<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(lock); } void set_exception(boost::exception_ptr p) { lazy_init(); - boost::lock_guard<boost::mutex> lock(future_->mutex); + boost::unique_lock<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,lock); + } + template <typename E> + void set_exception(E ex) + { + set_exception(copy_exception(ex)); + } + + // setting the result with deferred notification + void set_value_at_thread_exit() + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_value_at_thread_exit(); + } + + void set_exception_at_thread_exit(exception_ptr e) + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_exception_at_thread_exit(e); + } + template <typename E> + void set_exception_at_thread_exit(E ex) + { + set_exception_at_thread_exit(copy_exception(ex)); } template<typename F> @@ -1364,28 +2538,50 @@ namespace boost } }; - +} #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS - namespace container +namespace boost { namespace container { + template <class R, class Alloc> + struct uses_allocator< ::boost::promise<R> , Alloc> : true_type { - template <class R, class Alloc> - struct uses_allocator<promise<R> , Alloc> : true_type - { - }; - } + }; +}} +#if ! defined BOOST_NO_CXX11_ALLOCATOR +namespace std { + template <class R, class Alloc> + struct uses_allocator< ::boost::promise<R> , Alloc> : true_type + { + }; +} +#endif #endif +namespace boost +{ + BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END namespace detail { - template<typename R> - struct task_base: - detail::future_object<R> +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + template<typename R> + struct task_base_shared_state; +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template<typename R, typename ...ArgTypes> + struct task_base_shared_state<R(ArgTypes...)>: +#else + template<typename R> + struct task_base_shared_state<R()>: +#endif +#else + template<typename R> + struct task_base_shared_state: +#endif + detail::shared_state<R> { bool started; - task_base(): + task_base_shared_state(): started(false) {} @@ -1393,7 +2589,13 @@ namespace boost { started=false; } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0; + void run(BOOST_THREAD_RV_REF(ArgTypes) ... args) +#else + virtual void do_run()=0; void run() +#endif { { boost::lock_guard<boost::mutex> lk(this->mutex); @@ -1403,56 +2605,213 @@ namespace boost } started=true; } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + do_run(boost::forward<ArgTypes>(args)...); +#else do_run(); +#endif + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0; + void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) +#else + virtual void do_apply()=0; + void apply() +#endif + { + { + boost::lock_guard<boost::mutex> lk(this->mutex); + if(started) + { + boost::throw_exception(task_already_started()); + } + started=true; + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + do_apply(boost::forward<ArgTypes>(args)...); +#else + do_apply(); +#endif } void owner_destroyed() { - boost::lock_guard<boost::mutex> lk(this->mutex); + boost::unique_lock<boost::mutex> lk(this->mutex); if(!started) { started=true; - this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise())); + this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk); } } - - virtual void do_run()=0; }; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + template<typename F, typename R> + struct task_shared_state; +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template<typename F, typename R, typename ...ArgTypes> + struct task_shared_state<F, R(ArgTypes...)>: + task_base_shared_state<R(ArgTypes...)> +#else + template<typename F, typename R> + struct task_shared_state<F, R()>: + task_base_shared_state<R()> +#endif +#else + template<typename F, typename R> + struct task_shared_state: + task_base_shared_state<R> +#endif + { + private: + task_shared_state(task_shared_state&); + public: + F f; + task_shared_state(F const& f_): + f(f_) + {} + task_shared_state(BOOST_THREAD_RV_REF(F) f_): + f(boost::move(f_)) + {} +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...)); + } +#else + void do_apply() + { + try + { + this->set_value_at_thread_exit(f()); + } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + this->set_interrupted_at_thread_exit(); + } +#endif + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...)); + } +#else + void do_run() + { + try + { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + R res((f())); + this->mark_finished_with_result(boost::move(res)); +#else + this->mark_finished_with_result(f()); +#endif + } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + this->mark_interrupted_finish(); + } +#endif + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; - template<typename R,typename F> - struct task_object: - task_base<R> +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template<typename F, typename R, typename ...ArgTypes> + struct task_shared_state<F, R&(ArgTypes...)>: + task_base_shared_state<R&(ArgTypes...)> +#else + template<typename F, typename R> + struct task_shared_state<F, R&()>: + task_base_shared_state<R&()> +#endif +#else + template<typename F, typename R> + struct task_shared_state<F,R&>: + task_base_shared_state<R&> +#endif { private: - task_object(task_object&); + task_shared_state(task_shared_state&); public: F f; - task_object(F const& f_): + task_shared_state(F const& 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_): + task_shared_state(BOOST_THREAD_RV_REF(F) f_): f(boost::move(f_)) {} + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...)); + } +#else + void do_apply() + { + try + { + this->set_value_at_thread_exit(f()); + } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + this->set_interrupted_at_thread_exit(); + } #endif + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...)); + } +#else void do_run() { try { - this->mark_finished_with_result(f()); + R& res((f())); + this->mark_finished_with_result(res); } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS catch(thread_interrupted& ) { this->mark_interrupted_finish(); } +#endif catch(...) { this->mark_exceptional_finish(); @@ -1460,66 +2819,258 @@ namespace boost } }; - template<typename R> - struct task_object<R,R (*)()>: - task_base<R> +#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template<typename R, typename ...ArgTypes> + struct task_shared_state<R (*)(ArgTypes...), R(ArgTypes...)>: + task_base_shared_state<R(ArgTypes...)> +#else + template<typename R> + struct task_shared_state<R (*)(), R()>: + task_base_shared_state<R()> +#endif +#else + template<typename R> + struct task_shared_state<R (*)(), R> : + task_base_shared_state<R> +#endif { private: - task_object(task_object&); + task_shared_state(task_shared_state&); public: +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + R (*f)(BOOST_THREAD_RV_REF(ArgTypes) ... ); + task_shared_state(R (*f_)(BOOST_THREAD_RV_REF(ArgTypes) ... )): + f(f_) + {} +#else R (*f)(); - task_object(R (*f_)()): + task_shared_state(R (*f_)()): f(f_) {} +#endif + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...)); + } +#else + void do_apply() + { + try + { + R r((f())); + this->set_value_at_thread_exit(boost::move(r)); + } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + this->set_interrupted_at_thread_exit(); + } +#endif + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } + + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...)); + } +#else void do_run() { try { - this->mark_finished_with_result(f()); + R res((f())); + this->mark_finished_with_result(boost::move(res)); } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS catch(thread_interrupted& ) { this->mark_interrupted_finish(); } +#endif catch(...) { this->mark_exceptional_finish(); } } }; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template<typename R, typename ...ArgTypes> + struct task_shared_state<R& (*)(ArgTypes...), R&(ArgTypes...)>: + task_base_shared_state<R&(ArgTypes...)> +#else + template<typename R> + struct task_shared_state<R& (*)(), R&()>: + task_base_shared_state<R&()> +#endif +#else + template<typename R> + struct task_shared_state<R& (*)(), R&> : + task_base_shared_state<R&> +#endif + { + private: + task_shared_state(task_shared_state&); + public: +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + R& (*f)(BOOST_THREAD_RV_REF(ArgTypes) ... ); + task_shared_state(R& (*f_)(BOOST_THREAD_RV_REF(ArgTypes) ... )): + f(f_) + {} +#else + R& (*f)(); + task_shared_state(R& (*f_)()): + f(f_) + {} +#endif + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->set_value_at_thread_exit(f(boost::forward<ArgTypes>(args)...)); + } +#else + void do_apply() + { + try + { + this->set_value_at_thread_exit(f()); + } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + this->set_interrupted_at_thread_exit(); + } +#endif + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->mark_finished_with_result(f(boost::forward<ArgTypes>(args)...)); + } +#else + void do_run() + { + try + { + this->mark_finished_with_result(f()); + } +#endif +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + this->mark_interrupted_finish(); + } +#endif + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; +#endif +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template<typename F, typename ...ArgTypes> + struct task_shared_state<F, void(ArgTypes...)>: + task_base_shared_state<void(ArgTypes...)> +#else + template<typename F> + struct task_shared_state<F, void()>: + task_base_shared_state<void()> +#endif +#else template<typename F> - struct task_object<void,F>: - task_base<void> + struct task_shared_state<F,void>: + task_base_shared_state<void> +#endif { private: - task_object(task_object&); + task_shared_state(task_shared_state&); public: F f; - task_object(F const& f_): + task_shared_state(F const& 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_): + task_shared_state(BOOST_THREAD_RV_REF(F) f_): f(boost::move(f_)) {} + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + f(boost::forward<ArgTypes>(args)...); +#else + void do_apply() + { + try + { + f(); #endif + this->set_value_at_thread_exit(); + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + this->set_interrupted_at_thread_exit(); + } +#endif + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + f(boost::forward<ArgTypes>(args)...); +#else void do_run() { try { f(); +#endif this->mark_finished_with_result(); } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS catch(thread_interrupted& ) { this->mark_interrupted_finish(); } +#endif catch(...) { this->mark_exceptional_finish(); @@ -1527,43 +3078,109 @@ namespace boost } }; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template<typename ...ArgTypes> + struct task_shared_state<void (*)(ArgTypes...), void(ArgTypes...)>: + task_base_shared_state<void(ArgTypes...)> +#else template<> - struct task_object<void,void (*)()>: - task_base<void> + struct task_shared_state<void (*)(), void()>: + task_base_shared_state<void()> +#endif +#else + template<> + struct task_shared_state<void (*)(),void>: + task_base_shared_state<void> +#endif { private: - task_object(task_object&); + task_shared_state(task_shared_state&); public: void (*f)(); - task_object(void (*f_)()): + task_shared_state(void (*f_)()): f(f_) {} + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + f(boost::forward<ArgTypes>(args)...); +#else + void do_apply() + { + try + { + f(); +#endif + this->set_value_at_thread_exit(); + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + catch(thread_interrupted& ) + { + this->set_interrupted_at_thread_exit(); + } +#endif + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + f(boost::forward<ArgTypes>(args)...); +#else void do_run() { try { f(); +#endif this->mark_finished_with_result(); } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS catch(thread_interrupted& ) { this->mark_interrupted_finish(); } +#endif catch(...) { this->mark_exceptional_finish(); } } }; - } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template<typename R, typename ...ArgTypes> + class packaged_task<R(ArgTypes...)> + { + typedef boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task_ptr; + boost::shared_ptr<detail::task_base_shared_state<R(ArgTypes...)> > task; + #else + template<typename R> + class packaged_task<R()> + { + typedef boost::shared_ptr<detail::task_base_shared_state<R()> > task_ptr; + boost::shared_ptr<detail::task_base_shared_state<R()> > task; + #endif +#else template<typename R> class packaged_task { - typedef boost::shared_ptr<detail::task_base<R> > task_ptr; - boost::shared_ptr<detail::task_base<R> > task; + typedef boost::shared_ptr<detail::task_base_shared_state<R> > task_ptr; + boost::shared_ptr<detail::task_base_shared_state<R> > task; +#endif bool future_obtained; + struct dummy; public: typedef R result_type; @@ -1574,294 +3191,1646 @@ namespace boost {} // construction and destruction +#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) - explicit packaged_task(R(*f)()): - task(new detail::task_object<R,R(*)()>(f)),future_obtained(false) - {} +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args) + { + typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...); + typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; + task= task_ptr(new task_shared_state_type(f, boost::forward<ArgTypes>(args)...)); + future_obtained=false; + } + #else + explicit packaged_task(R(*f)()) + { + typedef R(*FR)(); + typedef detail::task_shared_state<FR,R()> task_shared_state_type; + task= task_ptr(new task_shared_state_type(f)); + future_obtained=false; + } + #endif +#else + explicit packaged_task(R(*f)()) + { + typedef R(*FR)(); + typedef detail::task_shared_state<FR,R> task_shared_state_type; + task= task_ptr(new task_shared_state_type(f)); + future_obtained=false; + } +#endif +#endif #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) - {} + explicit packaged_task(BOOST_THREAD_FWD_REF(F) f + , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0 + ) + { + //typedef typename remove_cv<typename remove_reference<F>::type>::type FR; + typedef typename decay<F>::type FR; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; + #else + typedef detail::task_shared_state<FR,R()> task_shared_state_type; + #endif +#else + typedef detail::task_shared_state<FR,R> task_shared_state_type; +#endif + task = task_ptr(new task_shared_state_type(boost::forward<F>(f))); + future_obtained = false; + + } + #else template <class F> - explicit packaged_task(F const& f): - task(new detail::task_object<R,F>(f)),future_obtained(false) - {} + explicit packaged_task(F const& f + , typename boost::disable_if<is_same<typename decay<F>::type, packaged_task>, dummy* >::type=0 + ) + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type; + #else + typedef detail::task_shared_state<F,R()> task_shared_state_type; + #endif +#else + typedef detail::task_shared_state<F,R> task_shared_state_type; +#endif + task = task_ptr(new task_shared_state_type(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) - {} + explicit packaged_task(BOOST_THREAD_RV_REF(F) f) + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type; + task = task_ptr(new task_shared_state_type(boost::forward<F>(f))); +#else + typedef detail::task_shared_state<F,R()> task_shared_state_type; + task = task_ptr(new task_shared_state_type(boost::move(f))); // TODO forward +#endif +#else + typedef detail::task_shared_state<F,R> task_shared_state_type; + task = task_ptr(new task_shared_state_type(boost::forward<F>(f))); +#endif + future_obtained=false; + + } #endif #if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) 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; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; + #else + typedef detail::task_shared_state<FR,R()> task_shared_state_type; + #endif +#else + typedef detail::task_shared_state<FR,R> task_shared_state_type; +#endif + typedef typename Allocator::template rebind<task_shared_state_type>::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) ); + task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) ); future_obtained = false; } -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES template <class F, class Allocator> - packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f) + packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_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; + //typedef typename remove_cv<typename remove_reference<F>::type>::type FR; + typedef typename decay<F>::type FR; + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state<FR,R(ArgTypes...)> task_shared_state_type; + #else + typedef detail::task_shared_state<FR,R()> task_shared_state_type; + #endif +#else + typedef detail::task_shared_state<FR,R> task_shared_state_type; +#endif + typedef typename Allocator::template rebind<task_shared_state_type>::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) ); + task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) ); future_obtained = false; } -#else +#else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES 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; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type; + #else + typedef detail::task_shared_state<F,R()> task_shared_state_type; + #endif +#else + typedef detail::task_shared_state<F,R> task_shared_state_type; +#endif + typedef typename Allocator::template rebind<task_shared_state_type>::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) ); + task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(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; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state<F,R(ArgTypes...)> task_shared_state_type; + #else + typedef detail::task_shared_state<F,R()> task_shared_state_type; + #endif +#else + typedef detail::task_shared_state<F,R> task_shared_state_type; +#endif + typedef typename Allocator::template rebind<task_shared_state_type>::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) ); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward<F>(f)), D(a2, 1) ); +#else + task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) ); // TODO forward +#endif future_obtained = false; } + #endif //BOOST_NO_CXX11_RVALUE_REFERENCES #endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS - ~packaged_task() - { - if(task) - { + ~packaged_task() { + if(task) { task->owner_destroyed(); } } // assignment - packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT : - future_obtained(BOOST_THREAD_RV(other).future_obtained) - { + packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT + : future_obtained(BOOST_THREAD_RV(other).future_obtained) { task.swap(BOOST_THREAD_RV(other).task); BOOST_THREAD_RV(other).future_obtained=false; } - packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT - { + packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT { + + // todo use forward +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + packaged_task temp(boost::move(other)); +#else packaged_task temp(static_cast<BOOST_THREAD_RV_REF(packaged_task)>(other)); +#endif swap(temp); return *this; } - void reset() - { + void reset() { if (!valid()) throw future_error(system::make_error_code(future_errc::no_state)); task->reset(); future_obtained=false; } - void swap(packaged_task& other) BOOST_NOEXCEPT - { + void swap(packaged_task& other) BOOST_NOEXCEPT { task.swap(other.task); std::swap(future_obtained,other.future_obtained); } - bool valid() const BOOST_NOEXCEPT - { + bool valid() const BOOST_NOEXCEPT { return task.get()!=0; } // result retrieval - BOOST_THREAD_FUTURE<R> get_future() - { - if(!task) - { + BOOST_THREAD_FUTURE<R> get_future() { + if(!task) { boost::throw_exception(task_moved()); - } - else if(!future_obtained) - { + } else if(!future_obtained) { future_obtained=true; return BOOST_THREAD_FUTURE<R>(task); - } - else - { + } else { boost::throw_exception(future_already_retrieved()); } - return BOOST_THREAD_FUTURE<R>(); - } - // execution - void operator()() - { - if(!task) - { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void operator()(BOOST_THREAD_RV_REF(ArgTypes)... args) { + if(!task) { + boost::throw_exception(task_moved()); + } + task->run(boost::forward<ArgTypes>(args)...); + } + void make_ready_at_thread_exit(ArgTypes... args) { + if(!task) { + boost::throw_exception(task_moved()); + } + if (task->has_value()) { + boost::throw_exception(promise_already_satisfied()); + } + task->apply(boost::forward<ArgTypes>(args)...); + } +#else + void operator()() { + if(!task) { boost::throw_exception(task_moved()); } task->run(); } - + void make_ready_at_thread_exit() { + if(!task) { + boost::throw_exception(task_moved()); + } + if (task->has_value()) boost::throw_exception(promise_already_satisfied()); + task->apply(); + } +#endif template<typename F> - void set_wait_callback(F f) - { + void set_wait_callback(F f) { 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 {}; - } +namespace boost { namespace container { + template <class R, class Alloc> + struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type + {}; +}} +#if ! defined BOOST_NO_CXX11_ALLOCATOR +namespace std { + template <class R, class Alloc> + struct uses_allocator< ::boost::packaged_task<R> , Alloc> : true_type + {}; +} +#endif #endif - BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END +namespace boost +{ + BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task<T> BOOST_THREAD_DCL_MOVABLE_END +namespace detail +{ + //////////////////////////////// + // make_future_deferred_shared_state + //////////////////////////////// + template <class Rp, class Fp> + BOOST_THREAD_FUTURE<Rp> + make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) { + shared_ptr<future_deferred_shared_state<Rp, Fp> > + h(new future_deferred_shared_state<Rp, Fp>(boost::forward<Fp>(f))); + return BOOST_THREAD_FUTURE<Rp>(h); + } - template <class R> - BOOST_THREAD_FUTURE<R> - async(launch policy, R(*f)()) - { - if (int(policy) & int(launch::async)) - { - packaged_task<R> pt( f ); + //////////////////////////////// + // make_future_async_shared_state + //////////////////////////////// + template <class Rp, class Fp> + BOOST_THREAD_FUTURE<Rp> + make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) { + shared_ptr<future_async_shared_state<Rp, Fp> > + h(new future_async_shared_state<Rp, Fp>(boost::forward<Fp>(f))); + return BOOST_THREAD_FUTURE<Rp>(h); + } +} - 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 ); + //////////////////////////////// + // template <class F, class... ArgTypes> + // future<R> async(launch policy, F&&, ArgTypes&&...); + //////////////////////////////// + +#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template <class R, class... ArgTypes> + BOOST_THREAD_FUTURE<R> + async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) { + typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...); + typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; + typedef typename BF::result_type Rp; + + if (underlying_cast<int>(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>( + BF( + thread_detail::decay_copy(boost::forward<F>(f)) + , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... + ) + )); + } else if (underlying_cast<int>(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>( + BF( + thread_detail::decay_copy(boost::forward<F>(f)) + , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... + ) + )); + } else { + std::terminate(); + BOOST_THREAD_FUTURE<R> ret; + return ::boost::move(ret); + } + } - BOOST_THREAD_FUTURE<R> ret = pt.get_future(); - return ::boost::move(ret); - } else { - BOOST_THREAD_FUTURE<R> ret; - return ::boost::move(ret); - } - } +#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + + template <class R> + BOOST_THREAD_FUTURE<R> + async(launch policy, R(*f)()) { + #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + typedef packaged_task<R()> packaged_task_type; + #else + typedef packaged_task<R> packaged_task_type; + #endif + + if (underlying_cast<int>(policy) & int(launch::async)) { + packaged_task_type pt( f ); + BOOST_THREAD_FUTURE<R> ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future()); + ret.set_async(); + boost::thread( boost::move(pt) ).detach(); + return ::boost::move(ret); + } else if (underlying_cast<int>(policy) & int(launch::deferred)) { + std::terminate(); + BOOST_THREAD_FUTURE<R> ret; + return ::boost::move(ret); + } else { + std::terminate(); + BOOST_THREAD_FUTURE<R> ret; + return ::boost::move(ret); + } + } +#endif +#endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + + template <class F, class ...ArgTypes> + BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( + typename decay<ArgTypes>::type... + )>::type> + async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { + typedef typename boost::result_of<typename decay<F>::type( + typename decay<ArgTypes>::type... + )>::type R; + typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; + typedef typename BF::result_type Rp; + + if (underlying_cast<int>(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state<Rp>( + BF( + thread_detail::decay_copy(boost::forward<F>(f)) + , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... + ) + )); + } else if (underlying_cast<int>(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state<Rp>( + BF( + thread_detail::decay_copy(boost::forward<F>(f)) + , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... + ) + )); + } else { + std::terminate(); + 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) +#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + + 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 defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + typedef packaged_task<R()> packaged_task_type; +#else // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + typedef packaged_task<R> packaged_task_type; +#endif // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + + if (underlying_cast<int>(policy) & int(launch::async)) { + packaged_task_type pt( boost::forward<F>(f) ); + BOOST_THREAD_FUTURE<R> ret = pt.get_future(); + ret.set_async(); + boost::thread( boost::move(pt) ).detach(); + return ::boost::move(ret); + } else if (underlying_cast<int>(policy) & int(launch::deferred)) { + std::terminate(); + BOOST_THREAD_FUTURE<R> ret; + return ::boost::move(ret); + // return boost::detail::make_future_deferred_shared_state<Rp>( + // BF( + // thread_detail::decay_copy(boost::forward<F>(f)) + // ) + // ); + } else { + std::terminate(); + BOOST_THREAD_FUTURE<R> ret; + return ::boost::move(ret); + } + } +#endif // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS +namespace detail { + ///////////////////////// + /// shared_state_nullary_task + ///////////////////////// + template<typename Rp, typename Fp> + struct shared_state_nullary_task { - 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) ); + shared_state<Rp>* that; + Fp f_; + public: - BOOST_THREAD_FUTURE<R> ret = pt.get_future(); - boost::thread( boost::move(pt) ).detach(); - return ::boost::move(ret); + shared_state_nullary_task(shared_state<Rp>* st, BOOST_THREAD_FWD_REF(Fp) f) + : that(st), f_(boost::forward<Fp>(f)) + {}; +#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_THREAD_MOVABLE(shared_state_nullary_task) + shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT + : that(x.that), f_(x.f_) + {} + shared_state_nullary_task& operator=(BOOST_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT + { + if (this != &x) { + that=x.that; + f_=x.f_; } - else if (int(policy) & int(launch::deferred)) - { - packaged_task<R> pt( boost::forward<F>(f) ); + return *this; + } + // move + shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT + : that(x.that), f_(boost::move(x.f_)) + { + x.that=0; + } + shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT + { + if (this != &x) { + that=x.that; + f_=boost::move(x.f_); + x.that=0; + } + return *this; + } +#endif + void operator()() { + try { + that->mark_finished_with_result(f_()); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } catch(thread_interrupted& ) { + that->mark_interrupted_finish(); +#endif // defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } catch(...) { + that->mark_exceptional_finish(); + } + + } + }; - BOOST_THREAD_FUTURE<R> ret = pt.get_future(); - return ::boost::move(ret); - } else { - BOOST_THREAD_FUTURE<R> ret; - return ::boost::move(ret); + template<typename Fp> + struct shared_state_nullary_task<void, Fp> + { + shared_state<void>* that; + Fp f_; + public: + shared_state_nullary_task(shared_state<void>* st, BOOST_THREAD_FWD_REF(Fp) f) + : that(st), f_(boost::forward<Fp>(f)) + {}; +#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_THREAD_MOVABLE(shared_state_nullary_task) + shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT + : that(x.that), f_(x.f_) + {} + shared_state_nullary_task& operator=(BOOST_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT + { + if (this != &x) { + that=x.that; + f_=x.f_; } - } - template <class F> - BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> - async(BOOST_THREAD_RV_REF(F) f) + return *this; + } + // move + shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT + : that(x.that), f_(boost::move(x.f_)) + { + x.that=0; + } + shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { + if (this != &x) { + that=x.that; + f_=boost::move(x.f_); + x.that=0; + } + return *this; + } +#endif + void operator()() { + try { + f_(); + that->mark_finished_with_result(); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } catch(thread_interrupted& ) { + that->mark_interrupted_finish(); +#endif // defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } catch(...) { + that->mark_exceptional_finish(); + } + } + }; + + template<typename Rp, typename Fp> + struct shared_state_nullary_task<Rp&, Fp> { - return async(launch::any, boost::forward<F>(f)); + shared_state<Rp&>* that; + Fp f_; + public: + shared_state_nullary_task(shared_state<Rp&>* st, BOOST_THREAD_FWD_REF(Fp) f) + : that(st), f_(boost::forward<Fp>(f)) + {} +#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_THREAD_MOVABLE(shared_state_nullary_task) + shared_state_nullary_task(shared_state_nullary_task const& x) BOOST_NOEXCEPT + : that(x.that), f_(x.f_) {} + + shared_state_nullary_task& operator=(BOOST_COPY_ASSIGN_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { + if (this != &x){ + that=x.that; + f_=x.f_; + } + return *this; + } + // move + shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT + : that(x.that), f_(boost::move(x.f_)) + { + x.that=0; + } + shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { + if (this != &x) { + that=x.that; + f_=boost::move(x.f_); + x.that=0; + } + return *this; + } +#endif + void operator()() { + try { + that->mark_finished_with_result(f_()); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } catch(thread_interrupted& ) { + that->mark_interrupted_finish(); +#endif // defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } catch(...) { + that->mark_exceptional_finish(); + } + } + }; + + ///////////////////////// + /// future_executor_shared_state_base + ///////////////////////// + template<typename Rp, typename Executor> + struct future_executor_shared_state: shared_state<Rp> + { + typedef shared_state<Rp> base_type; + protected: + public: + template<typename Fp> + future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) { + this->set_executor(); + shared_state_nullary_task<Rp,Fp> t(this, boost::forward<Fp>(f)); + ex.submit(boost::move(t)); + } + + ~future_executor_shared_state() { + this->wait(false); + } + }; + + //////////////////////////////// + // make_future_executor_shared_state + //////////////////////////////// + template <class Rp, class Fp, class Executor> + BOOST_THREAD_FUTURE<Rp> + make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) { + shared_ptr<future_executor_shared_state<Rp, Executor> > + h(new future_executor_shared_state<Rp, Executor>(ex, boost::forward<Fp>(f))); + return BOOST_THREAD_FUTURE<Rp>(h); } + +} // detail + + //////////////////////////////// + // template <class Executor, class F, class... ArgTypes> + // future<R> async(Executor& ex, F&&, ArgTypes&&...); + //////////////////////////////// + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + + template <class Executor, class R, class... ArgTypes> + BOOST_THREAD_FUTURE<R> + async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) { + typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...); + typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; + typedef typename BF::result_type Rp; + + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, + BF( + thread_detail::decay_copy(boost::forward<F>(f)) + , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... + ) + )); + } +#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + + template <class Executor, class F, class ...ArgTypes> + BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( + typename decay<ArgTypes>::type... + )>::type> + async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { + typedef detail::invoker<typename decay<F>::type, typename decay<ArgTypes>::type...> BF; + typedef typename BF::result_type Rp; + + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, + BF( + thread_detail::decay_copy(boost::forward<F>(f)) + , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... + ) + )); + } + +// template <class R, class Executor, class F, class ...ArgTypes> +// BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( +// typename decay<ArgTypes>::type... +// )>::type> +// async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { +// typedef detail::invoker_ret<R, typename decay<F>::type, typename decay<ArgTypes>::type...> BF; +// typedef typename BF::result_type Rp; +// +// return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, +// BF( +// thread_detail::decay_copy(boost::forward<F>(f)) +// , thread_detail::decay_copy(boost::forward<ArgTypes>(args))... +// ) +// )); +// } + +#else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + + template <class Executor, class R> + BOOST_THREAD_FUTURE<R> + async(Executor& ex, R(*f)()) { + typedef R(*F)(); + typedef detail::invoker<F> BF; + typedef typename BF::result_type Rp; + + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, + BF( + f + ) + )); + } + + template <class Executor, class R, class A1> + BOOST_THREAD_FUTURE<R> + async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(A1)), BOOST_THREAD_FWD_REF(A1) a1) { + typedef R(*F)(BOOST_THREAD_FWD_REF(A1)); + typedef detail::invoker<F, typename decay<A1>::type> BF; + typedef typename BF::result_type Rp; + + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, + BF( + f + , thread_detail::decay_copy(boost::forward<A1>(a1)) + ) + )); + } +#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + + template <class Executor, class F> + BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> + async(Executor& ex, BOOST_THREAD_FWD_REF(F) f) { + typedef detail::invoker<typename decay<F>::type> BF; + typedef typename BF::result_type Rp; + + return boost::detail::make_future_executor_shared_state<Rp>(ex, + BF( + thread_detail::decay_copy(boost::forward<F>(f)) + ) + ); + } + + template <class Executor, class F, class A1> + BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( + typename decay<A1>::type + )>::type> + async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) { + typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type> BF; + typedef typename BF::result_type Rp; + + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, + BF( + thread_detail::decay_copy(boost::forward<F>(f)) + , thread_detail::decay_copy(boost::forward<A1>(a1)) + ) + )); + } + + template <class Executor, class F, class A1, class A2> + BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( + typename decay<A1>::type, typename decay<A2>::type + )>::type> + async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) { + typedef detail::invoker<typename decay<F>::type, typename decay<A1>::type, typename decay<A2>::type> BF; + typedef typename BF::result_type Rp; + + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state<Rp>(ex, + BF( + thread_detail::decay_copy(boost::forward<F>(f)) + , thread_detail::decay_copy(boost::forward<A1>(a1)) + , thread_detail::decay_copy(boost::forward<A2>(a2)) + ) + )); + } + +#endif //! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#endif + + //////////////////////////////// + // template <class F, class... ArgTypes> + // future<R> async(F&&, ArgTypes&&...); + //////////////////////////////// + +#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template <class R, class... ArgTypes> + BOOST_THREAD_FUTURE<R> + async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) { + return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward<ArgTypes>(args)...)); + } + #else + template <class R> + BOOST_THREAD_FUTURE<R> + async(R(*f)()) { + return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f)); + } + #endif +#endif + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template <class F, class ...ArgTypes> + BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type( + typename decay<ArgTypes>::type... + )>::type> + async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { + return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f), boost::forward<ArgTypes>(args)...)); + } #else + template <class F> + BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> + async(BOOST_THREAD_RV_REF(F) f) { + return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward<F>(f))); + } +#endif -// 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 ); + //////////////////////////////// + // make_future deprecated + //////////////////////////////// + template <typename T> + BOOST_THREAD_FUTURE<typename decay<T>::type> make_future(BOOST_THREAD_FWD_REF(T) value) { + typedef typename decay<T>::type future_value_type; + promise<future_value_type> p; + p.set_value(boost::forward<future_value_type>(value)); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + +#if defined BOOST_THREAD_USES_MOVE + inline BOOST_THREAD_FUTURE<void> make_future() { + promise<void> p; + p.set_value(); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } +#endif + + //////////////////////////////// + // make_ready_future + //////////////////////////////// + template <typename T> + BOOST_THREAD_FUTURE<typename decay<T>::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) { + typedef typename decay<T>::type future_value_type; + promise<future_value_type> p; + p.set_value(boost::forward<future_value_type>(value)); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + + template <typename T, typename T1> + BOOST_THREAD_FUTURE<T> make_ready_no_decay_future(T1 value) { + typedef T future_value_type; + promise<future_value_type> p; + p.set_value(value); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + +#if defined BOOST_THREAD_USES_MOVE + inline BOOST_THREAD_FUTURE<void> make_ready_future() { + promise<void> p; + p.set_value(); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } +#endif + + template <typename T> + BOOST_THREAD_FUTURE<T> make_ready_future(exception_ptr ex) { + promise<T> p; + p.set_exception(ex); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } +// template <typename T, typename E> +// BOOST_THREAD_FUTURE<T> make_ready_future(E ex) +// { +// promise<T> p; +// p.set_exception(boost::copy_exception(ex)); +// return BOOST_THREAD_MAKE_RV_REF(p.get_future()); +// } + + template <typename T> + BOOST_THREAD_FUTURE<T> make_exceptional_future(exception_ptr ex) { + promise<T> p; + p.set_exception(ex); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + + template <typename T, typename E> + BOOST_THREAD_FUTURE<T> make_exceptional_future(E ex) { + promise<T> p; + p.set_exception(boost::copy_exception(ex)); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + + template <typename T> + BOOST_THREAD_FUTURE<T> make_exceptional_future() { + promise<T> p; + p.set_exception(boost::current_exception()); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + +#if 0 + template<typename CLOSURE> + make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE<decltype(closure())> { + typedef decltype(closure()) T; + promise<T> p; + try { + p.set_value(closure()); + } catch(...) { + p.set_exception(std::current_exception()); + } + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } +#endif + + //////////////////////////////// + // make_shared_future deprecated + //////////////////////////////// + template <typename T> + shared_future<typename decay<T>::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) { + typedef typename decay<T>::type future_type; + promise<future_type> p; + p.set_value(boost::forward<T>(value)); + return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); + } + + inline shared_future<void> make_shared_future() { + promise<void> p; + return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); + } + +// //////////////////////////////// +// // make_ready_shared_future +// //////////////////////////////// +// template <typename T> +// shared_future<typename decay<T>::type> make_ready_shared_future(BOOST_THREAD_FWD_REF(T) value) +// { +// typedef typename decay<T>::type future_type; +// promise<future_type> p; +// p.set_value(boost::forward<T>(value)); +// return p.get_future().share(); +// } // -// 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); -// } +// inline shared_future<void> make_ready_shared_future() +// { +// promise<void> p; +// return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); +// +// } +// +// //////////////////////////////// +// // make_exceptional_shared_future +// //////////////////////////////// +// template <typename T> +// shared_future<T> make_exceptional_shared_future(exception_ptr ex) +// { +// promise<T> p; +// p.set_exception(ex); +// return p.get_future().share(); +// } + + //////////////////////////////// + // detail::future_async_continuation_shared_state + //////////////////////////////// +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION +namespace detail +{ + + ///////////////////////// + /// future_async_continuation_shared_state + ///////////////////////// + + template<typename F, typename Rp, typename Fp> + struct future_async_continuation_shared_state: future_async_shared_state_base<Rp> + { + F parent; + Fp continuation; + + public: + future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : parent(boost::move(f)), + continuation(boost::move(c)) { + } + + void launch_continuation(boost::unique_lock<boost::mutex>& ) { + //lock.unlock(); + this->thr_ = thread(&future_async_continuation_shared_state::run, this); + } + + static void run(future_async_continuation_shared_state* that) { + try { + that->mark_finished_with_result(that->continuation(boost::move(that->parent))); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } catch(thread_interrupted& ) { + that->mark_interrupted_finish(); +#endif + } catch(...) { + that->mark_exceptional_finish(); + } + } + + ~future_async_continuation_shared_state() { + this->join(); + } + }; + + template<typename F, typename Fp> + struct future_async_continuation_shared_state<F, void, Fp>: public future_async_shared_state_base<void> + { + F parent; + Fp continuation; + + public: + future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : parent(boost::move(f)), + continuation(boost::move(c)) { + } + + void launch_continuation(boost::unique_lock<boost::mutex>& ) { + //lk.unlock(); + this->thr_ = thread(&future_async_continuation_shared_state::run, this); + } + + static void run(future_async_continuation_shared_state* that) { + try { + that->continuation(boost::move(that->parent)); + that->mark_finished_with_result(); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } catch(thread_interrupted& ) { + that->mark_interrupted_finish(); +#endif + } catch(...) { + that->mark_exceptional_finish(); + } + } + + ~future_async_continuation_shared_state() { + this->join(); + } + }; + + ////////////////////////// + /// future_deferred_continuation_shared_state + ////////////////////////// + template<typename F, typename Rp, typename Fp> + struct future_deferred_continuation_shared_state: shared_state<Rp> + { + F parent; + Fp continuation; + + public: + future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : parent(boost::move(f)), + continuation(boost::move(c)) { + this->set_deferred(); + } + + virtual void launch_continuation(boost::unique_lock<boost::mutex>& ) { + //execute(lk); + } + + virtual void execute(boost::unique_lock<boost::mutex>& lck) { + try { + Fp local_fuct=boost::move(continuation); + F ftmp = boost::move(parent); + relocker relock(lck); + Rp res = local_fuct(boost::move(ftmp)); + relock.lock(); + this->mark_finished_with_result_internal(boost::move(res), lck); + } catch (...) { + this->mark_exceptional_finish_internal(current_exception(), lck); + } + } + }; + + template<typename F, typename Fp> + struct future_deferred_continuation_shared_state<F,void,Fp>: shared_state<void> + { + F parent; + Fp continuation; + + public: + future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : parent(boost::move(f)), + continuation(boost::move(c)) { + this->set_deferred(); + } + + virtual void launch_continuation(boost::unique_lock<boost::mutex>& ) { + //execute(lk); + } + virtual void execute(boost::unique_lock<boost::mutex>& lck) { + try { + Fp local_fuct=boost::move(continuation); + F ftmp = boost::move(parent); + relocker relock(lck); + local_fuct(boost::move(ftmp)); + relock.lock(); + this->mark_finished_with_result_internal(lck); + } catch (...) { + this->mark_exceptional_finish_internal(current_exception(), lck); + } + } + }; + + //////////////////////////////// + // make_future_deferred_continuation_shared_state + //////////////////////////////// + template<typename F, typename Rp, typename Fp> + BOOST_THREAD_FUTURE<Rp> + make_future_deferred_continuation_shared_state( + boost::unique_lock<boost::mutex> &lock, + BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) { + shared_ptr<future_deferred_continuation_shared_state<F, Rp, Fp> > + h(new future_deferred_continuation_shared_state<F, Rp, Fp>(boost::move(f), boost::forward<Fp>(c))); + h->parent.future_->set_continuation_ptr(h, lock); + return BOOST_THREAD_FUTURE<Rp>(h); + } + + //////////////////////////////// + // make_future_async_continuation_shared_state + //////////////////////////////// + template<typename F, typename Rp, typename Fp> + BOOST_THREAD_FUTURE<Rp> + make_future_async_continuation_shared_state( + boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f, + BOOST_THREAD_FWD_REF(Fp) c) { + shared_ptr<future_async_continuation_shared_state<F,Rp, Fp> > + h(new future_async_continuation_shared_state<F,Rp, Fp>(boost::move(f), boost::forward<Fp>(c))); + h->parent.future_->set_continuation_ptr(h, lock); + + return BOOST_THREAD_FUTURE<Rp>(h); + } +} + + //////////////////////////////// + // template<typename F> + // auto future<R>::then(F&& func) -> BOOST_THREAD_FUTURE<decltype(func(*this))>; + //////////////////////////////// + + template <typename R> + template <typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> + BOOST_THREAD_FUTURE<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) { + typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + boost::unique_lock<boost::mutex> lock(this->future_->mutex); + if (underlying_cast<int>(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } else if (underlying_cast<int>(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } + } + + template <typename R> + template <typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type> + BOOST_THREAD_FUTURE<R>::then(BOOST_THREAD_FWD_REF(F) func) { + typedef typename boost::result_of<F(BOOST_THREAD_FUTURE<R>)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + boost::unique_lock<boost::mutex> lock(this->future_->mutex); + if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) { + return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( + lock, boost::move(*this), boost::forward<F>(func) + ); + } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) { + this->future_->wait_internal(lock); + return boost::detail::make_future_deferred_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( + lock, boost::move(*this), boost::forward<F>(func) + ); + } else { + return boost::detail::make_future_async_continuation_shared_state<BOOST_THREAD_FUTURE<R>, future_type, F>( + lock, boost::move(*this), boost::forward<F>(func) + ); + } + } + + +//#if 0 && defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) +// template <typename R> +// template<typename RF> +// BOOST_THREAD_FUTURE<RF> +// BOOST_THREAD_FUTURE<R>::then(RF(*func)(BOOST_THREAD_FUTURE<R>&)) +// { +// +// typedef RF future_type; +// +// if (this->future_) +// { +// boost::unique_lock<boost::mutex> lock(this->future_->mutex); +// detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr = +// new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func); +// if (ptr==0) +// { +// return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>()); +// } +// this->future_->set_continuation_ptr(ptr, lock); +// return ptr->get_future(); +// } else { +// // fixme what to do when the future has no associated state? +// return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>()); // } -// template <class F> -// BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> -// async(F const& f) +// +// } +// template <typename R> +// template<typename RF> +// BOOST_THREAD_FUTURE<RF> +// BOOST_THREAD_FUTURE<R>::then(launch policy, RF(*func)(BOOST_THREAD_FUTURE<R>&)) +// { +// +// typedef RF future_type; +// +// if (this->future_) // { -// return async(launch::any, f); +// boost::unique_lock<boost::mutex> lock(this->future_->mutex); +// detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&) > *ptr = +// new detail::future_continuation<BOOST_THREAD_FUTURE<R>, future_type, RF(*)(BOOST_THREAD_FUTURE&)>(*this, func, policy); +// if (ptr==0) +// { +// return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>()); +// } +// this->future_->set_continuation_ptr(ptr, lock); +// return ptr->get_future(); +// } else { +// // fixme what to do when the future has no associated state? +// return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE<future_type>()); // } +// +// } +//#endif + + template <typename R> + template <typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type> + shared_future<R>::then(launch policy, BOOST_THREAD_FWD_REF(F) func) + { + typedef typename boost::result_of<F(shared_future<R>)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + boost::unique_lock<boost::mutex> lock(this->future_->mutex); + if (underlying_cast<int>(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } else if (underlying_cast<int>(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>( + lock, boost::move(*this), boost::forward<F>(func) + ))); + } + } + + template <typename R> + template <typename F> + inline BOOST_THREAD_FUTURE<typename boost::result_of<F(shared_future<R>)>::type> + shared_future<R>::then(BOOST_THREAD_FWD_REF(F) func) { + typedef typename boost::result_of<F(shared_future<R>)>::type future_type; + + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + boost::unique_lock<boost::mutex> lock(this->future_->mutex); + if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::async)) { + return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>( + lock, boost::move(*this), boost::forward<F>(func)); + } else if (underlying_cast<int>(this->launch_policy(lock)) & int(launch::deferred)) { + this->future_->wait_internal(lock); + return boost::detail::make_future_deferred_continuation_shared_state<shared_future<R>, future_type, F>( + lock, boost::move(*this), boost::forward<F>(func)); + } else { + return boost::detail::make_future_async_continuation_shared_state<shared_future<R>, future_type, F>( + lock, boost::move(*this), boost::forward<F>(func)); + } + } + +namespace detail +{ + template <typename T> + struct mfallbacker_to + { + T value_; + typedef T result_type; + mfallbacker_to(BOOST_THREAD_RV_REF(T) v) + : value_(boost::move(v)) + {} + + T operator()(BOOST_THREAD_FUTURE<T> fut) { + return fut.get_or(boost::move(value_)); + } + }; + template <typename T> + struct cfallbacker_to + { + T value_; + typedef T result_type; + cfallbacker_to(T const& v) + : value_(v) + {} + + T operator()(BOOST_THREAD_FUTURE<T> fut) { + return fut.get_or(value_); + + } + }; +} + //////////////////////////////// + // future<R> future<R>::fallback_to(R&& v); + //////////////////////////////// + + template <typename R> + template <typename R2> + inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type + BOOST_THREAD_FUTURE<R>::fallback_to(BOOST_THREAD_RV_REF(R2) v) { + return then(detail::mfallbacker_to<R>(boost::move(v))); + } + + template <typename R> + template <typename R2> + inline typename boost::disable_if< is_void<R2>, BOOST_THREAD_FUTURE<R> >::type + BOOST_THREAD_FUTURE<R>::fallback_to(R2 const& v) { + return then(detail::cfallbacker_to<R>(v)); + } + +#endif + +#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP +namespace detail +{ + ///////////////////////// + /// future_unwrap_shared_state + ///////////////////////// + + template<typename F, typename Rp> + struct future_unwrap_shared_state: shared_state<Rp> + { + F parent; + public: + explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f) + : parent(boost::move(f)) {} + virtual void wait(bool ) { // todo see if rethrow must be used + boost::unique_lock<boost::mutex> lock(mutex); + parent.get().wait(); + } + virtual Rp get() { + boost::unique_lock<boost::mutex> lock(mutex); + return parent.get().get(); + } + }; + + template <class F, class Rp> + BOOST_THREAD_FUTURE<Rp> + make_future_unwrap_shared_state(boost::unique_lock<boost::mutex> &lock, BOOST_THREAD_RV_REF(F) f) { + shared_ptr<future_unwrap_shared_state<F, Rp> > + h(new future_unwrap_shared_state<F, Rp>(boost::move(f))); + h->parent.future_->set_continuation_ptr(h, lock); + return BOOST_THREAD_FUTURE<Rp>(h); + } +} + + template <typename R> + inline BOOST_THREAD_FUTURE<R>::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R> >) other) + : base_type(other.unwrap()) {} - template <class F> - BOOST_THREAD_FUTURE<typename boost::result_of<typename decay<F>::type()>::type> - async(launch policy, BOOST_THREAD_FWD_REF(F) f) + template <typename R2> + BOOST_THREAD_FUTURE<R2> + BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >::unwrap() + { + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + boost::unique_lock<boost::mutex> lock(this->future_->mutex); + return boost::detail::make_future_unwrap_shared_state<BOOST_THREAD_FUTURE<BOOST_THREAD_FUTURE<R2> >, R2>(lock, boost::move(*this)); + } +#endif + +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY +namespace detail +{ + struct input_iterator_tag {}; + struct vector_tag {}; + struct values_tag {}; + template <typename T> + struct alias_t { typedef T type; }; + + BOOST_CONSTEXPR_OR_CONST input_iterator_tag input_iterator_tag_value = {}; + BOOST_CONSTEXPR_OR_CONST vector_tag vector_tag_value = {}; + BOOST_CONSTEXPR_OR_CONST values_tag values_tag_value = {}; + //////////////////////////////// + // detail::future_async_when_all_shared_state + //////////////////////////////// + template<typename F> + struct future_when_all_vector_shared_state: future_async_shared_state_base<csbl::vector<F> > + { + typedef csbl::vector<F> vector_type; + typedef typename F::value_type value_type; + csbl::vector<F> vec_; + + static void run(future_when_all_vector_shared_state* that) { + try { + boost::wait_for_all(that->vec_.begin(), that->vec_.end()); + that->mark_finished_with_result(boost::move(that->vec_)); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } catch(thread_interrupted& ) { + that->mark_interrupted_finish(); +#endif + } catch(...) { + that->mark_exceptional_finish(); + } + } + void init() { + this->thr_ = thread(&future_when_all_vector_shared_state::run, this); + } + + public: + template< typename InputIterator> + future_when_all_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last) + : vec_(std::make_move_iterator(first), std::make_move_iterator(last)) { - 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) ); + init(); + } - 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) ); + future_when_all_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v) + : vec_(boost::move(v)) + { + init(); + } - BOOST_THREAD_FUTURE<R> ret = pt.get_future(); - return ::boost::move(ret); - } else { - BOOST_THREAD_FUTURE<R> ret; - return ::boost::move(ret); - } +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + future_when_all_vector_shared_state(values_tag, BOOST_THREAD_RV_REF(T0) f, BOOST_THREAD_RV_REF(T) ... futures) { + vec_.push_back(boost::forward<T0>(f)); + typename alias_t<char[]>::type{ + ( //first part of magic unpacker + vec_.push_back(boost::forward<T>(futures)),'0' + )..., '0' + }; //second part of magic unpacker + init(); + } +#else +#endif + ~future_when_all_vector_shared_state() { + this->join(); + } + + }; + + //////////////////////////////// + // detail::future_async_when_any_shared_state + //////////////////////////////// + template<typename F> + struct future_when_any_vector_shared_state: future_async_shared_state_base<csbl::vector<F> > + { + typedef csbl::vector<F> vector_type; + typedef typename F::value_type value_type; + csbl::vector<F> vec_; + + static void run(future_when_any_vector_shared_state* that) + { + try { + boost::wait_for_any(that->vec_.begin(), that->vec_.end()); + that->mark_finished_with_result(boost::move(that->vec_)); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + } catch(thread_interrupted& ) { + that->mark_interrupted_finish(); +#endif + } catch(...) { + that->mark_exceptional_finish(); + } + } + void init() { + this->thr_ = thread(&future_when_any_vector_shared_state::run, this); + } + + public: + template< typename InputIterator> + future_when_any_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last) + : vec_(std::make_move_iterator(first), std::make_move_iterator(last)) + { + init(); } - template <class F> - BOOST_THREAD_FUTURE<typename boost::result_of<F()>::type> - async(BOOST_THREAD_FWD_REF(F) f) + + future_when_any_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector<F>) v) + : vec_(boost::move(v)) { - return async(launch::any, boost::forward<F>(f)); + init(); } +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + future_when_any_vector_shared_state(values_tag, + BOOST_THREAD_RV_REF(T0) f, BOOST_THREAD_RV_REF(T) ... futures + ) { + vec_.push_back(boost::forward<T0>(f)); + typename alias_t<char[]>::type{ + ( //first part of magic unpacker + vec_.push_back(boost::forward<T>(futures)) + ,'0' + )..., + '0' + }; //second part of magic unpacker + init(); + } #endif + ~future_when_any_vector_shared_state() { + this->join(); + } + + }; + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +//#if ! defined(BOOST_NO_CXX11_HDR_TUPLE) + template< typename T0, typename ...T> + struct future_when_all_tuple_shared_state: future_async_shared_state_base< + csbl::tuple<BOOST_THREAD_FUTURE<typename T0::value_type>, BOOST_THREAD_FUTURE<typename T::value_type>... > + > + { + + }; + template< typename T0, typename ...T> + struct future_when_any_tuple_shared_state: future_async_shared_state_base< + csbl::tuple<BOOST_THREAD_FUTURE<typename T0::value_type>, BOOST_THREAD_FUTURE<typename T::value_type>... > + > + { + }; +//#endif +#endif + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename ...T> + struct are_same : true_type {}; + template< typename T0 > + struct are_same<T0> : true_type {}; + template< typename T0, typename T1, typename ...T> + struct are_same<T0, T1, T...> : integral_constant<bool, is_same<T0,T1>::value && are_same<T1, T...>::value> {}; + + template< bool AreSame, typename T0, typename ...T> + struct when_type_impl; + + template< typename T0, typename ...T> + struct when_type_impl<true, T0, T...> + { + typedef csbl::vector<typename decay<T0>::type> container_type; + typedef typename container_type::value_type value_type; + typedef detail::future_when_all_vector_shared_state<value_type> factory_all_type; + typedef detail::future_when_any_vector_shared_state<value_type> factory_any_type; + }; +//#if ! defined(BOOST_NO_CXX11_HDR_TUPLE) + template< typename T0, typename ...T> + struct when_type_impl<false, T0, T...> + { + typedef csbl::tuple<BOOST_THREAD_FUTURE<typename T0::value_type>, BOOST_THREAD_FUTURE<typename T::value_type>... > container_type; + typedef detail::future_when_all_tuple_shared_state<T0, T...> factory_all_type; + typedef detail::future_when_any_tuple_shared_state<T0, T...> factory_any_type; + }; +//#endif + + template< typename T0, typename ...T> + struct when_type : when_type_impl<are_same<T0, T...>::value, T0, T...> {}; +#endif +} + + template< typename InputIterator> + typename boost::disable_if<is_future_type<InputIterator>, + BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> > + >::type + when_all(InputIterator first, InputIterator last) { + typedef typename InputIterator::value_type value_type; + typedef csbl::vector<value_type> container_type; + typedef detail::future_when_all_vector_shared_state<value_type> factory_type; + + if (first==last) return make_ready_future(container_type()); + shared_ptr<factory_type > + h(new factory_type>(detail::input_iterator_tag_value, first,last)); + return BOOST_THREAD_FUTURE<container_type>(h); + } + +//#if ! defined(BOOST_NO_CXX11_HDR_TUPLE) + inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_all() { + return make_ready_future(csbl::tuple<>()); + } +//#endif + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + BOOST_THREAD_FUTURE<typename detail::when_type<T0, T...>::container_type> + when_all(BOOST_THREAD_RV_REF(T0) f, BOOST_THREAD_RV_REF(T) ... futures) { + typedef typename detail::when_type<T0, T...>::container_type container_type; + typedef typename detail::when_type<T0, T...>::factory_all_type factory_type; + + shared_ptr<factory_type> + h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...)); + return BOOST_THREAD_FUTURE<container_type>(h); + } +#endif + + template< typename InputIterator> + typename boost::disable_if<is_future_type<InputIterator>, + BOOST_THREAD_FUTURE<csbl::vector<typename InputIterator::value_type> > + >::type + when_any(InputIterator first, InputIterator last) { + typedef typename InputIterator::value_type value_type; + typedef csbl::vector<value_type> container_type; + typedef detail::future_when_any_vector_shared_state<value_type> factory_type; + + if (first==last) return make_ready_future(container_type()); + shared_ptr<factory_type > + h(new factory_type>(detail::input_iterator_tag_value, first,last)); + return BOOST_THREAD_FUTURE<container_type>(h); + } + +//#if ! defined(BOOST_NO_CXX11_HDR_TUPLE) + inline BOOST_THREAD_FUTURE<csbl::tuple<> > when_any() { + return make_ready_future(csbl::tuple<>()); + } +//#endif + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + BOOST_THREAD_FUTURE<typename detail::when_type<T0, T...>::container_type> + when_any(BOOST_THREAD_RV_REF(T0) f, BOOST_THREAD_RV_REF(T) ... futures) { + typedef typename detail::when_type<T0, T...>::container_type container_type; + typedef typename detail::when_type<T0, T...>::factory_any_type factory_type; + + shared_ptr<factory_type> + h(new factory_type(detail::values_tag_value, boost::forward<T0>(f), boost::forward<T>(futures)...)); + return BOOST_THREAD_FUTURE<container_type>(h); + } +#endif +#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY } #endif // BOOST_NO_EXCEPTION diff --git a/3rdParty/Boost/src/boost/thread/future_error_code.hpp b/3rdParty/Boost/src/boost/thread/future_error_code.hpp new file mode 100644 index 0000000..6fe9554 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/future_error_code.hpp @@ -0,0 +1,61 @@ +// (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 +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_FUTURE_ERROR_CODE_HPP +#define BOOST_THREAD_FUTURE_ERROR_CODE_HPP + +#include <boost/thread/detail/config.hpp> +#include <boost/core/scoped_enum.hpp> +#include <boost/system/error_code.hpp> +#include <boost/type_traits/integral_constant.hpp> + +namespace boost +{ + + //enum class future_errc + BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc) + { + broken_promise = 1, + 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< ::boost::future_errc> : public true_type {}; + + #ifdef BOOST_NO_CXX11_SCOPED_ENUMS + template <> + struct BOOST_SYMBOL_VISIBLE is_error_code_enum< ::boost::future_errc::enum_type> : public true_type { }; + #endif + } // system + + 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), boost::future_category()); + } + } // system +} // boost + +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/is_locked_by_this_thread.hpp b/3rdParty/Boost/src/boost/thread/is_locked_by_this_thread.hpp new file mode 100644 index 0000000..6344c0f --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/is_locked_by_this_thread.hpp @@ -0,0 +1,39 @@ +// (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) + + +#ifndef BOOST_THREAD_IS_LOCKED_BY_THIS_THREAD_HPP +#define BOOST_THREAD_IS_LOCKED_BY_THIS_THREAD_HPP + +#include <boost/thread/detail/config.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + template <typename Lockable> + class testable_mutex; + + /** + * Overloaded function used to check if the mutex is locked when it is testable and do nothing otherwise. + * + * This function is used usually to assert the pre-condition when the function can only be called when the mutex + * must be locked by the current thread. + */ + template <typename Lockable> + bool is_locked_by_this_thread(testable_mutex<Lockable> const& mtx) + { + return mtx.is_locked_by_this_thread(); + } + template <typename Lockable> + bool is_locked_by_this_thread(Lockable const&) + { + return true; + } +} + +#include <boost/config/abi_suffix.hpp> + +#endif // header diff --git a/3rdParty/Boost/src/boost/thread/lock_algorithms.hpp b/3rdParty/Boost/src/boost/thread/lock_algorithms.hpp new file mode 100644 index 0000000..7a55f92 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/lock_algorithms.hpp @@ -0,0 +1,468 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCK_ALGORITHMS_HPP +#define BOOST_THREAD_LOCK_ALGORITHMS_HPP + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/lock_types.hpp> +#include <boost/thread/lockable_traits.hpp> + +#include <algorithm> +#include <iterator> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + namespace detail + { + template <typename MutexType1, typename MutexType2> + unsigned try_lock_internal(MutexType1& m1, MutexType2& m2) + { + boost::unique_lock<MutexType1> l1(m1, boost::try_to_lock); + if (!l1) + { + return 1; + } + if (!m2.try_lock()) + { + return 2; + } + l1.release(); + return 0; + } + + template <typename MutexType1, typename MutexType2, typename MutexType3> + unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3) + { + boost::unique_lock<MutexType1> l1(m1, boost::try_to_lock); + if (!l1) + { + return 1; + } + if (unsigned const failed_lock=try_lock_internal(m2,m3)) + { + return failed_lock + 1; + } + l1.release(); + return 0; + } + + template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4> + unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4) + { + boost::unique_lock<MutexType1> l1(m1, boost::try_to_lock); + if (!l1) + { + return 1; + } + if (unsigned const failed_lock=try_lock_internal(m2,m3,m4)) + { + return failed_lock + 1; + } + l1.release(); + return 0; + } + + template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5> + unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5) + { + boost::unique_lock<MutexType1> l1(m1, boost::try_to_lock); + if (!l1) + { + return 1; + } + if (unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5)) + { + return failed_lock + 1; + } + l1.release(); + return 0; + } + + template <typename MutexType1, typename MutexType2> + unsigned lock_helper(MutexType1& m1, MutexType2& m2) + { + boost::unique_lock<MutexType1> l1(m1); + if (!m2.try_lock()) + { + return 1; + } + l1.release(); + return 0; + } + + template <typename MutexType1, typename MutexType2, typename MutexType3> + unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3) + { + boost::unique_lock<MutexType1> l1(m1); + if (unsigned const failed_lock=try_lock_internal(m2,m3)) + { + return failed_lock; + } + l1.release(); + return 0; + } + + template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4> + unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4) + { + boost::unique_lock<MutexType1> l1(m1); + if (unsigned const failed_lock=try_lock_internal(m2,m3,m4)) + { + return failed_lock; + } + l1.release(); + return 0; + } + + template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5> + unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5) + { + boost::unique_lock<MutexType1> l1(m1); + if (unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5)) + { + return failed_lock; + } + l1.release(); + return 0; + } + } + + namespace detail + { + 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> ) + { + unsigned const lock_count = 2; + unsigned lock_first = 0; + for (;;) + { + switch (lock_first) + { + case 0: + lock_first = detail::lock_helper(m1, m2); + if (!lock_first) return; + break; + case 1: + lock_first = detail::lock_helper(m2, m1); + if (!lock_first) return; + lock_first = (lock_first + 1) % lock_count; + break; + } + } + } + + 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) + { + detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); + } + + template <typename MutexType1, typename MutexType2> + void lock(const MutexType1& m1, MutexType2& m2) + { + detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); + } + + template <typename MutexType1, typename MutexType2> + void lock(MutexType1& m1, const MutexType2& m2) + { + detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); + } + + template <typename MutexType1, typename MutexType2> + void lock(const MutexType1& m1, const MutexType2& m2) + { + detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); + } + + template <typename MutexType1, typename MutexType2, typename MutexType3> + void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3) + { + unsigned const lock_count = 3; + unsigned lock_first = 0; + for (;;) + { + switch (lock_first) + { + case 0: + lock_first = detail::lock_helper(m1, m2, m3); + if (!lock_first) return; + break; + case 1: + lock_first = detail::lock_helper(m2, m3, m1); + if (!lock_first) return; + lock_first = (lock_first + 1) % lock_count; + break; + case 2: + lock_first = detail::lock_helper(m3, m1, m2); + if (!lock_first) return; + lock_first = (lock_first + 2) % lock_count; + break; + } + } + } + + template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4> + void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4) + { + unsigned const lock_count = 4; + unsigned lock_first = 0; + for (;;) + { + switch (lock_first) + { + case 0: + lock_first = detail::lock_helper(m1, m2, m3, m4); + if (!lock_first) return; + break; + case 1: + lock_first = detail::lock_helper(m2, m3, m4, m1); + if (!lock_first) return; + lock_first = (lock_first + 1) % lock_count; + break; + case 2: + lock_first = detail::lock_helper(m3, m4, m1, m2); + if (!lock_first) return; + lock_first = (lock_first + 2) % lock_count; + break; + case 3: + lock_first = detail::lock_helper(m4, m1, m2, m3); + if (!lock_first) return; + lock_first = (lock_first + 3) % lock_count; + break; + } + } + } + + template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5> + void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5) + { + unsigned const lock_count = 5; + unsigned lock_first = 0; + for (;;) + { + switch (lock_first) + { + case 0: + lock_first = detail::lock_helper(m1, m2, m3, m4, m5); + if (!lock_first) return; + break; + case 1: + lock_first = detail::lock_helper(m2, m3, m4, m5, m1); + if (!lock_first) return; + lock_first = (lock_first + 1) % lock_count; + break; + case 2: + lock_first = detail::lock_helper(m3, m4, m5, m1, m2); + if (!lock_first) return; + lock_first = (lock_first + 2) % lock_count; + break; + case 3: + lock_first = detail::lock_helper(m4, m5, m1, m2, m3); + if (!lock_first) return; + lock_first = (lock_first + 3) % lock_count; + break; + case 4: + lock_first = detail::lock_helper(m5, m1, m2, m3, m4); + if (!lock_first) return; + lock_first = (lock_first + 4) % lock_count; + break; + } + } + } + + namespace detail + { + template <typename Mutex, bool x = is_mutex_type<Mutex>::value> + struct try_lock_impl_return + { + typedef int type; + }; + + template <typename Iterator> + struct try_lock_impl_return<Iterator, false> + { + typedef Iterator type; + }; + + template <typename MutexType1, typename MutexType2> + int try_lock_impl(MutexType1& m1, MutexType2& m2, is_mutex_type_wrapper<true> ) + { + return ((int) detail::try_lock_internal(m1, m2)) - 1; + } + + 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) + { + return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); + } + + template <typename MutexType1, typename MutexType2> + typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1, MutexType2& m2) + { + return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); + } + + template <typename MutexType1, typename MutexType2> + typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1, const MutexType2& m2) + { + return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); + } + + template <typename MutexType1, typename MutexType2> + typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1, const MutexType2& m2) + { + return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); + } + + template <typename MutexType1, typename MutexType2, typename MutexType3> + int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3) + { + return ((int) detail::try_lock_internal(m1, m2, m3)) - 1; + } + + template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4> + int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4) + { + return ((int) detail::try_lock_internal(m1, m2, m3, m4)) - 1; + } + + template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5> + int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5) + { + return ((int) detail::try_lock_internal(m1, m2, m3, m4, m5)) - 1; + } + + namespace detail + { + template <typename Iterator> + struct range_lock_guard + { + Iterator begin; + Iterator end; + + range_lock_guard(Iterator begin_, Iterator end_) : + begin(begin_), end(end_) + { + boost::lock(begin, end); + } + + void release() + { + begin = end; + } + + ~range_lock_guard() + { + for (; begin != end; ++begin) + { + begin->unlock(); + } + } + }; + + template <typename Iterator> + Iterator try_lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> ) + + { + if (begin == end) + { + return end; + } + 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 = boost::try_lock(++begin, end); + if (failed == end) + { + guard.release(); + } + + return failed; + } + } + + namespace detail + { + template <typename Iterator> + 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; + } + bool start_with_begin = true; + 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 = boost::try_lock(next, end); + if (failed_lock == end) + { + begin_lock.release(); + return; + } + start_with_begin = false; + next = failed_lock; + } + else + { + detail::range_lock_guard<Iterator> guard(next, end); + if (begin_lock.try_lock()) + { + Iterator const failed_lock = boost::try_lock(second, next); + if (failed_lock == next) + { + begin_lock.release(); + guard.release(); + return; + } + start_with_begin = false; + next = failed_lock; + } + else + { + start_with_begin = true; + next = second; + } + } + } + } + + } + +} +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/3rdParty/Boost/src/boost/thread/lock_guard.hpp b/3rdParty/Boost/src/boost/thread/lock_guard.hpp new file mode 100644 index 0000000..4c2908a --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/lock_guard.hpp @@ -0,0 +1,88 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCK_GUARD_HPP +#define BOOST_THREAD_LOCK_GUARD_HPP + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/detail/delete.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/detail/lockable_wrapper.hpp> +#include <boost/thread/lock_options.hpp> +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include <boost/thread/is_locked_by_this_thread.hpp> +#include <boost/assert.hpp> +#endif + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + + template <typename Mutex> + class lock_guard + { + private: + Mutex& m; + + public: + typedef Mutex mutex_type; + BOOST_THREAD_NO_COPYABLE( lock_guard ) + + explicit lock_guard(Mutex& m_) : + m(m_) + { + m.lock(); + } + + lock_guard(Mutex& m_, adopt_lock_t) : + m(m_) + { +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + BOOST_ASSERT(is_locked_by_this_thread(m)); +#endif + } + +#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST + lock_guard(std::initializer_list<thread_detail::lockable_wrapper<Mutex> > l_) : + m(*(const_cast<thread_detail::lockable_wrapper<Mutex>*>(l_.begin())->m)) + { + m.lock(); + } + + lock_guard(std::initializer_list<thread_detail::lockable_adopt_wrapper<Mutex> > l_) : + m(*(const_cast<thread_detail::lockable_adopt_wrapper<Mutex>*>(l_.begin())->m)) + { +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + BOOST_ASSERT(is_locked_by_this_thread(m)); +#endif + } + +#endif + ~lock_guard() + { + m.unlock(); + } + }; + + +#if ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD + template <typename Lockable> + lock_guard<Lockable> make_lock_guard(Lockable& mtx) + { + return { thread_detail::lockable_wrapper<Lockable>(mtx) }; + } + template <typename Lockable> + lock_guard<Lockable> make_lock_guard(Lockable& mtx, adopt_lock_t) + { + return { thread_detail::lockable_adopt_wrapper<Lockable>(mtx) }; + } +#endif +} + +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/3rdParty/Boost/src/boost/thread/lock_options.hpp b/3rdParty/Boost/src/boost/thread/lock_options.hpp new file mode 100644 index 0000000..68899ca --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/lock_options.hpp @@ -0,0 +1,31 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCK_OPTIONS_HPP +#define BOOST_THREAD_LOCK_OPTIONS_HPP + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + struct defer_lock_t + { + }; + struct try_to_lock_t + { + }; + struct adopt_lock_t + { + }; + + 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 = {}; + +} +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/3rdParty/Boost/src/boost/thread/lock_types.hpp b/3rdParty/Boost/src/boost/thread/lock_types.hpp new file mode 100644 index 0000000..2b73edf --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/lock_types.hpp @@ -0,0 +1,1230 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCK_TYPES_HPP +#define BOOST_THREAD_LOCK_TYPES_HPP + +#include <boost/thread/detail/config.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/exceptions.hpp> +#include <boost/thread/lock_options.hpp> +#include <boost/thread/lockable_traits.hpp> +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include <boost/thread/is_locked_by_this_thread.hpp> +#endif +#include <boost/thread/thread_time.hpp> + +#include <boost/assert.hpp> +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/time_point.hpp> +#include <boost/chrono/duration.hpp> +#endif +#include <boost/detail/workaround.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + struct xtime; + + template <typename Mutex> + class shared_lock; + + template <typename Mutex> + class upgrade_lock; + + template <typename Mutex> + class unique_lock; + + namespace detail + { + template <typename Mutex> + class try_lock_wrapper; + } + +#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + namespace sync + { + template<typename T> + struct is_basic_lockable<unique_lock<T> > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<typename T> + struct is_lockable<unique_lock<T> > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + template<typename T> + struct is_basic_lockable<shared_lock<T> > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<typename T> + struct is_lockable<shared_lock<T> > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + template<typename T> + struct is_basic_lockable<upgrade_lock<T> > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<typename T> + struct is_lockable<upgrade_lock<T> > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + template<typename T> + struct is_basic_lockable<detail::try_lock_wrapper<T> > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<typename T> + struct is_lockable<detail::try_lock_wrapper<T> > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + } +#endif + + + template <typename Mutex> + class unique_lock + { + private: + Mutex* m; + bool is_locked; + + private: + explicit unique_lock(upgrade_lock<Mutex>&); + unique_lock& operator=(upgrade_lock<Mutex>& other); + public: + 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 +#endif + unique_lock()BOOST_NOEXCEPT : + m(0),is_locked(false) + {} + + explicit unique_lock(Mutex& m_) : + m(&m_), is_locked(false) + { + lock(); + } + unique_lock(Mutex& m_, adopt_lock_t) : + m(&m_), is_locked(true) + { +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + BOOST_ASSERT(is_locked_by_this_thread(m)); +#endif + } + unique_lock(Mutex& m_, defer_lock_t)BOOST_NOEXCEPT: + m(&m_),is_locked(false) + {} + unique_lock(Mutex& m_, try_to_lock_t) : + m(&m_), is_locked(false) + { + try_lock(); + } +#if defined BOOST_THREAD_USES_DATETIME + template<typename TimeDuration> + unique_lock(Mutex& m_,TimeDuration const& target_time): + m(&m_),is_locked(false) + { + timed_lock(target_time); + } + unique_lock(Mutex& m_,system_time const& target_time): + m(&m_),is_locked(false) + { + timed_lock(target_time); + } +#endif +#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)) + { + } + template <class Rep, class Period> + unique_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d) + : m(&mtx), is_locked(mtx.try_lock_for(d)) + { + } +#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); + +#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION + //std-2104 unique_lock move-assignment should not be noexcept + unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT + { + unique_lock temp(::boost::move(other)); + swap(temp); + return *this; + } +#endif + + //std-2104 unique_lock move-assignment should not be noexcept + unique_lock& operator=(BOOST_THREAD_RV_REF(unique_lock) other) //BOOST_NOEXCEPT + { + unique_lock temp(::boost::move(other)); + swap(temp); + return *this; + } +#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) + { + swap(other); + return *this; + } +#endif // BOOST_WORKAROUND +#endif + + // 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) + { + 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(); + } + } + +#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) + { + 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(); + } + } + + 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) + { + 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 + +#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) + { + 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(); + } + } + + 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) + { + 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 // 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()) + { + m->unlock(); + } + } + void lock() + { + if (m == 0) + { + boost::throw_exception( + boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if (owns_lock()) + { + boost::throw_exception( + boost::lock_error(static_cast<int>(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(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if (owns_lock()) + { + boost::throw_exception( + boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex")); + } + is_locked = m->try_lock(); + return is_locked; + } +#if defined BOOST_THREAD_USES_DATETIME + template<typename TimeDuration> + bool timed_lock(TimeDuration const& relative_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(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(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(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(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex")); + } + is_locked=m->timed_lock(absolute_time); + return is_locked; + } +#endif +#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(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(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(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(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(static_cast<int>(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if (!owns_lock()) + { + boost::throw_exception( + boost::lock_error(static_cast<int>(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 BOOST_NOEXCEPT + { + return is_locked?&unique_lock::lock:0; + } + bool operator!() const BOOST_NOEXCEPT + { + return !owns_lock(); + } +#else + explicit operator bool() const BOOST_NOEXCEPT + { + return owns_lock(); + } +#endif + bool owns_lock() const BOOST_NOEXCEPT + { + return is_locked; + } + + Mutex* mutex() const BOOST_NOEXCEPT + { + return m; + } + + Mutex* release()BOOST_NOEXCEPT + { + Mutex* const res=m; + m=0; + is_locked=false; + return res; + } + + friend class shared_lock<Mutex> ; + friend class upgrade_lock<Mutex> ; + }; + + template<typename Mutex> + void swap(unique_lock<Mutex>& lhs, unique_lock<Mutex>& rhs) + BOOST_NOEXCEPT + { + lhs.swap(rhs); + } + + BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END + + template<typename Mutex> + class shared_lock + { + protected: + Mutex* m; + bool is_locked; + + public: + 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) + { + lock(); + } + shared_lock(Mutex& m_,adopt_lock_t): + m(&m_),is_locked(true) + { +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + BOOST_ASSERT(is_locked_by_this_thread(m)); +#endif + } + shared_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT: + m(&m_),is_locked(false) + {} + shared_lock(Mutex& m_,try_to_lock_t): + m(&m_),is_locked(false) + { + try_lock(); + } +#if defined BOOST_THREAD_USES_DATETIME + shared_lock(Mutex& m_,system_time const& target_time): + m(&m_),is_locked(false) + { + timed_lock(target_time); + } +#endif +#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) + { + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; + } + + 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(); + } + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; + } + + 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(); + } + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; + } + + //std-2104 unique_lock move-assignment should not be noexcept + shared_lock& operator=(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT + { + shared_lock temp(::boost::move(other)); + swap(temp); + return *this; + } +#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(::boost::move(other)); + swap(temp); + return *this; + } + + shared_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) + { + shared_lock temp(::boost::move(other)); + swap(temp); + return *this; + } +#endif + + void swap(shared_lock& other) BOOST_NOEXCEPT + { + std::swap(m,other.m); + std::swap(is_locked,other.is_locked); + } + + Mutex* mutex() const BOOST_NOEXCEPT + { + return m; + } + + Mutex* release() BOOST_NOEXCEPT + { + Mutex* const res=m; + m=0; + is_locked=false; + return res; + } + + ~shared_lock() + { + if(owns_lock()) + { + m->unlock_shared(); + } + } + void lock() + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(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(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex")); + } + is_locked=m->try_lock_shared(); + return is_locked; + } +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(boost::system_time const& target_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex")); + } + is_locked=m->timed_lock_shared(target_time); + return is_locked; + } + template<typename Duration> + bool timed_lock(Duration const& target_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex")); + } + is_locked=m->timed_lock_shared(target_time); + return is_locked; + } +#endif +#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(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(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(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(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(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(!owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(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 BOOST_NOEXCEPT + { + return is_locked?&shared_lock::lock:0; + } + bool operator!() const BOOST_NOEXCEPT + { + return !owns_lock(); + } +#else + explicit operator bool() const BOOST_NOEXCEPT + { + return owns_lock(); + } +#endif + bool owns_lock() const BOOST_NOEXCEPT + { + return is_locked; + } + + }; + + 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) BOOST_NOEXCEPT + { + lhs.swap(rhs); + } + + template <typename Mutex> + class upgrade_lock + { + protected: + Mutex* m; + bool is_locked; + + public: + 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) + { + lock(); + } + upgrade_lock(Mutex& m_, adopt_lock_t) : + m(&m_), is_locked(true) + { +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + BOOST_ASSERT(is_locked_by_this_thread(m)); +#endif + } + upgrade_lock(Mutex& m_, defer_lock_t)BOOST_NOEXCEPT: + m(&m_),is_locked(false) + {} + upgrade_lock(Mutex& m_, try_to_lock_t) : + m(&m_), is_locked(false) + { + try_lock(); + } + +#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) + { + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; + } + + 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(); + } + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; + } + + //std-2104 unique_lock move-assignment should not be noexcept + upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT + { + upgrade_lock temp(::boost::move(other)); + swap(temp); + return *this; + } + +#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(::boost::move(other)); + swap(temp); + return *this; + } +#endif + +#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 (BOOST_THREAD_RV(sl).owns_lock()) + { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade()) + { + 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> + 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) + { + 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(); + } + } + + 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) + { + 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 + void swap(upgrade_lock& other)BOOST_NOEXCEPT + { + std::swap(m,other.m); + std::swap(is_locked,other.is_locked); + } + Mutex* mutex() const BOOST_NOEXCEPT + { + return m; + } + + Mutex* release()BOOST_NOEXCEPT + { + Mutex* const res=m; + m=0; + is_locked=false; + return res; + } + ~upgrade_lock() + { + if (owns_lock()) + { + m->unlock_upgrade(); + } + } + void lock() + { + if (m == 0) + { + boost::throw_exception( + boost::lock_error(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if (owns_lock()) + { + boost::throw_exception( + boost::lock_error(static_cast<int>(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(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if (owns_lock()) + { + boost::throw_exception( + boost::lock_error(static_cast<int>(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(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if (!owns_lock()) + { + boost::throw_exception( + boost::lock_error(static_cast<int>(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(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(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(static_cast<int>(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast<int>(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 BOOST_NOEXCEPT + { + return is_locked?&upgrade_lock::lock:0; + } + bool operator!() const BOOST_NOEXCEPT + { + return !owns_lock(); + } +#else + explicit operator bool() const BOOST_NOEXCEPT + { + return owns_lock(); + } +#endif + bool owns_lock() const BOOST_NOEXCEPT + { + return is_locked; + } + friend class shared_lock<Mutex> ; + friend class unique_lock<Mutex> ; + }; + + template<typename Mutex> + void swap(upgrade_lock<Mutex>& lhs, upgrade_lock<Mutex>& rhs) + BOOST_NOEXCEPT + { + lhs.swap(rhs); + } + + BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END + + template<typename Mutex> + 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) + { + if(is_locked) + { + m->unlock_upgrade_and_lock(); + } + BOOST_THREAD_RV(other).release(); + } + + template <class Mutex> + class upgrade_to_unique_lock + { + private: + upgrade_lock<Mutex>* source; + unique_lock<Mutex> exclusive; + + 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(::boost::move(*source)) + { + } + ~upgrade_to_unique_lock() + { + if (source) + { + *source = BOOST_THREAD_MAKE_RV_REF(upgrade_lock<Mutex> (::boost::move(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)) + { + BOOST_THREAD_RV(other).source=0; + } + + //std-2104 unique_lock move-assignment should not be noexcept + 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; + } + + 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 BOOST_NOEXCEPT + { + return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0; + } + bool operator!() const BOOST_NOEXCEPT + { + return !owns_lock(); + } +#else + explicit operator bool() const BOOST_NOEXCEPT + { + return owns_lock(); + } +#endif + + bool owns_lock() const BOOST_NOEXCEPT + { + return exclusive.owns_lock(); + } + Mutex* mutex() const BOOST_NOEXCEPT + { + return exclusive.mutex(); + } + }; + +BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_to_unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END + +namespace detail +{ + template<typename Mutex> + class try_lock_wrapper: +private unique_lock<Mutex> + { + 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) + {} + + try_lock_wrapper(Mutex& m_,adopt_lock_t): + base(m_,adopt_lock) + { +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + BOOST_ASSERT(is_locked_by_this_thread(m_)); +#endif + } + try_lock_wrapper(Mutex& m_,defer_lock_t): + base(m_,defer_lock) + {} + try_lock_wrapper(Mutex& m_,try_to_lock_t): + base(m_,try_to_lock) + {} +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other): + base(::boost::move(other)) + {} + +#elif defined BOOST_THREAD_USES_MOVE + try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other): + base(::boost::move(static_cast<base&>(other))) + {} + +#else + try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other): + base(BOOST_THREAD_RV_REF(base)(*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(try_lock_wrapper& other) + { + base::swap(other); + } + void lock() + { + base::lock(); + } + bool try_lock() + { + return base::try_lock(); + } + void unlock() + { + base::unlock(); + } + bool owns_lock() const + { + return base::owns_lock(); + } + Mutex* mutex() const BOOST_NOEXCEPT + { + return base::mutex(); + } + Mutex* release() + { + return base::release(); + } + +#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 + }; + + template<typename Mutex> + void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs) + { + lhs.swap(rhs); + } +} +} +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/3rdParty/Boost/src/boost/thread/lockable_traits.hpp b/3rdParty/Boost/src/boost/thread/lockable_traits.hpp new file mode 100644 index 0000000..8a17ae7 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/lockable_traits.hpp @@ -0,0 +1,207 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCKABLE_TRAITS_HPP +#define BOOST_THREAD_LOCKABLE_TRAITS_HPP + +#include <boost/thread/detail/config.hpp> + +#include <boost/assert.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/type_traits/is_class.hpp> + +#include <boost/config/abi_prefix.hpp> + +// todo make use of integral_constant, true_type and false_type + +namespace boost +{ + namespace sync + { + +#if defined(BOOST_NO_SFINAE) || \ + BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \ + BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) +#if ! defined BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES +#define BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES +#endif +#endif + +#ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + namespace detail + { +#define BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(member_name) \ + template<typename T, bool=boost::is_class<T>::value> \ + struct has_member_called_##member_name \ + { \ + BOOST_STATIC_CONSTANT(bool, value=false); \ + }; \ + \ + template<typename T> \ + struct has_member_called_##member_name<T,true> \ + { \ + typedef char true_type; \ + struct false_type \ + { \ + true_type dummy[2]; \ + }; \ + \ + struct fallback { int member_name; }; \ + struct derived: \ + T, fallback \ + { \ + derived(); \ + }; \ + \ + template<int fallback::*> struct tester; \ + \ + template<typename U> \ + static false_type has_member(tester<&U::member_name>*); \ + template<typename U> \ + static true_type has_member(...); \ + \ + BOOST_STATIC_CONSTANT( \ + bool, value=sizeof(has_member<derived>(0))==sizeof(true_type)); \ + } + + BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(lock) +; BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(unlock); + BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(try_lock); + + template<typename T,bool=has_member_called_lock<T>::value > + struct has_member_lock + { + BOOST_STATIC_CONSTANT(bool, value=false); + }; + + template<typename T> + struct has_member_lock<T,true> + { + typedef char true_type; + struct false_type + { + 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> + { + typedef char true_type; + struct false_type + { + 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> + { + typedef char true_type; + struct false_type + { + 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_basic_lockable + { + BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value && + detail::has_member_unlock<T>::value); + }; + template<typename T> + struct is_lockable + { + BOOST_STATIC_CONSTANT(bool, value = + is_basic_lockable<T>::value && + detail::has_member_try_lock<T>::value); + }; + +#else + template<typename T> + struct is_basic_lockable + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + template<typename T> + struct is_lockable + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; +#endif + + template<typename T> + struct is_recursive_mutex_sur_parole + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + template<typename T> + struct is_recursive_mutex_sur_parolle : is_recursive_mutex_sur_parole<T> + { + }; + + template<typename T> + struct is_recursive_basic_lockable + { + BOOST_STATIC_CONSTANT(bool, value = is_basic_lockable<T>::value && + is_recursive_mutex_sur_parolle<T>::value); + }; + template<typename T> + struct is_recursive_lockable + { + BOOST_STATIC_CONSTANT(bool, value = is_lockable<T>::value && + is_recursive_mutex_sur_parolle<T>::value); + }; + } + template<typename T> + struct is_mutex_type + { + BOOST_STATIC_CONSTANT(bool, value = sync::is_lockable<T>::value); + }; + +} +#include <boost/config/abi_suffix.hpp> + +#endif diff --git a/3rdParty/Boost/src/boost/thread/locks.hpp b/3rdParty/Boost/src/boost/thread/locks.hpp index c11c2bd..6749964 100644 --- a/3rdParty/Boost/src/boost/thread/locks.hpp +++ b/3rdParty/Boost/src/boost/thread/locks.hpp @@ -6,1822 +6,11 @@ #ifndef BOOST_THREAD_LOCKS_HPP #define BOOST_THREAD_LOCKS_HPP -#include <boost/thread/detail/config.hpp> -#include <boost/thread/exceptions.hpp> -#include <boost/thread/detail/move.hpp> -#include <algorithm> -#include <iterator> -#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> - -namespace boost -{ - struct xtime; - -#if defined(BOOST_NO_SFINAE) || \ - BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \ - BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) -#define BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES -#endif - -#ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES - namespace detail - { -#define BOOST_DEFINE_HAS_MEMBER_CALLED(member_name) \ - template<typename T, bool=boost::is_class<T>::value> \ - struct has_member_called_##member_name \ - { \ - BOOST_STATIC_CONSTANT(bool, value=false); \ - }; \ - \ - template<typename T> \ - struct has_member_called_##member_name<T,true> \ - { \ - typedef char true_type; \ - struct false_type \ - { \ - true_type dummy[2]; \ - }; \ - \ - struct fallback { int member_name; }; \ - struct derived: \ - T, fallback \ - { \ - derived(); \ - }; \ - \ - template<int fallback::*> struct tester; \ - \ - template<typename U> \ - static false_type has_member(tester<&U::member_name>*); \ - template<typename U> \ - static true_type has_member(...); \ - \ - BOOST_STATIC_CONSTANT( \ - bool, value=sizeof(has_member<derived>(0))==sizeof(true_type)); \ - } - - BOOST_DEFINE_HAS_MEMBER_CALLED(lock); - BOOST_DEFINE_HAS_MEMBER_CALLED(unlock); - BOOST_DEFINE_HAS_MEMBER_CALLED(try_lock); - - template<typename T,bool=has_member_called_lock<T>::value > - struct has_member_lock - { - BOOST_STATIC_CONSTANT(bool, value=false); - }; - - template<typename T> - struct has_member_lock<T,true> - { - typedef char true_type; - struct false_type - { - 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> - { - typedef char true_type; - struct false_type - { - 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> - { - typedef char true_type; - struct false_type - { - 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 - { - 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> - struct is_mutex_type - { - BOOST_STATIC_CONSTANT(bool, value = false); - }; -#endif - - struct defer_lock_t - {}; - struct try_to_lock_t - {}; - struct adopt_lock_t - {}; - - 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; - - template<typename Mutex> - class upgrade_lock; - - template<typename Mutex> - class unique_lock; - - namespace detail - { - 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> > - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - - template<typename T> - struct is_mutex_type<shared_lock<T> > - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - - template<typename T> - struct is_mutex_type<upgrade_lock<T> > - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - - template<typename T> - struct is_mutex_type<detail::try_lock_wrapper<T> > - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - - class mutex; - class timed_mutex; - class recursive_mutex; - class recursive_timed_mutex; - class shared_mutex; - - template<> - struct is_mutex_type<mutex> - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - template<> - struct is_mutex_type<timed_mutex> - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - template<> - struct is_mutex_type<recursive_mutex> - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - template<> - struct is_mutex_type<recursive_timed_mutex> - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - template<> - struct is_mutex_type<shared_mutex> - { - BOOST_STATIC_CONSTANT(bool, value = true); - }; - -#endif - - template<typename Mutex> - class lock_guard - { - private: - Mutex& m; - - public: - typedef Mutex mutex_type; - BOOST_THREAD_NO_COPYABLE(lock_guard) - - explicit lock_guard(Mutex& m_): - m(m_) - { - m.lock(); - } - lock_guard(Mutex& m_,adopt_lock_t): - m(m_) - {} - ~lock_guard() - { - m.unlock(); - } - }; - - template<typename Mutex> - class unique_lock - { - private: - Mutex* m; - bool is_locked; - - private: - explicit unique_lock(upgrade_lock<Mutex>&); - unique_lock& operator=(upgrade_lock<Mutex>& other); - public: - 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 -#endif - unique_lock() BOOST_NOEXCEPT : - m(0),is_locked(false) - {} - - explicit unique_lock(Mutex& m_): - m(&m_),is_locked(false) - { - lock(); - } - unique_lock(Mutex& m_,adopt_lock_t): - m(&m_),is_locked(true) - {} - unique_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT: - m(&m_),is_locked(false) - {} - unique_lock(Mutex& m_,try_to_lock_t): - m(&m_),is_locked(false) - { - try_lock(); - } - template<typename TimeDuration> - unique_lock(Mutex& m_,TimeDuration const& target_time): - m(&m_),is_locked(false) - { - timed_lock(target_time); - } - unique_lock(Mutex& m_,system_time const& target_time): - m(&m_),is_locked(false) - { - timed_lock(target_time); - } - -#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)) - { - } - template <class Rep, class Period> - unique_lock(Mutex& mtx, const chrono::duration<Rep, Period>& d) - : m(&mtx), is_locked(mtx.try_lock_for(d)) - { - } -#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); - -#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(::boost::move(other)); - swap(temp); - return *this; - } -#endif - - unique_lock& operator=(BOOST_THREAD_RV_REF(unique_lock) other) BOOST_NOEXCEPT - { - unique_lock temp(::boost::move(other)); - swap(temp); - return *this; - } -#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) - { - swap(other); - return *this; - } -#endif // BOOST_WORKAROUND -#endif - - // 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) - { - 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(); - } - } - -#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) - { - 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(); - } - } - - 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) - { - 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 - -#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) - { - 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(); - } - } - - 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) - { - 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 // 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()) - { - m->unlock(); - } - } - 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(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(system::errc::resource_deadlock_would_occur, "boost unique_lock owns already the mutex")); - } - is_locked=m->try_lock(); - return is_locked; - } - 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(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 BOOST_NOEXCEPT - { - return is_locked?&unique_lock::lock:0; - } - bool operator!() const BOOST_NOEXCEPT - { - return !owns_lock(); - } -#else - explicit operator bool() const BOOST_NOEXCEPT - { - return owns_lock(); - } -#endif - bool owns_lock() const BOOST_NOEXCEPT - { - return is_locked; - } - - Mutex* mutex() const BOOST_NOEXCEPT - { - return m; - } - - Mutex* release() BOOST_NOEXCEPT - { - Mutex* const res=m; - m=0; - is_locked=false; - return res; - } - - friend class shared_lock<Mutex>; - friend class upgrade_lock<Mutex>; - }; - - template<typename Mutex> - void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs) BOOST_NOEXCEPT - { - lhs.swap(rhs); - } - - BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) unique_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END - - template<typename Mutex> - class shared_lock - { - protected: - Mutex* m; - bool is_locked; - - public: - 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) - { - lock(); - } - shared_lock(Mutex& m_,adopt_lock_t): - m(&m_),is_locked(true) - {} - shared_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT: - m(&m_),is_locked(false) - {} - shared_lock(Mutex& m_,try_to_lock_t): - m(&m_),is_locked(false) - { - try_lock(); - } - shared_lock(Mutex& m_,system_time const& target_time): - m(&m_),is_locked(false) - { - timed_lock(target_time); - } - -#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) - { - BOOST_THREAD_RV(other).is_locked=false; - BOOST_THREAD_RV(other).m=0; - } - - 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(); - } - BOOST_THREAD_RV(other).is_locked=false; - BOOST_THREAD_RV(other).m=0; - } - - 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(); - } - BOOST_THREAD_RV(other).is_locked=false; - BOOST_THREAD_RV(other).m=0; - } - - - shared_lock& operator=(BOOST_THREAD_RV_REF_BEG shared_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT - { - shared_lock temp(::boost::move(other)); - swap(temp); - return *this; - } -#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(::boost::move(other)); - swap(temp); - return *this; - } - - shared_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) - { - shared_lock temp(::boost::move(other)); - swap(temp); - return *this; - } -#endif - - void swap(shared_lock& other) BOOST_NOEXCEPT - { - std::swap(m,other.m); - std::swap(is_locked,other.is_locked); - } - - Mutex* mutex() const BOOST_NOEXCEPT - { - return m; - } - - Mutex* release() BOOST_NOEXCEPT - { - Mutex* const res=m; - m=0; - is_locked=false; - return res; - } - - ~shared_lock() - { - if(owns_lock()) - { - m->unlock_shared(); - } - } - 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(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(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(system::errc::resource_deadlock_would_occur, "boost shared_lock owns already the mutex")); - } - is_locked=m->timed_lock_shared(target_time); - return is_locked; - } - 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(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(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 BOOST_NOEXCEPT - { - return is_locked?&shared_lock::lock:0; - } - bool operator!() const BOOST_NOEXCEPT - { - return !owns_lock(); - } -#else - explicit operator bool() const BOOST_NOEXCEPT - { - return owns_lock(); - } -#endif - bool owns_lock() const BOOST_NOEXCEPT - { - return is_locked; - } - - }; - - 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) BOOST_NOEXCEPT - { - lhs.swap(rhs); - } - - template<typename Mutex> - class upgrade_lock - { - protected: - Mutex* m; - bool is_locked; - - public: - 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) - { - lock(); - } - upgrade_lock(Mutex& m_,adopt_lock_t): - m(&m_),is_locked(true) - {} - upgrade_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT: - m(&m_),is_locked(false) - {} - upgrade_lock(Mutex& m_,try_to_lock_t): - m(&m_),is_locked(false) - { - try_lock(); - } - -#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) - { - BOOST_THREAD_RV(other).is_locked=false; - BOOST_THREAD_RV(other).m=0; - } - - 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(); - } - BOOST_THREAD_RV(other).is_locked=false; - BOOST_THREAD_RV(other).m=0; - } - - upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock<Mutex> BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT - { - upgrade_lock temp(::boost::move(other)); - swap(temp); - return *this; - } - -#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(::boost::move(other)); - swap(temp); - return *this; - } -#endif - -#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 (BOOST_THREAD_RV(sl).owns_lock()) { - if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade()) - { - 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> - 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) - { - 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(); - } - } - - 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) - { - 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 - - void swap(upgrade_lock& other) BOOST_NOEXCEPT - { - std::swap(m,other.m); - std::swap(is_locked,other.is_locked); - } - Mutex* mutex() const BOOST_NOEXCEPT - { - return m; - } - - Mutex* release() BOOST_NOEXCEPT - { - Mutex* const res=m; - m=0; - is_locked=false; - return res; - } - ~upgrade_lock() - { - if(owns_lock()) - { - m->unlock_upgrade(); - } - } - 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(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(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(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 BOOST_NOEXCEPT - { - return is_locked?&upgrade_lock::lock:0; - } - bool operator!() const BOOST_NOEXCEPT - { - return !owns_lock(); - } -#else - explicit operator bool() const BOOST_NOEXCEPT - { - return owns_lock(); - } -#endif - bool owns_lock() const BOOST_NOEXCEPT - { - return is_locked; - } - friend class shared_lock<Mutex>; - friend class unique_lock<Mutex>; - }; - - template<typename Mutex> - void swap(upgrade_lock<Mutex>& lhs,upgrade_lock<Mutex>& rhs) BOOST_NOEXCEPT - { - lhs.swap(rhs); - } - - BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_lock<Mutex> BOOST_THREAD_DCL_MOVABLE_END - - template<typename Mutex> - 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) - { - if(is_locked) - { - m->unlock_upgrade_and_lock(); - } - BOOST_THREAD_RV(other).release(); - } - - template <class Mutex> - class upgrade_to_unique_lock - { - private: - upgrade_lock<Mutex>* source; - unique_lock<Mutex> exclusive; - - 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(::boost::move(*source)) - {} - ~upgrade_to_unique_lock() - { - if(source) - { - *source=BOOST_THREAD_MAKE_RV_REF(upgrade_lock<Mutex>(::boost::move(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)) - { - BOOST_THREAD_RV(other).source=0; - } - - 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; - } - - 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 BOOST_NOEXCEPT - { - return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0; - } - bool operator!() const BOOST_NOEXCEPT - { - return !owns_lock(); - } -#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> - class try_lock_wrapper: - private unique_lock<Mutex> - { - 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) - {} - - try_lock_wrapper(Mutex& m_,adopt_lock_t): - base(m_,adopt_lock) - {} - try_lock_wrapper(Mutex& m_,defer_lock_t): - base(m_,defer_lock) - {} - try_lock_wrapper(Mutex& m_,try_to_lock_t): - base(m_,try_to_lock) - {} -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other): - base(::boost::move(other)) - {} - -#elif defined BOOST_THREAD_USES_MOVE - try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other): - base(::boost::move(static_cast<base&>(other))) - {} - -#else - try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other): - base(BOOST_THREAD_RV_REF(base)(*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(try_lock_wrapper& other) - { - base::swap(other); - } - void lock() - { - base::lock(); - } - bool try_lock() - { - return base::try_lock(); - } - void unlock() - { - base::unlock(); - } - bool owns_lock() const - { - return base::owns_lock(); - } - Mutex* mutex() const - { - return base::mutex(); - } - Mutex* release() - { - return base::release(); - } - -#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 - }; - - template<typename Mutex> - void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs) - { - lhs.swap(rhs); - } - - template<typename MutexType1,typename MutexType2> - unsigned try_lock_internal(MutexType1& m1,MutexType2& m2) - { - boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock); - if(!l1) - { - return 1; - } - if(!m2.try_lock()) - { - return 2; - } - l1.release(); - return 0; - } - - template<typename MutexType1,typename MutexType2,typename MutexType3> - unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3) - { - boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock); - if(!l1) - { - return 1; - } - if(unsigned const failed_lock=try_lock_internal(m2,m3)) - { - return failed_lock+1; - } - l1.release(); - return 0; - } - - - template<typename MutexType1,typename MutexType2,typename MutexType3, - typename MutexType4> - unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3, - MutexType4& m4) - { - boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock); - if(!l1) - { - return 1; - } - if(unsigned const failed_lock=try_lock_internal(m2,m3,m4)) - { - return failed_lock+1; - } - l1.release(); - return 0; - } - - template<typename MutexType1,typename MutexType2,typename MutexType3, - typename MutexType4,typename MutexType5> - unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3, - MutexType4& m4,MutexType5& m5) - { - boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock); - if(!l1) - { - return 1; - } - if(unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5)) - { - return failed_lock+1; - } - l1.release(); - return 0; - } - - - template<typename MutexType1,typename MutexType2> - unsigned lock_helper(MutexType1& m1,MutexType2& m2) - { - boost::unique_lock<MutexType1> l1(m1); - if(!m2.try_lock()) - { - return 1; - } - l1.release(); - return 0; - } - - template<typename MutexType1,typename MutexType2,typename MutexType3> - unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3) - { - boost::unique_lock<MutexType1> l1(m1); - if(unsigned const failed_lock=try_lock_internal(m2,m3)) - { - return failed_lock; - } - l1.release(); - return 0; - } - - template<typename MutexType1,typename MutexType2,typename MutexType3, - typename MutexType4> - unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3, - MutexType4& m4) - { - boost::unique_lock<MutexType1> l1(m1); - if(unsigned const failed_lock=try_lock_internal(m2,m3,m4)) - { - return failed_lock; - } - l1.release(); - return 0; - } - - template<typename MutexType1,typename MutexType2,typename MutexType3, - typename MutexType4,typename MutexType5> - unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3, - MutexType4& m4,MutexType5& m5) - { - boost::unique_lock<MutexType1> l1(m1); - if(unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5)) - { - return failed_lock; - } - l1.release(); - return 0; - } - } - - namespace detail - { - 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>) - { - unsigned const lock_count=2; - unsigned lock_first=0; - for(;;) - { - switch(lock_first) - { - case 0: - lock_first=detail::lock_helper(m1,m2); - if(!lock_first) - return; - break; - case 1: - lock_first=detail::lock_helper(m2,m1); - if(!lock_first) - return; - lock_first=(lock_first+1)%lock_count; - break; - } - } - } - - 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) - { - detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); - } - - template<typename MutexType1,typename MutexType2> - void lock(const MutexType1& m1,MutexType2& m2) - { - detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); - } - - template<typename MutexType1,typename MutexType2> - void lock(MutexType1& m1,const MutexType2& m2) - { - detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); - } - - template<typename MutexType1,typename MutexType2> - void lock(const MutexType1& m1,const MutexType2& m2) - { - detail::lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); - } - - template<typename MutexType1,typename MutexType2,typename MutexType3> - void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3) - { - unsigned const lock_count=3; - unsigned lock_first=0; - for(;;) - { - switch(lock_first) - { - case 0: - lock_first=detail::lock_helper(m1,m2,m3); - if(!lock_first) - return; - break; - case 1: - lock_first=detail::lock_helper(m2,m3,m1); - if(!lock_first) - return; - lock_first=(lock_first+1)%lock_count; - break; - case 2: - lock_first=detail::lock_helper(m3,m1,m2); - if(!lock_first) - return; - lock_first=(lock_first+2)%lock_count; - break; - } - } - } - - template<typename MutexType1,typename MutexType2,typename MutexType3, - typename MutexType4> - void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3, - MutexType4& m4) - { - unsigned const lock_count=4; - unsigned lock_first=0; - for(;;) - { - switch(lock_first) - { - case 0: - lock_first=detail::lock_helper(m1,m2,m3,m4); - if(!lock_first) - return; - break; - case 1: - lock_first=detail::lock_helper(m2,m3,m4,m1); - if(!lock_first) - return; - lock_first=(lock_first+1)%lock_count; - break; - case 2: - lock_first=detail::lock_helper(m3,m4,m1,m2); - if(!lock_first) - return; - lock_first=(lock_first+2)%lock_count; - break; - case 3: - lock_first=detail::lock_helper(m4,m1,m2,m3); - if(!lock_first) - return; - lock_first=(lock_first+3)%lock_count; - break; - } - } - } - - template<typename MutexType1,typename MutexType2,typename MutexType3, - typename MutexType4,typename MutexType5> - void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3, - MutexType4& m4,MutexType5& m5) - { - unsigned const lock_count=5; - unsigned lock_first=0; - for(;;) - { - switch(lock_first) - { - case 0: - lock_first=detail::lock_helper(m1,m2,m3,m4,m5); - if(!lock_first) - return; - break; - case 1: - lock_first=detail::lock_helper(m2,m3,m4,m5,m1); - if(!lock_first) - return; - lock_first=(lock_first+1)%lock_count; - break; - case 2: - lock_first=detail::lock_helper(m3,m4,m5,m1,m2); - if(!lock_first) - return; - lock_first=(lock_first+2)%lock_count; - break; - case 3: - lock_first=detail::lock_helper(m4,m5,m1,m2,m3); - if(!lock_first) - return; - lock_first=(lock_first+3)%lock_count; - break; - case 4: - lock_first=detail::lock_helper(m5,m1,m2,m3,m4); - if(!lock_first) - return; - lock_first=(lock_first+4)%lock_count; - break; - } - } - } - - namespace detail - { - template<typename Mutex,bool x=is_mutex_type<Mutex>::value> - struct try_lock_impl_return - { - typedef int type; - }; - - template<typename Iterator> - struct try_lock_impl_return<Iterator,false> - { - typedef Iterator type; - }; - - template<typename MutexType1,typename MutexType2> - int try_lock_impl(MutexType1& m1,MutexType2& m2,is_mutex_type_wrapper<true>) - { - return ((int)detail::try_lock_internal(m1,m2))-1; - } - - 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) - { - return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); - } - - template<typename MutexType1,typename MutexType2> - typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1,MutexType2& m2) - { - return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); - } - - template<typename MutexType1,typename MutexType2> - typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1,const MutexType2& m2) - { - return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); - } - - template<typename MutexType1,typename MutexType2> - typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1,const MutexType2& m2) - { - return detail::try_lock_impl(m1,m2,detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>()); - } - - template<typename MutexType1,typename MutexType2,typename MutexType3> - int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3) - { - return ((int)detail::try_lock_internal(m1,m2,m3))-1; - } - - template<typename MutexType1,typename MutexType2,typename MutexType3,typename MutexType4> - int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4) - { - return ((int)detail::try_lock_internal(m1,m2,m3,m4))-1; - } - - template<typename MutexType1,typename MutexType2,typename MutexType3,typename MutexType4,typename MutexType5> - int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4,MutexType5& m5) - { - return ((int)detail::try_lock_internal(m1,m2,m3,m4,m5))-1; - } - - - namespace detail - { - template<typename Iterator> - struct range_lock_guard - { - Iterator begin; - Iterator end; - - range_lock_guard(Iterator begin_,Iterator end_): - begin(begin_),end(end_) - { - boost::lock(begin,end); - } - - void release() - { - begin=end; - } - - ~range_lock_guard() - { - for(;begin!=end;++begin) - { - begin->unlock(); - } - } - }; - - template<typename Iterator> - Iterator try_lock_impl(Iterator begin,Iterator end,is_mutex_type_wrapper<false>) - - { - if(begin==end) - { - return end; - } - 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=boost::try_lock(++begin,end); - if(failed==end) - { - guard.release(); - } - - return failed; - } - } - - - namespace detail - { - template<typename Iterator> - 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; - } - bool start_with_begin=true; - 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=boost::try_lock(next,end); - if(failed_lock==end) - { - begin_lock.release(); - return; - } - start_with_begin=false; - next=failed_lock; - } - else - { - detail::range_lock_guard<Iterator> guard(next,end); - if(begin_lock.try_lock()) - { - Iterator const failed_lock=boost::try_lock(second,next); - if(failed_lock==next) - { - begin_lock.release(); - guard.release(); - return; - } - start_with_begin=false; - next=failed_lock; - } - else - { - start_with_begin=true; - next=second; - } - } - } - } - - } -} -#include <boost/config/abi_suffix.hpp> +#include <boost/thread/lock_algorithms.hpp> +#include <boost/thread/lock_types.hpp> +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/lockable_traits.hpp> +#include <boost/thread/lock_options.hpp> #endif diff --git a/3rdParty/Boost/src/boost/thread/mutex.hpp b/3rdParty/Boost/src/boost/thread/mutex.hpp index 4669886..05c6094 100644 --- a/3rdParty/Boost/src/boost/thread/mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/mutex.hpp @@ -3,7 +3,7 @@ // mutex.hpp // -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -18,4 +18,36 @@ #error "Boost threads unavailable on this platform" #endif +#include <boost/thread/lockable_traits.hpp> + + +namespace boost +{ + namespace sync + { +#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + template<> + struct is_basic_lockable<mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_lockable<mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_basic_lockable<timed_mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_lockable<timed_mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +#endif + } +} + #endif diff --git a/3rdParty/Boost/src/boost/thread/once.hpp b/3rdParty/Boost/src/boost/thread/once.hpp index acd216e..9fcfb53 100644 --- a/3rdParty/Boost/src/boost/thread/once.hpp +++ b/3rdParty/Boost/src/boost/thread/once.hpp @@ -9,11 +9,18 @@ // 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/thread/detail/platform.hpp> #if defined(BOOST_THREAD_PLATFORM_WIN32) #include <boost/thread/win32/once.hpp> #elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +#if defined BOOST_THREAD_ONCE_FAST_EPOCH #include <boost/thread/pthread/once.hpp> +#elif defined BOOST_THREAD_ONCE_ATOMIC +#include <boost/thread/pthread/once_atomic.hpp> +#else +#error "Once Not Implemented" +#endif #else #error "Boost threads unavailable on this platform" #endif @@ -24,7 +31,9 @@ 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) +template<typename Function> +inline void call_once(Function func,once_flag& flag) +//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 aa71007..b1b76b0 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/condition_variable.hpp @@ -4,11 +4,13 @@ // 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 +// (C) Copyright 2011-2012 Vicente J. Botet Escriba #include <boost/thread/pthread/timespec.hpp> #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS #include <boost/thread/pthread/thread_data.hpp> +#endif #include <boost/thread/pthread/condition_variable_fwd.hpp> #ifdef BOOST_THREAD_USES_CHRONO #include <boost/chrono/system_clocks.hpp> @@ -20,10 +22,12 @@ namespace boost { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS namespace this_thread { void BOOST_THREAD_DECL interruption_point(); } +#endif namespace thread_cv_detail { @@ -53,57 +57,88 @@ namespace boost inline void condition_variable::wait(unique_lock<mutex>& m) { +#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED + if(! m.owns_lock()) + { + boost::throw_exception(condition_error(-1, "boost::condition_variable::wait() failed precondition mutex not owned")); + } +#endif int res=0; { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS 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); +#else + //boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); + pthread_mutex_t* the_mutex = m.mutex()->native_handle(); + do { + res = pthread_cond_wait(&cond,the_mutex); + } while (res == EINTR); +#endif } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); +#endif if(res) { - boost::throw_exception(condition_error(res, "boost:: condition_variable constructor failed in pthread_cond_wait")); + boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_wait")); } } - inline bool condition_variable::do_timed_wait( + inline bool condition_variable::do_wait_until( unique_lock<mutex>& m, struct timespec const &timeout) { +#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED if (!m.owns_lock()) - boost::throw_exception(condition_error(EPERM, "condition_variable do_timed_wait: mutex not locked")); - + { + boost::throw_exception(condition_error(EPERM, "boost::condition_variable::do_wait_until() failed precondition mutex not owned")); + } +#endif thread_cv_detail::lock_on_exit<unique_lock<mutex> > guard; int cond_res; { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS detail::interruption_checker check_for_interruption(&internal_mutex,&cond); guard.activate(m); cond_res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); +#else + //boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); + pthread_mutex_t* the_mutex = m.mutex()->native_handle(); + cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout); +#endif } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); +#endif if(cond_res==ETIMEDOUT) { return false; } if(cond_res) { - boost::throw_exception(condition_error(cond_res, "condition_variable failed in pthread_cond_timedwait")); + boost::throw_exception(condition_error(cond_res, "boost::condition_variable::do_wait_until failed in pthread_cond_timedwait")); } return true; } inline void condition_variable::notify_one() BOOST_NOEXCEPT { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); +#endif BOOST_VERIFY(!pthread_cond_signal(&cond)); } inline void condition_variable::notify_all() BOOST_NOEXCEPT { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); +#endif BOOST_VERIFY(!pthread_cond_broadcast(&cond)); } @@ -119,13 +154,13 @@ namespace boost int const res=pthread_mutex_init(&internal_mutex,NULL); if(res) { - boost::throw_exception(thread_resource_error(res, "condition_variable_any failed in pthread_mutex_init")); + boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::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(res, "condition_variable_any failed in pthread_cond_init")); + boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_cond_init")); } } ~condition_variable_any() @@ -140,14 +175,20 @@ namespace boost int res=0; { thread_cv_detail::lock_on_exit<lock_type> guard; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS detail::interruption_checker check_for_interruption(&internal_mutex,&cond); +#else + boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); +#endif guard.activate(m); res=pthread_cond_wait(&cond,&internal_mutex); } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); +#endif if(res) { - boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_wait")); + boost::throw_exception(condition_error(res, "boost::condition_variable_any::wait() failed in pthread_cond_wait")); } } @@ -157,16 +198,17 @@ namespace boost while(!pred()) wait(m); } +#if defined BOOST_THREAD_USES_DATETIME 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) { - struct timespec const timeout=detail::get_timespec(wait_until); - return do_timed_wait(m, timeout); + struct timespec const timeout=detail::to_timespec(abs_time); + return do_wait_until(m, timeout); } template<typename lock_type> - bool timed_wait(lock_type& m,xtime const& wait_until) + bool timed_wait(lock_type& m,xtime const& abs_time) { - return timed_wait(m,system_time(wait_until)); + return timed_wait(m,system_time(abs_time)); } template<typename lock_type,typename duration_type> @@ -176,20 +218,20 @@ 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) { while (!pred()) { - if(!timed_wait(m, wait_until)) + if(!timed_wait(m, abs_time)) return pred(); } return true; } template<typename lock_type,typename predicate_type> - bool timed_wait(lock_type& m,xtime const& wait_until,predicate_type pred) + bool timed_wait(lock_type& m,xtime const& abs_time, predicate_type pred) { - return timed_wait(m,system_time(wait_until),pred); + return timed_wait(m,system_time(abs_time),pred); } template<typename lock_type,typename duration_type,typename predicate_type> @@ -197,7 +239,7 @@ namespace boost { return timed_wait(m,get_system_time()+wait_duration,pred); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class lock_type,class Duration> cv_status @@ -265,26 +307,26 @@ namespace boost const chrono::duration<Rep, Period>& d, Predicate pred) { - while (!pred()) - { - if (wait_for(lock, d) == cv_status::timeout) - return pred(); - } - return true; + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + +// while (!pred()) +// { +// if (wait_for(lock, d) == cv_status::timeout) +// return pred(); +// } +// return true; } template <class lock_type> - inline void wait_until( + cv_status 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); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; } #endif @@ -302,25 +344,31 @@ namespace boost private: // used by boost::thread::try_join_until template <class lock_type> - inline bool do_timed_wait( + inline bool do_wait_until( lock_type& m, struct timespec const &timeout) { int res=0; { thread_cv_detail::lock_on_exit<lock_type> guard; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS detail::interruption_checker check_for_interruption(&internal_mutex,&cond); +#else + boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); +#endif guard.activate(m); res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS this_thread::interruption_point(); +#endif if(res==ETIMEDOUT) { return false; } if(res) { - boost::throw_exception(condition_error(res, "condition_variable_any failed in pthread_cond_timedwait")); + boost::throw_exception(condition_error(res, "boost::condition_variable_any::do_wait_until() 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 dbb3892..e18030f 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/condition_variable_fwd.hpp @@ -4,22 +4,26 @@ // 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 +// (C) Copyright 2011-2012 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/lock_types.hpp> #include <boost/thread/thread_time.hpp> +#include <boost/thread/pthread/timespec.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/thread/xtime.hpp> +#endif #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 @@ -28,33 +32,58 @@ namespace boost class condition_variable { private: +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS pthread_mutex_t internal_mutex; +#endif pthread_cond_t cond; public: + //private: // used by boost::thread::try_join_until + + inline bool do_wait_until( + unique_lock<mutex>& lock, + struct timespec const &timeout); + + bool do_wait_for( + unique_lock<mutex>& lock, + struct timespec const &timeout) + { + return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now())); + } + + public: BOOST_THREAD_NO_COPYABLE(condition_variable) condition_variable() { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS int const res=pthread_mutex_init(&internal_mutex,NULL); if(res) { - boost::throw_exception(thread_resource_error(res, "boost:: condition_variable constructor failed in pthread_mutex_init")); + boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init")); } +#endif int const res2=pthread_cond_init(&cond,NULL); if(res2) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); - boost::throw_exception(thread_resource_error(res2, "boost:: condition_variable constructor failed in pthread_cond_init")); +#endif + boost::throw_exception(thread_resource_error(res2, "boost::condition_variable::condition_variable() constructor failed in pthread_cond_init")); } } ~condition_variable() { - BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); int ret; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + do { + ret = pthread_mutex_destroy(&internal_mutex); + } while (ret == EINTR); + BOOST_ASSERT(!ret); +#endif do { ret = pthread_cond_destroy(&cond); } while (ret == EINTR); - BOOST_VERIFY(!ret); + BOOST_ASSERT(!ret); } void wait(unique_lock<mutex>& m); @@ -66,23 +95,24 @@ namespace boost } +#if defined BOOST_THREAD_USES_DATETIME inline bool timed_wait( unique_lock<mutex>& m, - boost::system_time const& wait_until) + boost::system_time const& abs_time) { #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); + struct timespec const timeout=detail::to_timespec(abs_time + BOOST_THREAD_WAIT_BUG); + return do_wait_until(m, timeout); #else - struct timespec const timeout=detail::get_timespec(wait_until); - return do_timed_wait(m, timeout); + struct timespec const timeout=detail::to_timespec(abs_time); + return do_wait_until(m, timeout); #endif } bool timed_wait( unique_lock<mutex>& m, - xtime const& wait_until) + xtime const& abs_time) { - return timed_wait(m,system_time(wait_until)); + return timed_wait(m,system_time(abs_time)); } template<typename duration_type> @@ -96,11 +126,11 @@ namespace boost template<typename predicate_type> bool timed_wait( unique_lock<mutex>& m, - boost::system_time const& wait_until,predicate_type pred) + boost::system_time const& abs_time,predicate_type pred) { while (!pred()) { - if(!timed_wait(m, wait_until)) + if(!timed_wait(m, abs_time)) return pred(); } return true; @@ -109,9 +139,9 @@ namespace boost template<typename predicate_type> bool timed_wait( unique_lock<mutex>& m, - xtime const& wait_until,predicate_type pred) + xtime const& abs_time,predicate_type pred) { - return timed_wait(m,system_time(wait_until),pred); + return timed_wait(m,system_time(abs_time),pred); } template<typename duration_type,typename predicate_type> @@ -121,6 +151,7 @@ namespace boost { return timed_wait(m,get_system_time()+wait_duration,pred); } +#endif #ifdef BOOST_THREAD_USES_CHRONO @@ -190,12 +221,14 @@ namespace boost const chrono::duration<Rep, Period>& d, Predicate pred) { - while (!pred()) - { - if (wait_for(lock, d) == cv_status::timeout) - return pred(); - } - return true; + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + +// while (!pred()) +// { +// if (wait_for(lock, d) == cv_status::timeout) +// return pred(); +// } +// return true; } #endif @@ -210,27 +243,21 @@ namespace boost void notify_all() BOOST_NOEXCEPT; #ifdef BOOST_THREAD_USES_CHRONO - inline void wait_until( + inline cv_status 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); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; } #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); + } diff --git a/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp index 2c5af92..3e9af2a 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/mutex.hpp @@ -6,10 +6,14 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include <boost/thread/detail/config.hpp> #include <pthread.h> #include <boost/throw_exception.hpp> +#include <boost/core/ignore_unused.hpp> #include <boost/thread/exceptions.hpp> -#include <boost/thread/locks.hpp> +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include <boost/thread/lock_types.hpp> +#endif #include <boost/thread/thread_time.hpp> #include <boost/thread/xtime.hpp> #include <boost/assert.hpp> @@ -23,15 +27,68 @@ #include <boost/thread/detail/delete.hpp> #ifdef _POSIX_TIMEOUTS -#if _POSIX_TIMEOUTS >= 0 && _POSIX_C_SOURCE>=200112L +#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK #define BOOST_PTHREAD_HAS_TIMEDLOCK #endif #endif +#endif + #include <boost/config/abi_prefix.hpp> +#ifndef BOOST_THREAD_HAS_NO_EINTR_BUG +#define BOOST_THREAD_HAS_EINTR_BUG +#endif + namespace boost { + namespace posix { +#ifdef BOOST_THREAD_HAS_EINTR_BUG + BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m) + { + int ret; + do + { + ret = ::pthread_mutex_destroy(m); + } while (ret == EINTR); + return ret; + } + BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m) + { + int ret; + do + { + ret = ::pthread_mutex_lock(m); + } while (ret == EINTR); + return ret; + } + BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m) + { + int ret; + do + { + ret = ::pthread_mutex_unlock(m); + } while (ret == EINTR); + return ret; + } +#else + BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m) + { + return ::pthread_mutex_destroy(m); + } + BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m) + { + return ::pthread_mutex_lock(m); + } + BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m) + { + return ::pthread_mutex_unlock(m); + } + +#endif + + } class mutex { private: @@ -49,20 +106,14 @@ namespace boost } ~mutex() { - int ret; - do - { - ret = pthread_mutex_destroy(&m); - } while (ret == EINTR); + int const res = posix::pthread_mutex_destroy(&m); + boost::ignore_unused(res); + BOOST_ASSERT(!res); } void lock() { - int res; - do - { - res = pthread_mutex_lock(&m); - } while (res == EINTR); + int res = posix::pthread_mutex_lock(&m); if (res) { boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock")); @@ -71,12 +122,11 @@ namespace boost void unlock() { - int ret; - do + int res = posix::pthread_mutex_unlock(&m); + if (res) { - ret = pthread_mutex_unlock(&m); - } while (ret == EINTR); - BOOST_VERIFY(!ret); + boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); + } } bool try_lock() @@ -86,12 +136,8 @@ namespace boost { res = pthread_mutex_trylock(&m); } while (res == EINTR); - if(res && (res!=EBUSY)) + if (res==EBUSY) { - // 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; } @@ -105,8 +151,10 @@ namespace boost return &m; } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<mutex> scoped_lock; typedef detail::try_lock_wrapper<mutex> scoped_try_lock; +#endif }; typedef mutex try_mutex; @@ -132,7 +180,8 @@ namespace boost int const res2=pthread_cond_init(&cond,NULL); if(res2) { - BOOST_VERIFY(!pthread_mutex_destroy(&m)); + BOOST_VERIFY(!posix::pthread_mutex_destroy(&m)); + //BOOST_VERIFY(!pthread_mutex_destroy(&m)); boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init")); } is_locked=false; @@ -140,12 +189,13 @@ namespace boost } ~timed_mutex() { - BOOST_VERIFY(!pthread_mutex_destroy(&m)); + BOOST_VERIFY(!posix::pthread_mutex_destroy(&m)); #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK BOOST_VERIFY(!pthread_cond_destroy(&cond)); #endif } +#if defined BOOST_THREAD_USES_DATETIME template<typename TimeDuration> bool timed_lock(TimeDuration const & relative_time) { @@ -155,23 +205,39 @@ namespace boost { return timed_lock(system_time(absolute_time)); } - +#endif #ifdef BOOST_PTHREAD_HAS_TIMEDLOCK void lock() { - BOOST_VERIFY(!pthread_mutex_lock(&m)); + int res = posix::pthread_mutex_lock(&m); + if (res) + { + boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock")); + } } void unlock() { - BOOST_VERIFY(!pthread_mutex_unlock(&m)); + int res = posix::pthread_mutex_unlock(&m); + if (res) + { + boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); + } } bool try_lock() { - int const res=pthread_mutex_trylock(&m); - BOOST_ASSERT(!res || res==EBUSY); - return !res; + int res; + do + { + res = pthread_mutex_trylock(&m); + } while (res == EINTR); + if (res==EBUSY) + { + return false; + } + + return !res; } @@ -232,12 +298,13 @@ namespace boost public: #endif +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock(system_time const & abs_time) { - struct timespec const ts=detail::get_timespec(abs_time); + struct timespec const ts=boost::detail::to_timespec(abs_time); return do_try_lock_until(ts); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) @@ -261,12 +328,9 @@ namespace boost } 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()); + //using namespace chrono; + chrono::nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); return do_try_lock_until(ts); } #endif @@ -278,9 +342,11 @@ namespace boost return &m; } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<timed_mutex> scoped_timed_lock; typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock; typedef scoped_timed_lock scoped_lock; +#endif }; } diff --git a/3rdParty/Boost/src/boost/thread/pthread/once.hpp b/3rdParty/Boost/src/boost/thread/pthread/once.hpp index 02c2732..0bef038 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/once.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/once.hpp @@ -11,11 +11,14 @@ // http://www.boost.org/LICENSE_1_0.txt) #include <boost/thread/detail/config.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/detail/invoke.hpp> #include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp> #include <boost/thread/detail/delete.hpp> -#include <boost/detail/no_exceptions_support.hpp> +#include <boost/core/no_exceptions_support.hpp> +#include <boost/bind.hpp> #include <boost/assert.hpp> #include <boost/config/abi_prefix.hpp> @@ -26,21 +29,32 @@ namespace boost { -#define BOOST_ONCE_INITIAL_FLAG_VALUE 0 + struct once_flag; + + #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 + typedef boost::uint32_t uintmax_atomic_t; + #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(value) value##u #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(~0) -//#endif + } #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template<typename Function, class ...ArgTypes> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args); +#else + template<typename Function> + inline void call_once(once_flag& flag, Function f); + template<typename Function, typename T1> + inline void call_once(once_flag& flag, Function f, T1 p1); + template<typename Function, typename T1, typename T2> + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2); + template<typename Function, typename T1, typename T2, typename T3> + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3); +#endif struct once_flag { @@ -50,11 +64,26 @@ namespace boost {} private: volatile thread_detail::uintmax_atomic_t epoch; + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template<typename Function, class ...ArgTypes> + friend void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args); +#else template<typename Function> - friend - void call_once(once_flag& flag,Function f); + friend void call_once(once_flag& flag, Function f); + template<typename Function, typename T1> + friend void call_once(once_flag& flag, Function f, T1 p1); + template<typename Function, typename T1, typename T2> + friend void call_once(once_flag& flag, Function f, T1 p1, T2 p2); + template<typename Function, typename T1, typename T2, typename T3> + friend void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3); + +#endif + }; +#define BOOST_ONCE_INIT once_flag() + #else // BOOST_THREAD_PROVIDES_ONCE_CXX11 struct once_flag @@ -65,59 +94,445 @@ namespace boost #define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE} #endif // BOOST_THREAD_PROVIDES_ONCE_CXX11 - namespace detail + +#if defined BOOST_THREAD_PROVIDES_INVOKE +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void> +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#else +#define BOOST_THREAD_INVOKE_RET_VOID boost::bind +#define BOOST_THREAD_INVOKE_RET_VOID_CALL () +#endif + + namespace thread_detail { - 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 uintmax_atomic_t& get_once_per_thread_epoch(); + BOOST_THREAD_DECL extern 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; } // 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) + + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + + template<typename Function, class ...ArgTypes> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args) + { + 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=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<ArgTypes>(args))... + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + + } + } +#else + template<typename Function> + inline void call_once(once_flag& flag, Function f) + { + 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=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + f(); + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + + template<typename Function, typename T1> + inline void call_once(once_flag& flag, Function f, T1 p1) + { + 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=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + template<typename Function, typename T1, typename T2> + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2) + { + 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=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID(f,p1, p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + + template<typename Function, typename T1, typename T2, typename T3> + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3) + { + 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=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID(f,p1, p2, p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + + template<typename Function> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f) + { + 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=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + f(); + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + + template<typename Function, typename T1> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1) + { + 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=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_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(); + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); - if(epoch<this_thread_epoch) + while(flag.epoch<=being_initialized) { - pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex); + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + template<typename Function, typename T1, typename T2> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) + { + 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=thread_detail::get_once_per_thread_epoch(); + + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) + { + flag.epoch=being_initialized; + BOOST_TRY + { + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T1>(p2)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + + template<typename Function, typename T1, typename T2, typename T3> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) + { + 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=thread_detail::get_once_per_thread_epoch(); - while(flag.epoch<=being_initialized) + if(epoch<this_thread_epoch) + { + pthread::pthread_mutex_scoped_lock lk(&thread_detail::once_epoch_mutex); + + while(flag.epoch<=being_initialized) + { + if(flag.epoch==uninitialized_flag) { - if(flag.epoch==uninitialized_flag) + flag.epoch=being_initialized; + BOOST_TRY { - flag.epoch=being_initialized; - BOOST_TRY - { - pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex); - f(); - } - BOOST_CATCH (...) - { - flag.epoch=uninitialized_flag; - BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv)); - BOOST_RETHROW - } - BOOST_CATCH_END - flag.epoch=--detail::once_global_epoch; - BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv)); + pthread::pthread_mutex_scoped_unlock relocker(&thread_detail::once_epoch_mutex); + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T1>(p2)), + thread_detail::decay_copy(boost::forward<T1>(p3)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; } - else + BOOST_CATCH (...) { - while(flag.epoch==being_initialized) - { - BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv,&detail::once_epoch_mutex)); - } + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); } } - this_thread_epoch=detail::once_global_epoch; } + this_thread_epoch=thread_detail::once_global_epoch; } + } + +#endif + } #include <boost/config/abi_suffix.hpp> diff --git a/3rdParty/Boost/src/boost/thread/pthread/once_atomic.hpp b/3rdParty/Boost/src/boost/thread/pthread/once_atomic.hpp new file mode 100644 index 0000000..923f07b --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/pthread/once_atomic.hpp @@ -0,0 +1,313 @@ +#ifndef BOOST_THREAD_PTHREAD_ONCE_ATOMIC_HPP +#define BOOST_THREAD_PTHREAD_ONCE_ATOMIC_HPP + +// once.hpp +// +// (C) Copyright 2013 Andrey Semashev +// (C) Copyright 2013 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/cstdint.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/detail/invoke.hpp> +#include <boost/core/no_exceptions_support.hpp> +#include <boost/bind.hpp> +#include <boost/atomic.hpp> + +#include <boost/config/abi_prefix.hpp> + +namespace boost +{ + + struct once_flag; + + namespace thread_detail + { + +#if BOOST_ATOMIC_INT_LOCK_FREE == 2 + typedef unsigned int atomic_int_type; +#elif BOOST_ATOMIC_SHORT_LOCK_FREE == 2 + typedef unsigned short atomic_int_type; +#elif BOOST_ATOMIC_CHAR_LOCK_FREE == 2 + typedef unsigned char atomic_int_type; +#elif BOOST_ATOMIC_LONG_LOCK_FREE == 2 + typedef unsigned long atomic_int_type; +#elif defined(BOOST_HAS_LONG_LONG) && BOOST_ATOMIC_LLONG_LOCK_FREE == 2 + typedef ulong_long_type atomic_int_type; +#else + // All tested integer types are not atomic, the spinlock pool will be used + typedef unsigned int atomic_int_type; +#endif + + typedef boost::atomic<atomic_int_type> atomic_type; + + BOOST_THREAD_DECL bool enter_once_region(once_flag& flag) BOOST_NOEXCEPT; + BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT; + BOOST_THREAD_DECL void rollback_once_region(once_flag& flag) BOOST_NOEXCEPT; + inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT; + } + +#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 + + struct once_flag + { + BOOST_THREAD_NO_COPYABLE(once_flag) + BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT : storage(0) + { + } + + private: + thread_detail::atomic_type storage; + + friend BOOST_THREAD_DECL bool thread_detail::enter_once_region(once_flag& flag) BOOST_NOEXCEPT; + friend BOOST_THREAD_DECL void thread_detail::commit_once_region(once_flag& flag) BOOST_NOEXCEPT; + friend BOOST_THREAD_DECL void thread_detail::rollback_once_region(once_flag& flag) BOOST_NOEXCEPT; + friend thread_detail::atomic_type& thread_detail::get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT; + }; + +#define BOOST_ONCE_INIT boost::once_flag() + + namespace thread_detail + { + inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT + { + //return reinterpret_cast< atomic_type& >(flag.storage); + return flag.storage; + } + } + +#else // BOOST_THREAD_PROVIDES_ONCE_CXX11 + struct once_flag + { + // The thread_detail::atomic_int_type storage is marked + // with this attribute in order to let the compiler know that it will alias this member + // and silence compilation warnings. + BOOST_THREAD_ATTRIBUTE_MAY_ALIAS thread_detail::atomic_int_type storage; + }; + + #define BOOST_ONCE_INIT {0} + + namespace thread_detail + { + inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT + { + return reinterpret_cast< atomic_type& >(flag.storage); + } + + } + +#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11 + +#if defined BOOST_THREAD_PROVIDES_INVOKE +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void> +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#else +#define BOOST_THREAD_INVOKE_RET_VOID boost::bind +#define BOOST_THREAD_INVOKE_RET_VOID_CALL () +#endif + + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + template<typename Function, class ...ArgTypes> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<ArgTypes>(args))... + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } +#else + template<typename Function> + inline void call_once(once_flag& flag, Function f) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template<typename Function, typename T1> + inline void call_once(once_flag& flag, Function f, T1 p1) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f, p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template<typename Function, typename T1, typename T2> + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f, p1, p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template<typename Function, typename T1, typename T2, typename T3> + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f, p1, p2, p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template<typename Function> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template<typename Function, typename T1> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + template<typename Function, typename T1, typename T2> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T1>(p2)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + template<typename Function, typename T1, typename T2, typename T3> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T1>(p2)), + thread_detail::decay_copy(boost::forward<T1>(p3)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + + +#endif +} + +#include <boost/config/abi_suffix.hpp> + +#endif + diff --git a/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp index 2a6bc7d..9330d77 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/recursive_mutex.hpp @@ -9,7 +9,9 @@ #include <pthread.h> #include <boost/throw_exception.hpp> #include <boost/thread/exceptions.hpp> -#include <boost/thread/locks.hpp> +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include <boost/thread/lock_types.hpp> +#endif #include <boost/thread/thread_time.hpp> #include <boost/assert.hpp> #ifndef _WIN32 @@ -26,10 +28,13 @@ #include <boost/thread/detail/delete.hpp> #ifdef _POSIX_TIMEOUTS -#if _POSIX_TIMEOUTS >= 0 +#if _POSIX_TIMEOUTS >= 0 && _POSIX_TIMEOUTS>=200112L +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK #define BOOST_PTHREAD_HAS_TIMEDLOCK #endif #endif +#endif + #if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE) && defined(BOOST_PTHREAD_HAS_TIMEDLOCK) #define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK @@ -167,8 +172,10 @@ namespace boost #endif +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<recursive_mutex> scoped_lock; typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock; +#endif }; typedef recursive_mutex recursive_try_mutex; @@ -232,11 +239,13 @@ namespace boost #endif } +#if defined BOOST_THREAD_USES_DATETIME template<typename TimeDuration> bool timed_lock(TimeDuration const & relative_time) { return timed_lock(get_system_time()+relative_time); } +#endif #ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK void lock() @@ -334,12 +343,13 @@ namespace boost #endif +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock(system_time const & abs_time) { - struct timespec const ts=detail::get_timespec(abs_time); + struct timespec const ts=detail::to_timespec(abs_time); return do_try_lock_until(ts); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) @@ -363,12 +373,9 @@ namespace boost } 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()); + //using namespace chrono; + chrono::nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); return do_try_lock_until(ts); } #endif @@ -380,9 +387,11 @@ namespace boost return &m; } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS 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; +#endif }; } diff --git a/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp b/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp index cf45188..458d6c8 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/shared_mutex.hpp @@ -12,12 +12,15 @@ #include <boost/static_assert.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/condition_variable.hpp> +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS #include <boost/thread/detail/thread_interruption.hpp> +#endif #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/assert.hpp> #include <boost/config/abi_prefix.hpp> @@ -26,8 +29,125 @@ namespace boost class shared_mutex { private: - struct state_data + class state_data { + public: + state_data () : + shared_count(0), + exclusive(false), + upgrade(false), + exclusive_waiting_blocked(false) + {} + + void assert_free() const + { + BOOST_ASSERT( ! exclusive ); + BOOST_ASSERT( ! upgrade ); + BOOST_ASSERT( shared_count==0 ); + } + + void assert_locked() const + { + BOOST_ASSERT( exclusive ); + BOOST_ASSERT( shared_count==0 ); + BOOST_ASSERT( ! upgrade ); + } + + void assert_lock_shared () const + { + BOOST_ASSERT( ! exclusive ); + BOOST_ASSERT( shared_count>0 ); + //BOOST_ASSERT( (! upgrade) || (shared_count>1)); + // if upgraded there are at least 2 threads sharing the mutex, + // except when unlock_upgrade_and_lock has decreased the number of readers but has not taken yet exclusive ownership. + } + + void assert_lock_upgraded () const + { + BOOST_ASSERT( ! exclusive ); + BOOST_ASSERT( upgrade ); + BOOST_ASSERT( shared_count>0 ); + } + + void assert_lock_not_upgraded () const + { + BOOST_ASSERT( ! upgrade ); + } + + bool can_lock () const + { + return ! (shared_count || exclusive); + } + + void exclusive_blocked (bool blocked) + { + exclusive_waiting_blocked = blocked; + } + + void lock () + { + exclusive = true; + } + + void unlock () + { + exclusive = false; + exclusive_waiting_blocked = false; + } + + bool can_lock_shared () const + { + return ! (exclusive || exclusive_waiting_blocked); + } + + bool more_shared () const + { + return shared_count > 0 ; + } + unsigned get_shared_count () const + { + return shared_count ; + } + unsigned lock_shared () + { + return ++shared_count; + } + + + void unlock_shared () + { + --shared_count; + } + + bool unlock_shared_downgrades() + { + if (upgrade) { + upgrade=false; + exclusive=true; + return true; + } else { + exclusive_waiting_blocked=false; + return false; + } + } + + void lock_upgrade () + { + ++shared_count; + upgrade=true; + } + bool can_lock_upgrade () const + { + return ! (exclusive || exclusive_waiting_blocked || upgrade); + } + + void unlock_upgrade () + { + upgrade=false; + --shared_count; + } + + //private: unsigned shared_count; bool exclusive; bool upgrade; @@ -49,12 +169,11 @@ namespace boost } public: + BOOST_THREAD_NO_COPYABLE(shared_mutex) shared_mutex() { - state_data state_={0,0,0,0}; - state=state_; } ~shared_mutex() @@ -63,44 +182,45 @@ namespace boost void lock_shared() { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); - - while(state.exclusive || state.exclusive_waiting_blocked) +#endif + boost::unique_lock<boost::mutex> lk(state_change); + while(!state.can_lock_shared()) { shared_cond.wait(lk); } - ++state.shared_count; + state.lock_shared(); } bool try_lock_shared() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); - if(state.exclusive || state.exclusive_waiting_blocked) + if(!state.can_lock_shared()) { return false; } - else - { - ++state.shared_count; - return true; - } + state.lock_shared(); + return true; } +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock_shared(system_time const& timeout) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked) + while(!state.can_lock_shared()) { if(!shared_cond.timed_wait(lk,timeout)) { return false; } } - ++state.shared_count; + state.lock_shared(); return true; } @@ -109,6 +229,7 @@ namespace boost { return timed_lock_shared(get_system_time()+relative_time); } +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time) @@ -118,36 +239,43 @@ namespace boost template <class Clock, class Duration> bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); - while(state.exclusive || state.exclusive_waiting_blocked) + while(!state.can_lock_shared()) + //while(state.exclusive || state.exclusive_waiting_blocked) { if(cv_status::timeout==shared_cond.wait_until(lk,abs_time)) { return false; } } - ++state.shared_count; + state.lock_shared(); return true; } #endif void unlock_shared() { - boost::mutex::scoped_lock lk(state_change); - bool const last_reader=!--state.shared_count; - - if(last_reader) + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_shared(); + state.unlock_shared(); + if (! state.more_shared()) { - if(state.upgrade) + if (state.upgrade) { + // As there is a thread doing a unlock_upgrade_and_lock that is waiting for ! state.more_shared() + // avoid other threads to lock, lock_upgrade or lock_shared, so only this thread is notified. state.upgrade=false; state.exclusive=true; + lk.unlock(); upgrade_cond.notify_one(); } else { state.exclusive_waiting_blocked=false; + lk.unlock(); } release_waiters(); } @@ -155,10 +283,12 @@ namespace boost void lock() { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); - while(state.shared_count || state.exclusive) + while (state.shared_count || state.exclusive) { state.exclusive_waiting_blocked=true; exclusive_cond.wait(lk); @@ -166,10 +296,13 @@ namespace boost state.exclusive=true; } +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock(system_time const& timeout) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); while(state.shared_count || state.exclusive) { @@ -194,7 +327,7 @@ namespace boost { return timed_lock(get_system_time()+relative_time); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) @@ -204,8 +337,10 @@ namespace boost template <class Clock, class Duration> bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); while(state.shared_count || state.exclusive) { @@ -228,7 +363,7 @@ namespace boost bool try_lock() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); if(state.shared_count || state.exclusive) { @@ -244,28 +379,35 @@ namespace boost void unlock() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_locked(); state.exclusive=false; state.exclusive_waiting_blocked=false; + state.assert_free(); release_waiters(); } void lock_upgrade() { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) { shared_cond.wait(lk); } - ++state.shared_count; + state.lock_shared(); state.upgrade=true; } +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock_upgrade(system_time const& timeout) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) { if(!shared_cond.timed_wait(lk,timeout)) @@ -277,7 +419,7 @@ namespace boost break; } } - ++state.shared_count; + state.lock_shared(); state.upgrade=true; return true; } @@ -287,7 +429,7 @@ namespace boost { return timed_lock_upgrade(get_system_time()+relative_time); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_upgrade_for(const chrono::duration<Rep, Period>& rel_time) @@ -297,8 +439,10 @@ namespace boost template <class Clock, class Duration> bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) { if(cv_status::timeout == shared_cond.wait_until(lk,abs_time)) @@ -310,68 +454,75 @@ namespace boost break; } } - ++state.shared_count; + state.lock_shared(); state.upgrade=true; return true; } #endif bool try_lock_upgrade() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) { return false; } else { - ++state.shared_count; + state.lock_shared(); state.upgrade=true; + state.assert_lock_upgraded(); return true; } } void unlock_upgrade() { - boost::mutex::scoped_lock lk(state_change); - state.upgrade=false; - bool const last_reader=!--state.shared_count; - - if(last_reader) + boost::unique_lock<boost::mutex> lk(state_change); + //state.upgrade=false; + state.unlock_upgrade(); + if(! state.more_shared() ) { state.exclusive_waiting_blocked=false; release_waiters(); } else { - shared_cond.notify_all(); + shared_cond.notify_all(); } } // Upgrade <-> Exclusive void unlock_upgrade_and_lock() { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); - --state.shared_count; - while(state.shared_count) +#endif + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_upgraded(); + state.unlock_shared(); + while (state.more_shared()) { upgrade_cond.wait(lk); } state.upgrade=false; state.exclusive=true; + state.assert_locked(); } void unlock_and_lock_upgrade() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_locked(); state.exclusive=false; state.upgrade=true; - ++state.shared_count; + state.lock_shared(); state.exclusive_waiting_blocked=false; + state.assert_lock_upgraded(); release_waiters(); } bool try_unlock_upgrade_and_lock() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_upgraded(); if( !state.exclusive && !state.exclusive_waiting_blocked && state.upgrade @@ -380,6 +531,7 @@ namespace boost state.shared_count=0; state.exclusive=true; state.upgrade=false; + state.assert_locked(); return true; } return false; @@ -398,8 +550,11 @@ namespace boost try_unlock_upgrade_and_lock_until( const chrono::time_point<Clock, Duration>& abs_time) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_upgraded(); if (state.shared_count != 1) { for (;;) @@ -422,9 +577,10 @@ namespace boost // Shared <-> Exclusive void unlock_and_lock_shared() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_locked(); state.exclusive=false; - ++state.shared_count; + state.lock_shared(); state.exclusive_waiting_blocked=false; release_waiters(); } @@ -432,7 +588,8 @@ namespace boost #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS bool try_unlock_shared_and_lock() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_shared(); if( !state.exclusive && !state.exclusive_waiting_blocked && !state.upgrade @@ -458,8 +615,11 @@ namespace boost try_unlock_shared_and_lock_until( const chrono::time_point<Clock, Duration>& abs_time) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_shared(); if (state.shared_count != 1) { for (;;) @@ -483,7 +643,8 @@ namespace boost // Shared <-> Upgrade void unlock_upgrade_and_lock_shared() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_upgraded(); state.upgrade=false; state.exclusive_waiting_blocked=false; release_waiters(); @@ -492,7 +653,8 @@ namespace boost #ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS bool try_unlock_shared_and_lock_upgrade() { - boost::mutex::scoped_lock lk(state_change); + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_shared(); if( !state.exclusive && !state.exclusive_waiting_blocked && !state.upgrade @@ -517,8 +679,11 @@ namespace boost try_unlock_shared_and_lock_upgrade_until( const chrono::time_point<Clock, Duration>& abs_time) { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS boost::this_thread::disable_interruption do_not_disturb; - boost::mutex::scoped_lock lk(state_change); +#endif + boost::unique_lock<boost::mutex> lk(state_change); + state.assert_lock_shared(); if( state.exclusive || state.exclusive_waiting_blocked || state.upgrade diff --git a/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp b/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp index db4e09f..801f470 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/thread_data.hpp @@ -8,13 +8,13 @@ #include <boost/thread/detail/config.hpp> #include <boost/thread/exceptions.hpp> -#include <boost/thread/locks.hpp> +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/lock_types.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/optional.hpp> #include <boost/assert.hpp> #ifdef BOOST_THREAD_USES_CHRONO #include <boost/chrono/system_clocks.hpp> @@ -24,6 +24,10 @@ #include <vector> #include <utility> +#if defined(__ANDROID__) +#include <asm/page.h> // http://code.google.com/p/android/issues/detail?id=39983 +#endif + #include <pthread.h> #include <unistd.h> @@ -77,6 +81,7 @@ namespace boost namespace detail { + struct shared_state_base; struct tss_cleanup_function; struct thread_exit_callback_node; struct tss_data_node @@ -107,8 +112,7 @@ namespace boost bool joined; boost::detail::thread_exit_callback_node* thread_exit_callbacks; std::map<void const*,boost::detail::tss_data_node> tss_data; - bool interrupt_enabled; - bool interrupt_requested; + pthread_mutex_t* cond_mutex; pthread_cond_t* current_cond; typedef std::vector<std::pair<condition_variable*, mutex*> @@ -116,27 +120,49 @@ namespace boost > notify_list_t; notify_list_t notify; + typedef std::vector<shared_ptr<shared_state_base> > async_states_t; + async_states_t async_states_; + +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + // These data must be at the end so that the access to the other fields doesn't change + // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined. + // Another option is to have them always + bool interrupt_enabled; + bool interrupt_requested; +//#endif thread_data_base(): + thread_handle(0), done(false),join_started(false),joined(false), thread_exit_callbacks(0), - interrupt_enabled(true), - interrupt_requested(false), + cond_mutex(0), current_cond(0), - notify() + notify(), + async_states_() +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + , interrupt_enabled(true) + , interrupt_requested(false) +//#endif {} 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) + virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m) { notify.push_back(std::pair<condition_variable*, mutex*>(cv, m)); } + + void make_ready_at_thread_exit(shared_ptr<shared_state_base> as) + { + async_states_.push_back(as); + } + }; BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS class interruption_checker { thread_data_base* const thread_info; @@ -188,71 +214,68 @@ namespace boost } } }; +#endif } namespace this_thread { + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts); + void BOOST_THREAD_DECL sleep_until(const timespec& ts); + } + #ifdef BOOST_THREAD_USES_CHRONO +#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + 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 - } - } + return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns)); } #endif +#endif // BOOST_THREAD_USES_CHRONO + + namespace no_interruption_point + { + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts); + void BOOST_THREAD_DECL sleep_until(const timespec& ts); + } + + #ifdef BOOST_THREAD_USES_CHRONO + #ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + + inline + void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) + { + return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns)); + } + #endif + #endif // BOOST_THREAD_USES_CHRONO + + } // no_interruption_point + void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; +#if defined BOOST_THREAD_USES_DATETIME #ifdef __DECXXX /// Workaround of DECCXX issue of incorrect template substitution - template<typename TimeDuration> - inline void sleep(TimeDuration const& rel_time) + template<> +#endif + inline void sleep(system_time const& abs_time) { - this_thread::sleep(get_system_time()+rel_time); + return boost::this_thread::hiden::sleep_until(boost::detail::to_timespec(abs_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 - } +#endif // BOOST_THREAD_USES_DATETIME + } // this_thread } #include <boost/config/abi_suffix.hpp> diff --git a/3rdParty/Boost/src/boost/thread/pthread/timespec.hpp b/3rdParty/Boost/src/boost/thread/pthread/timespec.hpp index d7465c1..82f50f6 100644 --- a/3rdParty/Boost/src/boost/thread/pthread/timespec.hpp +++ b/3rdParty/Boost/src/boost/thread/pthread/timespec.hpp @@ -1,34 +1,118 @@ #ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP #define BOOST_THREAD_PTHREAD_TIMESPEC_HPP -// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2007-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/thread/detail/config.hpp> #include <boost/thread/thread_time.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/date_time/posix_time/conversion.hpp> +#endif #include <pthread.h> #ifndef _WIN32 #include <unistd.h> #endif +#ifdef BOOST_THREAD_USES_CHRONO +#include <boost/chrono/duration.hpp> +#endif + +#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +# define BOOST_THREAD_TIMESPEC_MAC_API +#include <sys/time.h> //for gettimeofday and timeval +#else +#include <time.h> // for clock_gettime +#endif #include <boost/config/abi_prefix.hpp> namespace boost { - namespace detail - { - inline struct timespec get_timespec(boost::system_time const& abs_time) - { - struct timespec timeout={0,0}; - boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0); - - timeout.tv_sec=time_since_epoch.total_seconds(); - timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second())); - return timeout; - } + namespace detail + { +#if defined BOOST_THREAD_USES_DATETIME + inline struct timespec to_timespec(boost::system_time const& abs_time) + { + struct timespec timeout = { 0,0}; + boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0); + + timeout.tv_sec=time_since_epoch.total_seconds(); + timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second())); + return timeout; + } +#endif +#if defined BOOST_THREAD_USES_CHRONO + inline timespec to_timespec(chrono::nanoseconds const& ns) + { + struct timespec ts; + ts.tv_sec = static_cast<long>(chrono::duration_cast<chrono::seconds>(ns).count()); + ts.tv_nsec = static_cast<long>((ns - chrono::duration_cast<chrono::seconds>(ns)).count()); + return ts; } + +#endif + + inline timespec to_timespec(boost::intmax_t const& ns) + { + boost::intmax_t s = ns / 1000000000l; + struct timespec ts; + ts.tv_sec = static_cast<long> (s); + ts.tv_nsec = static_cast<long> (ns - s * 1000000000l); + return ts; + } + inline boost::intmax_t to_nanoseconds_int_max(timespec const& ts) + { + return static_cast<boost::intmax_t>(ts.tv_sec) * 1000000000l + ts.tv_nsec; + } + inline bool timespec_ge_zero(timespec const& ts) + { + return (ts.tv_sec >= 0) || (ts.tv_nsec >= 0); + } + inline timespec timespec_now() + { + timespec ts; + +#if defined(BOOST_THREAD_TIMESPEC_MAC_API) + timeval tv; + ::gettimeofday(&tv, 0); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; +#else + if ( ::clock_gettime( CLOCK_REALTIME, &ts ) ) + { + BOOST_ASSERT(0 && "Boost::Thread - Internal Error"); + } +#endif + return ts; + } + inline timespec timespec_zero() + { + timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 0; + return ts; + } + inline timespec timespec_plus(timespec const& lhs, timespec const& rhs) + { + return to_timespec(to_nanoseconds_int_max(lhs) + to_nanoseconds_int_max(rhs)); + } + inline timespec timespec_minus(timespec const& lhs, timespec const& rhs) + { + return to_timespec(to_nanoseconds_int_max(lhs) - to_nanoseconds_int_max(rhs)); + } + inline bool timespec_gt(timespec const& lhs, timespec const& rhs) + { + return to_nanoseconds_int_max(lhs) > to_nanoseconds_int_max(rhs); + } + inline bool timespec_ge(timespec const& lhs, timespec const& rhs) + { + return to_nanoseconds_int_max(lhs) >= to_nanoseconds_int_max(rhs); + } + + } } #include <boost/config/abi_suffix.hpp> diff --git a/3rdParty/Boost/src/boost/thread/recursive_mutex.hpp b/3rdParty/Boost/src/boost/thread/recursive_mutex.hpp index d5f6116..e716a19 100644 --- a/3rdParty/Boost/src/boost/thread/recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/recursive_mutex.hpp @@ -3,7 +3,7 @@ // recursive_mutex.hpp // -// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2007 Anthony Williams // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -18,4 +18,47 @@ #error "Boost threads unavailable on this platform" #endif +#include <boost/thread/lockable_traits.hpp> + +namespace boost +{ + namespace sync + { + +#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + template<> + struct is_basic_lockable<recursive_mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_lockable<recursive_mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_basic_lockable<recursive_timed_mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_lockable<recursive_timed_mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +#endif + + template<> + struct is_recursive_mutex_sur_parolle<recursive_mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_recursive_mutex_sur_parolle<recursive_timed_mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + } +} #endif diff --git a/3rdParty/Boost/src/boost/thread/shared_mutex.hpp b/3rdParty/Boost/src/boost/thread/shared_mutex.hpp index e85e269..b968f2a 100644 --- a/3rdParty/Boost/src/boost/thread/shared_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/shared_mutex.hpp @@ -18,9 +18,32 @@ #include <boost/thread/win32/shared_mutex.hpp> #endif #elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +//#include <boost/thread/v2/shared_mutex.hpp> #include <boost/thread/pthread/shared_mutex.hpp> #else #error "Boost threads unavailable on this platform" #endif +#include <boost/thread/lockable_traits.hpp> + +namespace boost +{ + namespace sync + { +#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + template<> + struct is_basic_lockable<shared_mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_lockable<shared_mutex> + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +#endif + + } +} + #endif diff --git a/3rdParty/Boost/src/boost/thread/thread.hpp b/3rdParty/Boost/src/boost/thread/thread.hpp index ee15c6e..3e63b42 100644 --- a/3rdParty/Boost/src/boost/thread/thread.hpp +++ b/3rdParty/Boost/src/boost/thread/thread.hpp @@ -9,20 +9,8 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include <boost/thread/detail/platform.hpp> - -#if defined(BOOST_THREAD_PLATFORM_WIN32) -#include <boost/thread/win32/thread_data.hpp> -#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) -#include <boost/thread/pthread/thread_data.hpp> -#else -#error "Boost threads unavailable on this platform" -#endif - -#include <boost/thread/detail/thread.hpp> -#include <boost/thread/detail/thread_interruption.hpp> +#include <boost/thread/thread_only.hpp> #include <boost/thread/detail/thread_group.hpp> -#include <boost/thread/v2/thread.hpp> #endif diff --git a/3rdParty/Boost/src/boost/thread/thread_only.hpp b/3rdParty/Boost/src/boost/thread/thread_only.hpp new file mode 100644 index 0000000..0d0c070 --- /dev/null +++ b/3rdParty/Boost/src/boost/thread/thread_only.hpp @@ -0,0 +1,29 @@ +#ifndef BOOST_THREAD_THREAD_ONLY_HPP +#define BOOST_THREAD_THREAD_ONLY_HPP + +// thread.hpp +// +// (C) Copyright 2013 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> + +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#include <boost/thread/win32/thread_data.hpp> +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +#include <boost/thread/pthread/thread_data.hpp> +#else +#error "Boost threads unavailable on this platform" +#endif + +#include <boost/thread/detail/thread.hpp> +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS +#include <boost/thread/detail/thread_interruption.hpp> +#endif +#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 index d686c5f..181661a 100644 --- a/3rdParty/Boost/src/boost/thread/v2/thread.hpp +++ b/3rdParty/Boost/src/boost/thread/v2/thread.hpp @@ -9,26 +9,77 @@ #include <boost/thread/detail/config.hpp> #ifdef BOOST_THREAD_USES_CHRONO #include <boost/chrono/system_clocks.hpp> +#include <boost/chrono/ceil.hpp> #endif #include <boost/thread/condition_variable.hpp> -#include <boost/thread/locks.hpp> +#include <boost/thread/lock_types.hpp> namespace boost { namespace this_thread { - + namespace no_interruption_point + { #ifdef BOOST_THREAD_USES_CHRONO + 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); + } + +#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + 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); + if (d > duration<Rep, Period>::zero()) + { + duration<long double> Max = nanoseconds::max BOOST_PREVENT_MACRO_SUBSTITUTION (); + nanoseconds ns; + if (d < Max) + { + ns = duration_cast<nanoseconds>(d); + if (ns < d) + ++ns; + } + else + ns = nanoseconds:: max BOOST_PREVENT_MACRO_SUBSTITUTION (); + sleep_for(ns); + } } + 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()); + } +#else + template <class Rep, class Period> + void sleep_for(const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + if (d > duration<Rep, Period>::zero()) + { + steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d); + sleep_until(c_timeout); + } + } + +#endif + +#endif + } +#ifdef BOOST_THREAD_USES_CHRONO + template <class Clock, class Duration> void sleep_until(const chrono::time_point<Clock, Duration>& t) { @@ -40,6 +91,28 @@ namespace boost cv.wait_until(lk, t); } +#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + + template <class Rep, class Period> + void sleep_for(const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + if (d > duration<Rep, Period>::zero()) + { + duration<long double> Max = nanoseconds::max BOOST_PREVENT_MACRO_SUBSTITUTION (); + nanoseconds ns; + if (d < Max) + { + ns = duration_cast<nanoseconds>(d); + if (ns < d) + ++ns; + } + else + ns = nanoseconds:: max BOOST_PREVENT_MACRO_SUBSTITUTION (); + sleep_for(ns); + } + } + template <class Duration> inline BOOST_SYMBOL_VISIBLE void sleep_until(const chrono::time_point<chrono::steady_clock, Duration>& t) @@ -47,6 +120,19 @@ namespace boost using namespace chrono; sleep_for(t - steady_clock::now()); } +#else + template <class Rep, class Period> + void sleep_for(const chrono::duration<Rep, Period>& d) + { + using namespace chrono; + if (d > duration<Rep, Period>::zero()) + { + steady_clock::time_point c_timeout = steady_clock::now() + ceil<nanoseconds>(d); + sleep_until(c_timeout); + } + } + +#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 e259121..cfdfa04 100644 --- a/3rdParty/Boost/src/boost/thread/win32/basic_recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/basic_recursive_mutex.hpp @@ -58,6 +58,7 @@ namespace boost recursion_count=1; } } +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock(::boost::system_time const& target) { long const current_thread_id=win32::GetCurrentThreadId(); @@ -68,6 +69,7 @@ namespace boost { return timed_lock(get_system_time()+timeout); } +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> @@ -114,6 +116,7 @@ namespace boost return false; } +#if defined BOOST_THREAD_USES_DATETIME bool try_timed_lock(long current_thread_id,::boost::system_time const& target) { if(mutex.timed_lock(target)) @@ -124,6 +127,7 @@ namespace boost } return false; } +#endif template <typename TP> bool try_timed_lock_until(long current_thread_id,TP const& target) { 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 6a43077..01db033 100644 --- a/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/basic_timed_mutex.hpp @@ -14,7 +14,9 @@ #include <boost/thread/win32/thread_primitives.hpp> #include <boost/thread/win32/interlocked_read.hpp> #include <boost/thread/thread_time.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/thread/xtime.hpp> +#endif #include <boost/detail/interlocked.hpp> #ifdef BOOST_THREAD_USES_CHRONO #include <boost/chrono/system_clocks.hpp> @@ -79,8 +81,10 @@ namespace boost do { - BOOST_VERIFY(win32::WaitForSingleObject( - sem,::boost::detail::win32::infinite)==0); + unsigned const retval(win32::WaitForSingleObject(sem, ::boost::detail::win32::infinite)); + BOOST_VERIFY(0 == retval || ::boost::detail::win32::wait_abandoned == retval); +// BOOST_VERIFY(win32::WaitForSingleObject( +// sem,::boost::detail::win32::infinite)==0); clear_waiting_and_try_lock(old_count); lock_acquired=!(old_count&lock_flag_value); } @@ -91,10 +95,13 @@ namespace boost { for(;;) { - long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value); + bool const was_locked=(old_count&lock_flag_value) ? true : false; + long const new_count=was_locked?(old_count+1):(old_count|lock_flag_value); long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count); if(current==old_count) { + if(was_locked) + old_count=new_count; break; } old_count=current; @@ -118,6 +125,7 @@ namespace boost } +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock(::boost::system_time const& wait_until) { if(try_lock()) @@ -147,7 +155,6 @@ namespace boost return true; } - template<typename Duration> bool timed_lock(Duration const& timeout) { @@ -158,7 +165,7 @@ namespace boost { return timed_lock(system_time(timeout)); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) diff --git a/3rdParty/Boost/src/boost/thread/win32/condition_variable.hpp b/3rdParty/Boost/src/boost/thread/win32/condition_variable.hpp index 4c893ad..57aaf8c 100644 --- a/3rdParty/Boost/src/boost/thread/win32/condition_variable.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/condition_variable.hpp @@ -11,9 +11,13 @@ #include <boost/thread/win32/thread_data.hpp> #include <boost/thread/win32/interlocked_read.hpp> #include <boost/thread/cv_status.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/thread/xtime.hpp> +#endif #include <boost/thread/mutex.hpp> #include <boost/thread/thread_time.hpp> +#include <boost/thread/lock_guard.hpp> +#include <boost/thread/lock_types.hpp> #include <boost/assert.hpp> #include <boost/intrusive_ptr.hpp> @@ -187,18 +191,17 @@ namespace boost struct entry_manager { entry_ptr const entry; + boost::mutex& internal_mutex; BOOST_THREAD_NO_COPYABLE(entry_manager) - entry_manager(entry_ptr const& entry_): - entry(entry_) + entry_manager(entry_ptr const& entry_, boost::mutex& mutex_): + entry(entry_), internal_mutex(mutex_) {} ~entry_manager() { - if(! entry->is_notified()) - { + boost::lock_guard<boost::mutex> internal_lock(internal_mutex); entry->remove_waiter(); - } } list_entry* operator->() @@ -214,7 +217,7 @@ namespace boost { relocker<lock_type> locker(lock); - entry_manager entry(get_wait_entry()); + entry_manager entry(get_wait_entry(), internal_mutex); locker.unlock(); @@ -321,6 +324,7 @@ namespace boost } +#if defined BOOST_THREAD_USES_DATETIME bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time) { return do_wait(m,abs_time); @@ -333,7 +337,16 @@ namespace boost template<typename duration_type> bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration) { - return do_wait(m,wait_duration.total_milliseconds()); + if (wait_duration.is_pos_infinity()) + { + wait(m); // or do_wait(m,detail::timeout::sentinel()); + return true; + } + if (wait_duration.is_special()) + { + return true; + } + return do_wait(m,wait_duration.total_milliseconds()); } template<typename predicate_type> @@ -351,7 +364,7 @@ namespace boost { return do_wait(m,wait_duration.total_milliseconds(),pred); } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Clock, class Duration> @@ -361,7 +374,11 @@ namespace boost const chrono::time_point<Clock, Duration>& t) { using namespace chrono; - do_wait(lock, ceil<milliseconds>(t-Clock::now()).count()); + chrono::time_point<Clock, Duration> now = Clock::now(); + if (t<=now) { + return cv_status::timeout; + } + do_wait(lock, ceil<milliseconds>(t-now).count()); return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; } @@ -373,6 +390,10 @@ namespace boost const chrono::duration<Rep, Period>& d) { using namespace chrono; + if (d<=chrono::duration<Rep, Period>::zero()) { + return cv_status::timeout; + } + 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 : @@ -400,7 +421,7 @@ namespace boost const chrono::duration<Rep, Period>& d, Predicate pred) { - return wait_until(lock, chrono::steady_clock::now() + d, pred); + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); } #endif }; @@ -428,6 +449,7 @@ namespace boost while(!pred()) wait(m); } +#if defined BOOST_THREAD_USES_DATETIME template<typename lock_type> bool timed_wait(lock_type& m,boost::system_time const& abs_time) { @@ -463,6 +485,7 @@ namespace boost { return do_wait(m,wait_duration.total_milliseconds(),pred); } +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class lock_type, class Clock, class Duration> @@ -472,7 +495,11 @@ namespace boost const chrono::time_point<Clock, Duration>& t) { using namespace chrono; - do_wait(lock, ceil<milliseconds>(t-Clock::now()).count()); + chrono::time_point<Clock, Duration> now = Clock::now(); + if (t<=now) { + return cv_status::timeout; + } + do_wait(lock, ceil<milliseconds>(t-now).count()); return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; } @@ -484,6 +511,9 @@ namespace boost const chrono::duration<Rep, Period>& d) { using namespace chrono; + if (d<=chrono::duration<Rep, Period>::zero()) { + return cv_status::timeout; + } 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 : @@ -512,7 +542,7 @@ namespace boost const chrono::duration<Rep, Period>& d, Predicate pred) { - return wait_until(lock, chrono::steady_clock::now() + d, pred); + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); } #endif }; diff --git a/3rdParty/Boost/src/boost/thread/win32/mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/mutex.hpp index 85a00e2..0154478 100644 --- a/3rdParty/Boost/src/boost/thread/win32/mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/mutex.hpp @@ -8,7 +8,10 @@ #include <boost/thread/win32/basic_timed_mutex.hpp> #include <boost/thread/exceptions.hpp> -#include <boost/thread/locks.hpp> +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include <boost/thread/lock_types.hpp> +#endif +#include <boost/thread/detail/delete.hpp> #include <boost/config/abi_prefix.hpp> @@ -33,8 +36,10 @@ namespace boost destroy(); } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<mutex> scoped_lock; typedef detail::try_lock_wrapper<mutex> scoped_try_lock; +#endif }; typedef mutex try_mutex; @@ -54,9 +59,11 @@ namespace boost destroy(); } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<timed_mutex> scoped_timed_lock; typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock; typedef scoped_timed_lock scoped_lock; +#endif }; } diff --git a/3rdParty/Boost/src/boost/thread/win32/once.hpp b/3rdParty/Boost/src/boost/thread/win32/once.hpp index 3066b50..0ed56a5 100644 --- a/3rdParty/Boost/src/boost/thread/win32/once.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/once.hpp @@ -5,7 +5,7 @@ // // (C) Copyright 2005-7 Anthony Williams // (C) Copyright 2005 John Maddock -// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// (C) Copyright 2011-2013 Vicente J. Botet Escriba // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -18,6 +18,11 @@ #include <boost/detail/interlocked.hpp> #include <boost/thread/win32/thread_primitives.hpp> #include <boost/thread/win32/interlocked_read.hpp> +#include <boost/core/no_exceptions_support.hpp> +#include <boost/thread/detail/move.hpp> +#include <boost/thread/detail/invoke.hpp> + +#include <boost/bind.hpp> #include <boost/config/abi_prefix.hpp> @@ -31,6 +36,16 @@ namespace std namespace boost { + struct once_flag; + namespace detail + { + struct once_context; + + inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT; + inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT; + inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT; + } + #ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 struct once_flag @@ -39,12 +54,12 @@ namespace boost 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); + private: + friend inline bool enter_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT; + friend inline void commit_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT; + friend inline void rollback_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT; }; #define BOOST_ONCE_INIT once_flag() @@ -59,6 +74,17 @@ namespace boost #define BOOST_ONCE_INIT {0,0} #endif // BOOST_THREAD_PROVIDES_ONCE_CXX11 +#if defined BOOST_THREAD_PROVIDES_INVOKE +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke<void> +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#else +#define BOOST_THREAD_INVOKE_RET_VOID boost::bind +#define BOOST_THREAD_INVOKE_RET_VOID_CALL () +#endif + namespace detail { #ifdef BOOST_NO_ANSI_APIS @@ -135,94 +161,928 @@ namespace boost ::boost::detail::win32::event_initially_reset, mutex_name); } - } + struct once_context { + long const function_complete_flag_value; + long const running_value; + bool counted; + detail::win32::handle_manager event_handle; + detail::once_char_type mutex_name[once_mutex_name_length]; + once_context() : + function_complete_flag_value(0xc15730e2), + running_value(0x7f0725e3), + counted(false) + { + mutex_name[0]=0; + } + }; + enum once_action {try_, break_, continue_}; + inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT + { + long status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,ctx.running_value,0); + if(!status) + { + if(!ctx.event_handle) + { + ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag); + } + if(ctx.event_handle) + { + ::boost::detail::win32::ResetEvent(ctx.event_handle); + } + return true; + } + return false; + } + inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT + { + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + } + BOOST_INTERLOCKED_EXCHANGE(&flag.status,ctx.function_complete_flag_value); + if(!ctx.event_handle && + (::boost::detail::interlocked_read_acquire(&flag.count)>1)) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + } + if(ctx.event_handle) + { + ::boost::detail::win32::SetEvent(ctx.event_handle); + } + } + inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT + { + BOOST_INTERLOCKED_EXCHANGE(&flag.status,0); + if(!ctx.event_handle) + { + ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag); + } + if(ctx.event_handle) + { + ::boost::detail::win32::SetEvent(ctx.event_handle); + } + } + } + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + inline void call_once(once_flag& flag, void (*f)()) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } +//#endif + template<typename Function> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, class A, class ...ArgTypes> + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(A) a, BOOST_THREAD_RV_REF(ArgTypes)... args) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<A>(a)), + thread_detail::decay_copy(boost::forward<ArgTypes>(args))... + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } +#else +#if ! defined(BOOST_MSVC) && ! defined(BOOST_INTEL) template<typename Function> void call_once(once_flag& flag,Function f) { // Try for a quick win: if the procedure has already been called // just skip through: - long const function_complete_flag_value=0xc15730e2; - long const running_value=0x7f0725e3; - long status; - bool counted=false; - detail::win32::handle_manager event_handle; - detail::once_char_type mutex_name[detail::once_mutex_name_length]; - mutex_name[0]=0; + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1> + void call_once(once_flag& flag,Function f, T1 p1) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2> + void call_once(once_flag& flag,Function f, T1 p1, T2 p2) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2, typename T3> + void call_once(once_flag& flag,Function f, T1 p1, T2 p2, T3 p3) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } +#elif defined BOOST_NO_CXX11_RVALUE_REFERENCES - while((status=::boost::detail::interlocked_read_acquire(&flag.status)) - !=function_complete_flag_value) + template<typename Function> + void call_once(once_flag& flag,Function const&f) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) { - status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,running_value,0); - if(!status) + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) { -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1> + void call_once(once_flag& flag,Function const&f, T1 const&p1) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2> + void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2, typename T3> + void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2, T3 const&p3) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } #endif +#if 1 +#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + inline void call_once(once_flag& flag, void (*f)()) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) { - if(!event_handle) + BOOST_TRY { - event_handle=detail::open_once_event(mutex_name,&flag); + f(); } - if(event_handle) + BOOST_CATCH(...) { - ::boost::detail::win32::ResetEvent(event_handle); + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW } - f(); - if(!counted) + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename T1> + void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1)), BOOST_THREAD_RV_REF(T1) p1) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f( + thread_detail::decay_copy(boost::forward<T1>(p1)) + ); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2> + void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1),BOOST_THREAD_RV_REF(T2)), BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY { - BOOST_INTERLOCKED_INCREMENT(&flag.count); - counted=true; + f( + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T2>(p2)) + ); } - BOOST_INTERLOCKED_EXCHANGE(&flag.status,function_complete_flag_value); - if(!event_handle && - (::boost::detail::interlocked_read_acquire(&flag.count)>1)) + BOOST_CATCH(...) { - event_handle=detail::create_once_event(mutex_name,&flag); + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW } - if(event_handle) + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) { - ::boost::detail::win32::SetEvent(event_handle); + break; } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2, typename T3> + void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1),BOOST_THREAD_RV_REF(T2)), BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f( + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T2>(p2)), + thread_detail::decay_copy(boost::forward<T3>(p3)) + ); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); break; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + if(!ctx.counted) { - BOOST_INTERLOCKED_EXCHANGE(&flag.status,0); - if(!event_handle) + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) { - event_handle=detail::open_once_event(mutex_name,&flag); + break; } - if(event_handle) + if(!ctx.event_handle) { - ::boost::detail::win32::SetEvent(event_handle); + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; } - throw; // BOOST_NO_EXCEPTIONS protected } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } #endif + template<typename Function> + void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } - if(!counted) + template<typename Function, typename T1> + void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) { BOOST_INTERLOCKED_INCREMENT(&flag.count); - counted=true; - status=::boost::detail::interlocked_read_acquire(&flag.status); - if(status==function_complete_flag_value) + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) { break; } - if(!event_handle) + if(!ctx.event_handle) { - event_handle=detail::create_once_event(mutex_name,&flag); + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); continue; } } BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( - event_handle,::boost::detail::win32::infinite)); + ctx.event_handle,::boost::detail::win32::infinite)); } } + template<typename Function, typename T1, typename T2> + void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T2>(p2)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + template<typename Function, typename T1, typename T2, typename T3> + void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward<Function>(f)), + thread_detail::decay_copy(boost::forward<T1>(p1)), + thread_detail::decay_copy(boost::forward<T2>(p2)), + thread_detail::decay_copy(boost::forward<T3>(p3)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject( + ctx.event_handle,::boost::detail::win32::infinite)); + } + } + +#endif +#endif } #include <boost/config/abi_suffix.hpp> diff --git a/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp index 5144e77..1f0f7f5 100644 --- a/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/recursive_mutex.hpp @@ -12,7 +12,10 @@ #include <boost/thread/win32/basic_recursive_mutex.hpp> #include <boost/thread/exceptions.hpp> -#include <boost/thread/locks.hpp> +#include <boost/thread/detail/delete.hpp> +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include <boost/thread/lock_types.hpp> +#endif #include <boost/config/abi_prefix.hpp> @@ -32,8 +35,10 @@ namespace boost ::boost::detail::basic_recursive_mutex::destroy(); } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS typedef unique_lock<recursive_mutex> scoped_lock; typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock; +#endif }; typedef recursive_mutex recursive_try_mutex; @@ -52,9 +57,11 @@ namespace boost ::boost::detail::basic_recursive_timed_mutex::destroy(); } +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS 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; +#endif }; } diff --git a/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp b/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp index fef2d5b..252174f 100644 --- a/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/shared_mutex.hpp @@ -95,7 +95,7 @@ namespace boost detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX); boost::throw_exception(thread_resource_error()); } - state_data state_={0}; + state_data state_={0,0,0,0,0,0}; state=state_; } @@ -133,15 +133,19 @@ namespace boost void lock_shared() { +#if defined BOOST_THREAD_USES_DATETIME BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel())); +#else + BOOST_VERIFY(try_lock_shared_until(chrono::steady_clock::now())); +#endif } +#if defined BOOST_THREAD_USES_DATETIME template<typename TimeDuration> bool timed_lock_shared(TimeDuration const & relative_time) { return timed_lock_shared(get_system_time()+relative_time); } - bool timed_lock_shared(boost::system_time const& wait_until) { for(;;) @@ -220,6 +224,7 @@ namespace boost BOOST_ASSERT(res==0); } } +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> @@ -378,14 +383,20 @@ namespace boost void lock() { +#if defined BOOST_THREAD_USES_DATETIME BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel())); +#else + BOOST_VERIFY(try_lock_until(chrono::steady_clock::now())); +#endif } +#if defined BOOST_THREAD_USES_DATETIME template<typename TimeDuration> bool timed_lock(TimeDuration const & relative_time) { return timed_lock(get_system_time()+relative_time); } +#endif bool try_lock() { @@ -413,6 +424,7 @@ namespace boost } +#if defined BOOST_THREAD_USES_DATETIME bool timed_lock(boost::system_time const& wait_until) { for(;;) @@ -459,6 +471,7 @@ namespace boost { for(;;) { + bool must_notify = false; state_data new_state=old_state; if(new_state.shared_count || new_state.exclusive) { @@ -467,6 +480,7 @@ namespace boost if(!--new_state.exclusive_waiting) { new_state.exclusive_waiting_blocked=false; + must_notify = true; } } } @@ -476,6 +490,11 @@ namespace boost } state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if (must_notify) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0); + } + if(current_state==old_state) { break; @@ -491,7 +510,7 @@ namespace boost BOOST_ASSERT(wait_res<2); } } - +#endif #ifdef BOOST_THREAD_USES_CHRONO template <class Rep, class Period> bool try_lock_for(const chrono::duration<Rep, Period>& rel_time) @@ -568,6 +587,7 @@ namespace boost { for(;;) { + bool must_notify = false; state_data new_state=old_state; if(new_state.shared_count || new_state.exclusive) { @@ -576,6 +596,7 @@ namespace boost if(!--new_state.exclusive_waiting) { new_state.exclusive_waiting_blocked=false; + must_notify = true; } } } @@ -585,6 +606,10 @@ namespace boost } state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if (must_notify) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0); + } if(current_state==old_state) { break; @@ -724,9 +749,11 @@ namespace boost if(last_reader) { release_waiters(old_state); - } else { - release_waiters(old_state); } + // #7720 + //else { + // release_waiters(old_state); + //} break; } old_state=current_state; diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp index 18fd7cb..1d4f572 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_data.hpp @@ -22,6 +22,11 @@ #include <boost/config/abi_prefix.hpp> +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4251) +#endif + namespace boost { class condition_variable; @@ -67,6 +72,7 @@ namespace boost namespace detail { + struct shared_state_base; struct tss_cleanup_function; struct thread_exit_callback_node; struct tss_data_node @@ -88,24 +94,34 @@ namespace boost { long count; detail::win32::handle_manager thread_handle; - detail::win32::handle_manager interruption_handle; boost::detail::thread_exit_callback_node* thread_exit_callbacks; 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; + typedef std::vector<shared_ptr<shared_state_base> > async_states_t; + async_states_t async_states_; +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + // These data must be at the end so that the access to the other fields doesn't change + // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined + // Another option is to have them always + detail::win32::handle_manager interruption_handle; + bool interruption_enabled; +//#endif 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(), - interruption_enabled(true), id(0), - notify() + notify(), + async_states_() +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + , interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)) + , interruption_enabled(true) +//#endif {} virtual ~thread_data_base(); @@ -122,27 +138,34 @@ namespace boost } } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS void interrupt() { BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0); } - +#endif typedef detail::win32::handle native_handle_type; virtual void run()=0; - void notify_all_at_thread_exit(condition_variable* cv, mutex* m) + virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m) { notify.push_back(std::pair<condition_variable*, mutex*>(cv, m)); } + void make_ready_at_thread_exit(shared_ptr<shared_state_base> as) + { + async_states_.push_back(as); + } + }; + BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr; struct BOOST_SYMBOL_VISIBLE timeout { - unsigned long start; + win32::ticks_type start; uintmax_t milliseconds; bool relative; boost::system_time abs_time; @@ -150,14 +173,14 @@ namespace boost static unsigned long const max_non_infinite_wait=0xfffffffe; timeout(uintmax_t milliseconds_): - start(win32::GetTickCount()), + start(win32::GetTickCount64()()), milliseconds(milliseconds_), relative(true), abs_time(boost::get_system_time()) {} timeout(boost::system_time const& abs_time_): - start(win32::GetTickCount()), + start(win32::GetTickCount64()()), milliseconds(0), relative(false), abs_time(abs_time_) @@ -182,8 +205,8 @@ namespace boost } else if(relative) { - unsigned long const now=win32::GetTickCount(); - unsigned long const elapsed=now-start; + win32::ticks_type const now=win32::GetTickCount64()(); + win32::ticks_type const elapsed=now-start; return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0); } else @@ -235,7 +258,6 @@ namespace boost { interruptible_wait(detail::win32::invalid_handle_value,abs_time); } - template<typename TimeDuration> inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { @@ -251,10 +273,41 @@ namespace boost interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count()); } #endif + namespace no_interruption_point + { + bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time); + inline void non_interruptible_wait(uintmax_t milliseconds) + { + non_interruptible_wait(detail::win32::invalid_handle_value,milliseconds); + } + inline BOOST_SYMBOL_VISIBLE void non_interruptible_wait(system_time const& abs_time) + { + non_interruptible_wait(detail::win32::invalid_handle_value,abs_time); + } + template<typename TimeDuration> + inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) + { + non_interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); + } + inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) + { + non_interruptible_wait(abs_time); + } +#ifdef BOOST_THREAD_USES_CHRONO + inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) + { + non_interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count()); + } +#endif + } } } +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + #include <boost/config/abi_suffix.hpp> #endif 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 9b6d390..610fe32 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_heap_alloc.hpp @@ -5,10 +5,12 @@ #ifndef THREAD_HEAP_ALLOC_HPP #define THREAD_HEAP_ALLOC_HPP #include <new> +#include <boost/thread/detail/config.hpp> #include <boost/thread/win32/thread_primitives.hpp> #include <stdexcept> #include <boost/assert.hpp> #include <boost/throw_exception.hpp> +#include <boost/core/no_exceptions_support.hpp> #if defined( BOOST_USE_WINDOWS_H ) # include <windows.h> @@ -75,20 +77,17 @@ namespace boost inline T* heap_new() { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES @@ -96,159 +95,135 @@ namespace boost inline T* heap_new(A1&& a1) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(static_cast<A1&&>(a1)); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } 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)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2)); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } 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)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2), static_cast<A3&&>(a3)); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } 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)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { 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; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } #else template<typename T,typename A1> inline T* heap_new_impl(A1 a1) { void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(a1); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } 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)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(a1,a2); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } 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)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(a1,a2,a3); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } 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)); -#ifndef BOOST_NO_EXCEPTIONS - try // BOOST_NO_EXCEPTIONS protected -#endif + BOOST_TRY { T* const data=new (heap_memory) T(a1,a2,a3,a4); return data; } -#ifndef BOOST_NO_EXCEPTIONS - catch(...) // BOOST_NO_EXCEPTIONS protected + BOOST_CATCH(...) { free_raw_heap_memory(heap_memory); - throw; // BOOST_NO_EXCEPTIONS protected + BOOST_RETHROW } -#endif + BOOST_CATCH_END } diff --git a/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp b/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp index c0dba11..fcf59b3 100644 --- a/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp +++ b/3rdParty/Boost/src/boost/thread/win32/thread_primitives.hpp @@ -15,6 +15,7 @@ #include <boost/assert.hpp> #include <boost/thread/exceptions.hpp> #include <boost/detail/interlocked.hpp> +//#include <boost/detail/winapi/synchronization.hpp> #include <algorithm> #if defined( BOOST_USE_WINDOWS_H ) @@ -26,13 +27,14 @@ namespace boost { namespace win32 { - typedef ULONG_PTR ulong_ptr; typedef HANDLE handle; unsigned const infinite=INFINITE; unsigned const timeout=WAIT_TIMEOUT; handle const invalid_handle_value=INVALID_HANDLE_VALUE; unsigned const event_modify_state=EVENT_MODIFY_STATE; unsigned const synchronize=SYNCHRONIZE; + unsigned const wait_abandoned=WAIT_ABANDONED; + # ifdef BOOST_NO_ANSI_APIS using ::CreateMutexW; @@ -60,7 +62,6 @@ namespace boost using ::SleepEx; using ::Sleep; using ::QueueUserAPC; - using ::GetTickCount; } } } @@ -88,13 +89,13 @@ typedef void* HANDLE; # endif # endif + namespace boost { namespace detail { namespace win32 { - # ifdef _WIN64 typedef unsigned __int64 ulong_ptr; # else @@ -106,6 +107,7 @@ namespace boost handle const invalid_handle_value=(handle)(-1); unsigned const event_modify_state=2; unsigned const synchronize=0x100000u; + unsigned const wait_abandoned=0x00000080u; extern "C" { @@ -132,8 +134,6 @@ namespace boost typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr); __declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr); - __declspec(dllimport) unsigned long __stdcall GetTickCount(); - # ifndef UNDER_CE __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId(); __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(); @@ -165,7 +165,88 @@ namespace boost { namespace win32 { - enum event_type + typedef unsigned __int64 ticks_type; + namespace detail { typedef int (__stdcall *farproc_t)(); typedef ticks_type (__stdcall *gettickcount64_t)(); } + extern "C" + { + __declspec(dllimport) detail::farproc_t __stdcall GetProcAddress(void *, const char *); +#if !defined(BOOST_NO_ANSI_APIS) + __declspec(dllimport) void * __stdcall GetModuleHandleA(const char *); +#else + __declspec(dllimport) void * __stdcall GetModuleHandleW(const wchar_t *); +#endif + int __stdcall GetTickCount(); + long _InterlockedCompareExchange(long volatile *, long, long); +#pragma intrinsic(_InterlockedCompareExchange) + } + // Borrowed from https://stackoverflow.com/questions/8211820/userland-interrupt-timer-access-such-as-via-kequeryinterrupttime-or-similar + inline ticks_type __stdcall GetTickCount64emulation() + { + static volatile long count = 0xFFFFFFFF; + unsigned long previous_count, current_tick32, previous_count_zone, current_tick32_zone; + ticks_type current_tick64; + + previous_count = (unsigned long) _InterlockedCompareExchange(&count, 0, 0); + current_tick32 = GetTickCount(); + + if(previous_count == 0xFFFFFFFF) + { + // count has never been written + unsigned long initial_count; + initial_count = current_tick32 >> 28; + previous_count = (unsigned long) _InterlockedCompareExchange(&count, initial_count, 0xFFFFFFFF); + + current_tick64 = initial_count; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + previous_count_zone = previous_count & 15; + current_tick32_zone = current_tick32 >> 28; + + if(current_tick32_zone == previous_count_zone) + { + // The top four bits of the 32-bit tick count haven't changed since count was last written. + current_tick64 = previous_count; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + if(current_tick32_zone == previous_count_zone + 1 || (current_tick32_zone == 0 && previous_count_zone == 15)) + { + // The top four bits of the 32-bit tick count have been incremented since count was last written. + _InterlockedCompareExchange(&count, previous_count + 1, previous_count); + current_tick64 = previous_count + 1; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + // Oops, we weren't called often enough, we're stuck + return 0xFFFFFFFF; + } + inline detail::gettickcount64_t GetTickCount64() + { + static detail::gettickcount64_t gettickcount64impl; + if(gettickcount64impl) + return gettickcount64impl; + detail::farproc_t addr=GetProcAddress( +#if !defined(BOOST_NO_ANSI_APIS) + GetModuleHandleA("KERNEL32.DLL"), +#else + GetModuleHandleW(L"KERNEL32.DLL"), +#endif + "GetTickCount64"); + if(addr) + gettickcount64impl=(detail::gettickcount64_t) addr; + else + gettickcount64impl=&GetTickCount64emulation; + return gettickcount64impl; + } + + enum event_type { auto_reset_event=false, manual_reset_event=true @@ -232,7 +313,7 @@ namespace boost BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0); } - class handle_manager + class BOOST_THREAD_DECL handle_manager { private: handle handle_to_manage; diff --git a/3rdParty/Boost/src/boost/thread/xtime.hpp b/3rdParty/Boost/src/boost/thread/xtime.hpp index 1ca996f..9c6a359 100644 --- a/3rdParty/Boost/src/boost/thread/xtime.hpp +++ b/3rdParty/Boost/src/boost/thread/xtime.hpp @@ -9,6 +9,7 @@ #define BOOST_XTIME_WEK070601_HPP #include <boost/thread/detail/config.hpp> +#if defined BOOST_THREAD_USES_DATETIME #include <boost/cstdint.hpp> #include <boost/thread/thread_time.hpp> @@ -88,5 +89,5 @@ inline int xtime_cmp(const xtime& xt1, const xtime& xt2) } // namespace boost #include <boost/config/abi_suffix.hpp> - +#endif #endif //BOOST_XTIME_WEK070601_HPP |