New upstream version 8.1.0

This commit is contained in:
geos_one
2025-08-10 01:34:16 +02:00
commit c891bb7105
4398 changed files with 838833 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
#ifndef BOOST_THREAD_CONDITION_VARIABLE_HPP
#define BOOST_THREAD_CONDITION_VARIABLE_HPP
// condition_variable.hpp
//
// (C) Copyright 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/condition_variable.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/condition_variable.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#endif

View File

@@ -0,0 +1,49 @@
// 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_FUNCTIONAL_HPP
#define BOOST_CSBL_FUNCTIONAL_HPP
#include <boost/config.hpp>
#include <functional>
#if defined BOOST_THREAD_USES_BOOST_FUNCTIONAL || defined BOOST_NO_CXX11_HDR_FUNCTIONAL || defined BOOST_NO_CXX11_RVALUE_REFERENCES
#ifndef BOOST_THREAD_USES_BOOST_FUNCTIONAL
#define BOOST_THREAD_USES_BOOST_FUNCTIONAL
#endif
#include <boost/function.hpp>
#endif
namespace boost
{
namespace csbl
{
#if defined BOOST_THREAD_USES_BOOST_FUNCTIONAL
using ::boost::function;
#else
// D.8.1, base (deprecated):
// 20.9.3, reference_wrapper:
// 20.9.4, arithmetic operations:
// 20.9.5, comparisons:
// 20.9.6, logical operations:
// 20.9.7, bitwise operations:
// 20.9.8, negators:
// 20.9.9, bind:
// D.9, binders (deprecated):
// D.8.2.1, adaptors (deprecated):
// D.8.2.2, adaptors (deprecated):
// 20.9.10, member function adaptors:
// 20.9.11 polymorphic function wrappers:
using ::std::function;
// 20.9.12, hash function primary template:
#endif
}
}
#endif // header

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,42 @@
// Copyright (C) 2014 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)
//
// 2014/10 Vicente J. Botet Escriba
// Creation.
#ifndef BOOST_CSBL_MEMORY_SHARED_PTR_HPP
#define BOOST_CSBL_MEMORY_SHARED_PTR_HPP
#include <boost/thread/csbl/memory/config.hpp>
#if defined BOOST_NO_CXX11_SMART_PTR
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
namespace boost
{
namespace csbl
{
using ::boost::shared_ptr;
using ::boost::make_shared;
}
}
#else
#include <boost/shared_ptr.hpp>
namespace boost
{
namespace csbl
{
using std::shared_ptr;
using std::make_shared;
}
}
#endif
#endif // header

View File

@@ -0,0 +1,28 @@
// Copyright (C) 2013-2014 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 using interprocess::unique_ptr.
// 2014/09 Vicente J. Botet Escriba
// Adaptation to movelib::unique_ptr
#ifndef BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
#define BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP
#include <boost/thread/csbl/memory/config.hpp>
#include <boost/move/unique_ptr.hpp>
#include <boost/move/make_unique.hpp>
namespace boost
{
namespace csbl
{
using ::boost::movelib::unique_ptr;
using ::boost::movelib::make_unique;
}
}
#endif // header

View File

@@ -0,0 +1,49 @@
// 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;
using ::boost::make_tuple;
//using ::boost::tuple_size;
#else
// 20.4.2, class template tuple:
using ::std::tuple;
using ::std::get;
using ::std::make_tuple;
using ::std::tuple_size;
// 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

View File

@@ -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_RVALUE_REFERENCES || defined BOOST_MSVC
#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

View File

@@ -0,0 +1,26 @@
// cv_status.hpp
//
// Copyright (C) 2011 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_CV_STATUS_HPP
#define BOOST_THREAD_CV_STATUS_HPP
#include <boost/core/scoped_enum.hpp>
namespace boost
{
// enum class cv_status;
BOOST_SCOPED_ENUM_DECLARE_BEGIN(cv_status)
{
no_timeout,
timeout
}
BOOST_SCOPED_ENUM_DECLARE_END(cv_status)
}
#endif // header

View File

@@ -0,0 +1,465 @@
// Copyright (C) 2001-2003
// William E. Kempf
// 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)
#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP
#define BOOST_THREAD_CONFIG_WEK01032003_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/thread/detail/platform.hpp>
//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS
// ATTRIBUTE_MAY_ALIAS
#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_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
#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
#define BOOST_THREAD_DONT_USE_MOVE
#endif
// This compiler doesn't support Boost.Container Allocators files
#if defined __SUNPRO_CC \
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#endif
#if defined _WIN32_WCE && _WIN32_WCE==0x501 \
&& ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS
#endif
#if defined BOOST_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
/// 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 && 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
#define BOOST_THREAD_USES_CHRONO
#endif
#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
// PROVIDE_PROMISE_LAZY
#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY \
&& ! defined BOOST_THREAD_PROVIDES_PROMISE_LAZY
#define BOOST_THREAD_PROVIDES_PROMISE_LAZY
#endif
// 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
// 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_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
// USE_MOVE
#if ! defined BOOST_THREAD_DONT_USE_MOVE \
&& ! defined BOOST_THREAD_USES_MOVE
#define BOOST_THREAD_USES_MOVE
#endif
#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_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
// 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_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
#if ! defined BOOST_THREAD_PROVIDES_THREAD_EQ
#define BOOST_THREAD_PROVIDES_THREAD_EQ
#endif
#endif
//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_THREAD_USES_MOVE
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_FUTURE_USES_OPTIONAL
#endif
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
# pragma warn -8008 // Condition always true/false
# pragma warn -8080 // Identifier declared but never used
# pragma warn -8057 // Parameter never used
# pragma warn -8066 // Unreachable code
#endif
#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
# define BOOST_THREAD_DYN_LINK
#endif
// 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
# if !defined(BOOST_THREAD_USE_DLL)
# define BOOST_THREAD_USE_DLL
# endif
#endif
#if defined(BOOST_THREAD_BUILD_DLL) //Build dll
#elif defined(BOOST_THREAD_BUILD_LIB) //Build lib
#elif defined(BOOST_THREAD_USE_DLL) //Use dll
#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) \
|| 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
//For compilers not yet supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads dll
# define BOOST_THREAD_USE_DLL
# endif
# else
# define BOOST_THREAD_USE_LIB
# endif
#endif
#if defined(BOOST_HAS_DECLSPEC)
# if defined(BOOST_THREAD_BUILD_DLL) //Build dll
# define BOOST_THREAD_DECL BOOST_SYMBOL_EXPORT
//# define BOOST_THREAD_DECL __declspec(dllexport)
# elif defined(BOOST_THREAD_USE_DLL) //Use dll
# define BOOST_THREAD_DECL BOOST_SYMBOL_IMPORT
//# define BOOST_THREAD_DECL __declspec(dllimport)
# else
# define BOOST_THREAD_DECL
# endif
#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
# define BOOST_THREAD_DECL BOOST_SYMBOL_VISIBLE
#else
# define BOOST_THREAD_DECL
#endif // BOOST_HAS_DECLSPEC
//
// Automatically link to the correct build variant where possible.
//
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL) && !defined(BOOST_THREAD_BUILD_LIB)
//
// Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#if defined(BOOST_THREAD_USE_DLL)
# define BOOST_DYN_LINK
#endif
//
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#if defined(BOOST_THREAD_LIB_NAME)
# define BOOST_LIB_NAME BOOST_THREAD_LIB_NAME
#else
# define BOOST_LIB_NAME boost_thread
#endif
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif // BOOST_THREAD_CONFIG_WEK1032003_HPP
// Change Log:
// 22 Jan 05 Roland Schwarz (speedsnail)
// Usage of BOOST_HAS_DECLSPEC macro.
// Default again is static lib usage.
// BOOST_DYN_LINK only defined when autolink included.

View File

@@ -0,0 +1,58 @@
// Copyright (C) 2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_DETAIL_DELETE_HPP
#define BOOST_THREAD_DETAIL_DELETE_HPP
#include <boost/config.hpp>
/**
* BOOST_THREAD_DELETE_COPY_CTOR deletes the copy constructor when the compiler supports it or
* makes it private.
*
* BOOST_THREAD_DELETE_COPY_ASSIGN deletes the copy assignment when the compiler supports it or
* makes it private.
*/
#if ! defined BOOST_NO_CXX11_DELETED_FUNCTIONS && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
CLASS(CLASS const&) = delete; \
#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \
CLASS& operator=(CLASS const&) = delete;
#else // BOOST_NO_CXX11_DELETED_FUNCTIONS
#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&); \
public:
#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \
private: \
CLASS& operator=(CLASS&); \
public:
#endif
#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS
/**
* BOOST_THREAD_NO_COPYABLE deletes the copy constructor and assignment when the compiler supports it or
* makes them private.
*/
#define BOOST_THREAD_NO_COPYABLE(CLASS) \
BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \
BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS)
#endif // BOOST_THREAD_DETAIL_DELETE_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,762 @@
// 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_INVOKER_HPP
#define BOOST_THREAD_DETAIL_INVOKER_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_COPYABLE_AND_MOVABLE( 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_))
{}
BOOST_SYMBOL_VISIBLE
invoker( const invoker& f) : f_(f.f_)
{}
BOOST_SYMBOL_VISIBLE
invoker& operator=(BOOST_THREAD_RV_REF(invoker) f)
{
if (this != &f)
{
f_ = boost::move(BOOST_THREAD_RV(f).f_);
}
return *this;
}
BOOST_SYMBOL_VISIBLE
invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f)
{
if (this != &f)
{
f_ = f.f_;
}
return *this;
}
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 detail::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_COPYABLE_AND_MOVABLE( 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 detail::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 && defined(BOOST_THREAD_PROVIDES_INVOKE)
#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_COPYABLE_AND_MOVABLE(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_RV_REF(invoker) x) \
: fp_(boost::move(x.fp_)) \
BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \
{} \
\
result_type operator()() { \
return detail::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_COPYABLE_AND_MOVABLE(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_RV_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_COPYABLE_AND_MOVABLE(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_RV_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 detail::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_COPYABLE_AND_MOVABLE(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_RV_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 detail::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_COPYABLE_AND_MOVABLE(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_RV_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 detail::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_COPYABLE_AND_MOVABLE(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_RV_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 detail::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_COPYABLE_AND_MOVABLE(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_RV_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 detail::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_COPYABLE_AND_MOVABLE(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_RV_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 detail::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_COPYABLE_AND_MOVABLE(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_RV_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 detail::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_COPYABLE_AND_MOVABLE(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_RV_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 detail::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_COPYABLE_AND_MOVABLE(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_RV_REF(invoker) f)
: fp_(boost::move(BOOST_THREAD_RV(f).fp))
, v0_(boost::move(BOOST_THREAD_RV(f).v0_))
{}
result_type operator()()
{
return detail::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_RV_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_RV_REF(invoker) f)
: fp_(f.fp_)
{}
result_type operator()()
{
return fp_();
}
};
#endif
#endif
}
}
#include <boost/thread/detail/variadic_footer.hpp>
#endif // header

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,48 @@
//////////////////////////////////////////////////////////////////////////////
//
// 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_MEMORY_HPP
#define BOOST_THREAD_DETAIL_MEMORY_HPP
#include <boost/config.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
{
namespace thread_detail
{
template <class _Alloc>
class allocator_destructor
{
typedef csbl::allocator_traits<_Alloc> alloc_traits;
public:
typedef typename alloc_traits::pointer pointer;
typedef typename alloc_traits::size_type size_type;
private:
_Alloc alloc_;
size_type s_;
public:
allocator_destructor(_Alloc& a, size_type s)BOOST_NOEXCEPT
: alloc_(a), s_(s)
{}
void operator()(pointer p)BOOST_NOEXCEPT
{
alloc_traits::destroy(alloc_, p);
alloc_traits::deallocate(alloc_, p, s_);
}
};
} //namespace thread_detail
}
#endif // BOOST_THREAD_DETAIL_MEMORY_HPP

View File

@@ -0,0 +1,374 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#ifndef BOOST_THREAD_MOVE_HPP
#define BOOST_THREAD_MOVE_HPP
#include <boost/thread/detail/config.hpp>
#ifndef BOOST_NO_SFINAE
#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/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 enable_move_utility_emulation_dummy_specialization;
template<typename T>
struct thread_move_t
{
T& t;
explicit thread_move_t(T& t_):
t(t_)
{}
T& operator*() const
{
return t;
}
T* operator->() const
{
return &t;
}
private:
void operator=(thread_move_t&);
};
}
#if !defined BOOST_THREAD_USES_MOVE
#ifndef BOOST_NO_SFINAE
template<typename T>
typename enable_if<boost::is_convertible<T&,boost::detail::thread_move_t<T> >, boost::detail::thread_move_t<T> >::type move(T& t)
{
return boost::detail::thread_move_t<T>(t);
}
#endif
template<typename T>
boost::detail::thread_move_t<T> move(boost::detail::thread_move_t<T> t)
{
return t;
}
#endif //#if !defined BOOST_THREAD_USES_MOVE
}
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#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
#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE
#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE)
#define BOOST_THREAD_DCL_MOVABLE(TYPE)
#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \
namespace detail { \
template <typename T> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
namespace detail { \
template <typename T1, typename T2> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: integral_constant<bool, false> \
{}; \
}
#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_MSVC
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#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
#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE
#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE)
#define BOOST_THREAD_DCL_MOVABLE(TYPE)
#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \
namespace detail { \
template <typename T> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
namespace detail { \
template <typename T1, typename T2> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: integral_constant<bool, false> \
{}; \
}
#else
#if defined BOOST_THREAD_USES_MOVE
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE)
#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
#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE)
#define BOOST_THREAD_DCL_MOVABLE(TYPE)
#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \
namespace detail { \
template <typename T> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
namespace detail { \
template <typename T1, typename T2> \
struct enable_move_utility_emulation_dummy_specialization<
#define BOOST_THREAD_DCL_MOVABLE_END > \
: integral_constant<bool, false> \
{}; \
}
#else
#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) const TYPE&
#define BOOST_THREAD_RV_REF(TYPE) boost::detail::thread_move_t< TYPE >
#define BOOST_THREAD_RV_REF_BEG boost::detail::thread_move_t<
#define BOOST_THREAD_RV_REF_END >
#define BOOST_THREAD_RV(V) (*V)
#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE)
#define BOOST_THREAD_DCL_MOVABLE(TYPE) \
template <> \
struct enable_move_utility_emulation< TYPE > \
{ \
static const bool value = false; \
};
#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \
template <typename T> \
struct enable_move_utility_emulation<
#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \
template <typename T1, typename T2> \
struct enable_move_utility_emulation<
#define BOOST_THREAD_DCL_MOVABLE_END > \
{ \
static const bool value = false; \
};
#endif
namespace boost
{
namespace detail
{
template <typename T>
BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type)
make_rv_ref(T v) BOOST_NOEXCEPT
{
return (BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v);
}
// template <typename T>
// BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type)
// make_rv_ref(T &v) BOOST_NOEXCEPT
// {
// return (BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v);
// }
// template <typename T>
// const BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type)
// make_rv_ref(T const&v) BOOST_NOEXCEPT
// {
// return (const BOOST_THREAD_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v);
// }
}
}
#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE.move()
//#define BOOST_THREAD_MAKE_RV_REF(RVALUE) boost::detail::make_rv_ref(RVALUE)
#endif
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_THREAD_MOVABLE(TYPE)
#define BOOST_THREAD_COPYABLE(TYPE)
#else
#if defined BOOST_THREAD_USES_MOVE
#define BOOST_THREAD_MOVABLE(TYPE) \
::boost::rv<TYPE>& move() BOOST_NOEXCEPT \
{ \
return *static_cast< ::boost::rv<TYPE>* >(this); \
} \
const ::boost::rv<TYPE>& move() const BOOST_NOEXCEPT \
{ \
return *static_cast<const ::boost::rv<TYPE>* >(this); \
} \
operator ::boost::rv<TYPE>&() \
{ \
return *static_cast< ::boost::rv<TYPE>* >(this); \
} \
operator const ::boost::rv<TYPE>&() const \
{ \
return *static_cast<const ::boost::rv<TYPE>* >(this); \
}\
#define BOOST_THREAD_COPYABLE(TYPE) \
TYPE& operator=(TYPE &t)\
{ this->operator=(static_cast<const ::boost::rv<TYPE> &>(const_cast<const TYPE &>(t))); return *this;}
#else
#define BOOST_THREAD_MOVABLE(TYPE) \
operator ::boost::detail::thread_move_t<TYPE>() BOOST_NOEXCEPT \
{ \
return move(); \
} \
::boost::detail::thread_move_t<TYPE> move() BOOST_NOEXCEPT \
{ \
::boost::detail::thread_move_t<TYPE> x(*this); \
return x; \
} \
#define BOOST_THREAD_COPYABLE(TYPE)
#endif
#endif
#define BOOST_THREAD_MOVABLE_ONLY(TYPE) \
BOOST_THREAD_NO_COPYABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
typedef int boost_move_no_copy_constructor_or_assign; \
#define BOOST_THREAD_COPYABLE_AND_MOVABLE(TYPE) \
BOOST_THREAD_COPYABLE(TYPE) \
BOOST_THREAD_MOVABLE(TYPE) \
namespace boost
{
namespace thread_detail
{
#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES
#elif defined BOOST_THREAD_USES_MOVE
template <class T>
struct is_rv
: ::boost::move_detail::is_rv<T>
{};
#else
template <class T>
struct is_rv
: ::boost::integral_constant<bool, false>
{};
template <class T>
struct is_rv< ::boost::detail::thread_move_t<T> >
: ::boost::integral_constant<bool, true>
{};
template <class T>
struct is_rv< const ::boost::detail::thread_move_t<T> >
: ::boost::integral_constant<bool, true>
{};
#endif
#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>
#endif

View File

@@ -0,0 +1,234 @@
// 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/thread/csbl/memory/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()
{
}
};
csbl::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_COPYABLE_AND_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 :
#if defined BOOST_NO_CXX11_SMART_PTR
impl(BOOST_THREAD_RV(other).impl)
{
BOOST_THREAD_RV(other).impl.reset();
}
#else
impl(boost::move(other.impl))
{
}
#endif
~nullary_function()
{
}
nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
{
impl=other.impl;
return *this;
}
nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
{
#if defined BOOST_NO_CXX11_SMART_PTR
impl=BOOST_THREAD_RV(other).impl;
BOOST_THREAD_RV(other).impl.reset();
#else
impl = boost::move(other.impl);
#endif
return *this;
}
void operator()()
{ if (impl) impl->call();}
};
template <typename R>
class nullary_function<R()>
{
struct impl_base
{
virtual R call()=0;
virtual ~impl_base()
{
}
};
csbl::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_COPYABLE_AND_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 :
#if defined BOOST_NO_CXX11_SMART_PTR
impl(BOOST_THREAD_RV(other).impl)
{
BOOST_THREAD_RV(other).impl.reset();
}
#else
impl(boost::move(other.impl))
{
}
#endif
nullary_function()
: impl()
{
}
~nullary_function()
{
}
nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
{
impl=other.impl;
return *this;
}
nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
{
#if defined BOOST_NO_CXX11_SMART_PTR
impl=BOOST_THREAD_RV(other).impl;
BOOST_THREAD_RV(other).impl.reset();
#else
impl = boost::move(other.impl);
#endif
return *this;
}
R operator()()
{ if (impl) return impl->call(); else return R();}
};
}
BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END
}
#endif // header

View File

@@ -0,0 +1,73 @@
// Copyright 2006 Roland Schwarz.
// (C) Copyright 2007 Anthony Williams
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06040501_HPP
#define BOOST_THREAD_RS06040501_HPP
// fetch compiler and platform configuration
#include <boost/config.hpp>
// insist on threading support being available:
#include <boost/config/requires_threads.hpp>
// choose platform
#if defined(linux) || defined(__linux) || defined(__linux__)
# define BOOST_THREAD_LINUX
//# define BOOST_THREAD_WAIT_BUG boost::posix_time::microseconds(100000)
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
# define BOOST_THREAD_BSD
#elif defined(sun) || defined(__sun)
# define BOOST_THREAD_SOLARIS
#elif defined(__sgi)
# define BOOST_THREAD_IRIX
#elif defined(__hpux)
# define BOOST_THREAD_HPUX
#elif defined(__CYGWIN__)
# define BOOST_THREAD_CYGWIN
#elif (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && !defined(BOOST_DISABLE_WIN32)
# define BOOST_THREAD_WIN32
#elif defined(__BEOS__)
# define BOOST_THREAD_BEOS
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
# define BOOST_THREAD_MACOS
//# define BOOST_THREAD_WAIT_BUG boost::posix_time::microseconds(1000)
#elif defined(__IBMCPP__) || defined(_AIX)
# define BOOST_THREAD_AIX
#elif defined(__amigaos__)
# define BOOST_THREAD_AMIGAOS
#elif defined(__QNXNTO__)
# define BOOST_THREAD_QNXNTO
#elif defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE)
# if defined(BOOST_HAS_PTHREADS) && !defined(BOOST_THREAD_POSIX)
# define BOOST_THREAD_POSIX
# endif
#endif
// For every supported platform add a new entry into the dispatch table below.
// BOOST_THREAD_POSIX is tested first, so on platforms where posix and native
// threading is available, the user may choose, by defining BOOST_THREAD_POSIX
// in her source. If a platform is known to support pthreads and no native
// port of boost_thread is available just specify "pthread" in the
// dispatcher table. If there is no entry for a platform but pthreads is
// available on the platform, pthread is choosen as default. If nothing is
// available the preprocessor will fail with a diagnostic message.
#if defined(BOOST_THREAD_POSIX)
# define BOOST_THREAD_PLATFORM_PTHREAD
#else
# if defined(BOOST_THREAD_WIN32)
# define BOOST_THREAD_PLATFORM_WIN32
# elif defined(BOOST_HAS_PTHREADS)
# define BOOST_THREAD_PLATFORM_PTHREAD
# else
# error "Sorry, no boost threads are available for this platform."
# endif
#endif
#endif // BOOST_THREAD_RS06040501_HPP

View File

@@ -0,0 +1,873 @@
#ifndef BOOST_THREAD_THREAD_COMMON_HPP
#define BOOST_THREAD_THREAD_COMMON_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-2010 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/predef/platform.h>
#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/core/ref.hpp>
#include <boost/cstdint.hpp>
#include <boost/bind.hpp>
#include <stdlib.h>
#include <memory>
#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>
#include <boost/type_traits/decay.hpp>
#include <boost/functional/hash.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
#include <tuple>
#endif
#include <boost/config/abi_prefix.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4251)
#endif
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...>)
{
detail::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
{
public:
BOOST_THREAD_NO_COPYABLE(thread_data)
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
thread_data(BOOST_THREAD_RV_REF(F) f_):
f(boost::forward<F>(f_))
{}
// This overloading must be removed if we want the packaged_task's tests to pass.
// thread_data(F& f_):
// f(f_)
// {}
#else
thread_data(BOOST_THREAD_RV_REF(F) f_):
f(f_)
{}
thread_data(F f_):
f(f_)
{}
#endif
//thread_data() {}
void run()
{
f();
}
private:
F f;
};
template<typename F>
class thread_data<boost::reference_wrapper<F> >:
public detail::thread_data_base
{
private:
F& f;
public:
BOOST_THREAD_NO_COPYABLE(thread_data)
thread_data(boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
}
};
template<typename F>
class thread_data<const boost::reference_wrapper<F> >:
public detail::thread_data_base
{
private:
F& f;
public:
BOOST_THREAD_NO_COPYABLE(thread_data)
thread_data(const boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
}
};
#endif
}
class BOOST_THREAD_DECL thread
{
public:
typedef thread_attributes attributes;
BOOST_THREAD_MOVABLE_ONLY(thread)
private:
struct dummy;
void release_handle();
detail::thread_data_ptr thread_info;
private:
bool start_thread_noexcept();
bool start_thread_noexcept(const attributes& attr);
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(*)()> >(
boost::forward<void(*)()>(f)));
}
#else
template<typename 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));
}
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<F> >(f));
}
#endif
public:
#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
thread(const volatile thread&);
#endif
#endif
thread() BOOST_NOEXCEPT;
~thread()
{
#if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
if (joinable()) {
std::terminate();
}
#else
detach();
#endif
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <
class F
>
explicit thread(BOOST_THREAD_RV_REF(F) f
//, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
):
thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
{
start_thread();
}
template <
class 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);
}
#else
#ifdef BOOST_NO_SFINAE
template <class F>
explicit thread(F f):
thread_info(make_thread_info(f))
{
start_thread();
}
template <class F>
thread(attributes const& attrs, F f):
thread_info(make_thread_info(f))
{
start_thread(attrs);
}
#else
template <class F>
explicit thread(F f
, typename disable_if_c<
boost::thread_detail::is_rv<F>::value // todo ass a thread_detail::is_rv
//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 const& attrs, F f
, typename disable_if<boost::thread_detail::is_rv<F>, dummy* >::type=0
//, 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);
}
#endif
template <class F>
explicit thread(BOOST_THREAD_RV_REF(F) f
, typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
):
#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 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) BOOST_NOEXCEPT
{
thread_info=BOOST_THREAD_RV(x).thread_info;
BOOST_THREAD_RV(x).thread_info.reset();
}
#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
thread& operator=(thread x)
{
swap(x);
return *this;
}
#endif
#endif
thread& operator=(BOOST_THREAD_RV_REF(thread) other) BOOST_NOEXCEPT
{
#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
if (joinable()) std::terminate();
#else
detach();
#endif
thread_info=BOOST_THREAD_RV(other).thread_info;
BOOST_THREAD_RV(other).thread_info.reset();
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::thread_detail::is_convertible<F&,thread_attributes >, dummy* >::type=0):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
{
start_thread();
}
template <class F,class A1,class A2>
thread(F f,A1 a1,A2 a2):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2)))
{
start_thread();
}
template <class F,class A1,class A2,class A3>
thread(F f,A1 a1,A2 a2,A3 a3):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5,class A6>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9)))
{
start_thread();
}
#endif
void swap(thread& x) BOOST_NOEXCEPT
{
thread_info.swap(x.thread_info);
}
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;
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;
bool joined= false;
do {
system_clock::time_point s_now = system_clock::now();
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)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
#endif
#if defined(BOOST_THREAD_PLATFORM_WIN32)
private:
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)
{
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
return do_try_join_until(rel_time.count());
}
#endif
#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::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 = boost::detail::to_timespec(d);
return do_try_join_until(ts);
}
#endif
#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_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();
}
static inline void sleep(const system_time& xt)
{
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
{
return lhs.swap(rhs);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
inline thread&& move(thread& t) BOOST_NOEXCEPT
{
return static_cast<thread&&>(t);
}
#endif
BOOST_THREAD_DCL_MOVABLE(thread)
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
{
private:
friend inline
std::size_t
hash_value(const thread::id &v)
{
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
return hash_value(v.thread_data);
#else
return hash_value(v.thread_data.get());
#endif
}
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
#if defined(BOOST_THREAD_PLATFORM_WIN32)
typedef unsigned int data;
#else
typedef thread::native_handle_type data;
#endif
#else
typedef detail::thread_data_ptr data;
#endif
data thread_data;
id(data thread_data_):
thread_data(thread_data_)
{}
friend class thread;
friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT;
public:
id() BOOST_NOEXCEPT:
#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
thread_data(0)
#else
thread_data()
#endif
{}
id(const id& other) BOOST_NOEXCEPT :
thread_data(other.thread_data)
{}
bool operator==(const id& y) const BOOST_NOEXCEPT
{
return thread_data==y.thread_data;
}
bool operator!=(const id& y) const BOOST_NOEXCEPT
{
return thread_data!=y.thread_data;
}
bool operator<(const id& y) const BOOST_NOEXCEPT
{
return thread_data<y.thread_data;
}
bool operator>(const id& y) const BOOST_NOEXCEPT
{
return y.thread_data<thread_data;
}
bool operator<=(const id& y) const BOOST_NOEXCEPT
{
return !(y.thread_data<thread_data);
}
bool operator>=(const id& y) const BOOST_NOEXCEPT
{
return !(thread_data<y.thread_data);
}
#ifndef BOOST_NO_IOSTREAM
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
template<class charT, class traits>
friend BOOST_SYMBOL_VISIBLE
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const id& x)
{
if(x.thread_data)
{
io::ios_flags_saver ifs( os );
return os<< std::hex << x.thread_data;
}
else
{
return os<<"{Not-any-thread}";
}
}
#else
template<class charT, class traits>
BOOST_SYMBOL_VISIBLE
std::basic_ostream<charT, traits>&
print(std::basic_ostream<charT, traits>& os) const
{
if(thread_data)
{
io::ios_flags_saver ifs( os );
return os<< std::hex << thread_data;
}
else
{
return os<<"{Not-any-thread}";
}
}
#endif
#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
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const thread::id& x)
{
return x.print(os);
}
#endif
#if defined BOOST_THREAD_PROVIDES_THREAD_EQ
inline bool thread::operator==(const thread& other) const
{
return get_id()==other.get_id();
}
inline bool thread::operator!=(const thread& other) const
{
return get_id()!=other.get_id();
}
#endif
namespace detail
{
struct thread_exit_function_base
{
virtual ~thread_exit_function_base()
{}
virtual void operator()()=0;
};
template<typename F>
struct thread_exit_function:
thread_exit_function_base
{
F f;
thread_exit_function(F f_):
f(f_)
{}
void operator()()
{
f();
}
};
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
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
{
template<typename F>
void at_thread_exit(F f)
{
detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f);
detail::add_thread_exit_function(thread_exit_func);
}
}
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,23 @@
#ifndef BOOST_THREAD_THREAD_HEAP_ALLOC_HPP
#define BOOST_THREAD_THREAD_HEAP_ALLOC_HPP
// thread_heap_alloc.hpp
//
// (C) Copyright 2008 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/thread_heap_alloc.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/thread_heap_alloc.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#endif

View File

@@ -0,0 +1,39 @@
#ifndef BOOST_THREAD_DETAIL_THREAD_INTERRUPTION_HPP
#define BOOST_THREAD_DETAIL_THREAD_INTERRUPTION_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-9 Anthony Williams
// (C) Copyright 2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
namespace boost
{
namespace this_thread
{
class BOOST_THREAD_DECL disable_interruption
{
bool interruption_was_enabled;
friend class restore_interruption;
public:
BOOST_THREAD_NO_COPYABLE(disable_interruption)
disable_interruption() BOOST_NOEXCEPT;
~disable_interruption() BOOST_NOEXCEPT;
};
class BOOST_THREAD_DECL restore_interruption
{
public:
BOOST_THREAD_NO_COPYABLE(restore_interruption)
explicit restore_interruption(disable_interruption& d) BOOST_NOEXCEPT;
~restore_interruption() BOOST_NOEXCEPT;
};
}
}
#endif // BOOST_THREAD_PROVIDES_INTERRUPTIONS
#endif // header

View File

@@ -0,0 +1,65 @@
// (C) Copyright Michael Glassford 2004.
// Use, modification and distribution are subject to 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_TLS_HOOKS_HPP)
#define BOOST_TLS_HOOKS_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/config/abi_prefix.hpp>
#if defined(BOOST_HAS_WINTHREADS)
namespace boost
{
BOOST_THREAD_DECL void __cdecl on_process_enter(void);
//Function to be called when the exe or dll
//that uses Boost.Threads first starts
//or is first loaded.
//Should be called only before the first call to
//on_thread_enter().
//Called automatically by Boost.Threads when
//a method for doing so has been discovered.
//May be omitted; may be called multiple times.
BOOST_THREAD_DECL void __cdecl on_process_exit(void);
//Function to be called when the exe or dll
//that uses Boost.Threads first starts
//or is first loaded.
//Should be called only after the last call to
//on_exit_thread().
//Called automatically by Boost.Threads when
//a method for doing so has been discovered.
//Must not be omitted; may be called multiple times.
BOOST_THREAD_DECL void __cdecl on_thread_enter(void);
//Function to be called just after a thread starts
//in an exe or dll that uses Boost.Threads.
//Must be called in the context of the thread
//that is starting.
//Called automatically by Boost.Threads when
//a method for doing so has been discovered.
//May be omitted; may be called multiple times.
BOOST_THREAD_DECL void __cdecl on_thread_exit(void);
//Function to be called just be fore a thread ends
//in an exe or dll that uses Boost.Threads.
//Must be called in the context of the thread
//that is ending.
//Called automatically by Boost.Threads when
//a method for doing so has been discovered.
//Must not be omitted; may be called multiple times.
void tss_cleanup_implemented();
//Dummy function used both to detect whether tss cleanup
//cleanup has been implemented and to force
//it to be linked into the Boost.Threads library.
}
#endif //defined(BOOST_HAS_WINTHREADS)
#include <boost/config/abi_suffix.hpp>
#endif //!defined(BOOST_TLS_HOOKS_HPP)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,225 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007-9 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_EXCEPTIONS_PDM070801_H
#define BOOST_THREAD_EXCEPTIONS_PDM070801_H
#include <boost/thread/detail/config.hpp>
// pdm: Sorry, but this class is used all over the place & I end up
// with recursive headers if I don't separate it
// wek: Not sure why recursive headers would cause compilation problems
// given the include guards, but regardless it makes sense to
// seperate this out any way.
#include <string>
#include <stdexcept>
#include <boost/system/system_error.hpp>
#include <boost/system/error_code.hpp>
#include <boost/config/abi_prefix.hpp>
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
//public std::exception
{
typedef system::system_error base_type;
public:
thread_exception()
: base_type(0,system::system_category())
{}
thread_exception(int sys_error_code)
: base_type(sys_error_code, system::system_category())
{}
thread_exception( int ev, const char * what_arg )
: base_type(system::error_code(ev, system::system_category()), what_arg)
{
}
thread_exception( int ev, const std::string & what_arg )
: base_type(system::error_code(ev, system::system_category()), what_arg)
{
}
~thread_exception() throw()
{}
int native_error() const
{
return code().value();
}
};
class BOOST_SYMBOL_VISIBLE condition_error:
public system::system_error
//public std::exception
{
typedef system::system_error base_type;
public:
condition_error()
: base_type(system::error_code(0, system::system_category()), "Condition error")
{}
condition_error( int ev )
: base_type(system::error_code(ev, system::system_category()), "Condition error")
{
}
condition_error( int ev, const char * what_arg )
: base_type(system::error_code(ev, system::system_category()), what_arg)
{
}
condition_error( int ev, const std::string & what_arg )
: base_type(system::error_code(ev, system::system_category()), what_arg)
{
}
};
class BOOST_SYMBOL_VISIBLE lock_error:
public thread_exception
{
typedef thread_exception base_type;
public:
lock_error()
: base_type(0, "boost::lock_error")
{}
lock_error( int ev )
: base_type(ev, "boost::lock_error")
{
}
lock_error( int ev, const char * what_arg )
: base_type(ev, what_arg)
{
}
lock_error( int ev, const std::string & what_arg )
: base_type(ev, what_arg)
{
}
~lock_error() throw()
{}
};
class BOOST_SYMBOL_VISIBLE thread_resource_error:
public thread_exception
{
typedef thread_exception base_type;
public:
thread_resource_error()
: base_type(static_cast<int>(system::errc::resource_unavailable_try_again), "boost::thread_resource_error")
{}
thread_resource_error( int ev )
: base_type(ev, "boost::thread_resource_error")
{
}
thread_resource_error( int ev, const char * what_arg )
: base_type(ev, what_arg)
{
}
thread_resource_error( int ev, const std::string & what_arg )
: base_type(ev, what_arg)
{
}
~thread_resource_error() throw()
{}
};
class BOOST_SYMBOL_VISIBLE unsupported_thread_option:
public thread_exception
{
typedef thread_exception base_type;
public:
unsupported_thread_option()
: base_type(static_cast<int>(system::errc::invalid_argument), "boost::unsupported_thread_option")
{}
unsupported_thread_option( int ev )
: base_type(ev, "boost::unsupported_thread_option")
{
}
unsupported_thread_option( int ev, const char * what_arg )
: base_type(ev, what_arg)
{
}
unsupported_thread_option( int ev, const std::string & what_arg )
: base_type(ev, what_arg)
{
}
};
class BOOST_SYMBOL_VISIBLE invalid_thread_argument:
public thread_exception
{
typedef thread_exception base_type;
public:
invalid_thread_argument()
: base_type(static_cast<int>(system::errc::invalid_argument), "boost::invalid_thread_argument")
{}
invalid_thread_argument( int ev )
: base_type(ev, "boost::invalid_thread_argument")
{
}
invalid_thread_argument( int ev, const char * what_arg )
: base_type(ev, what_arg)
{
}
invalid_thread_argument( int ev, const std::string & what_arg )
: base_type(ev, what_arg)
{
}
};
class BOOST_SYMBOL_VISIBLE thread_permission_error:
public thread_exception
{
typedef thread_exception base_type;
public:
thread_permission_error()
: base_type(static_cast<int>(system::errc::permission_denied), "boost::thread_permission_error")
{}
thread_permission_error( int ev )
: base_type(ev, "boost::thread_permission_error")
{
}
thread_permission_error( int ev, const char * what_arg )
: base_type(ev, what_arg)
{
}
thread_permission_error( int ev, const std::string & what_arg )
: base_type(ev, what_arg)
{
}
};
} // namespace boost
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,15 @@
// 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
#ifndef BOOST_THREAD_EXECUTOR_HPP
#define BOOST_THREAD_EXECUTOR_HPP
#include <boost/thread/executors/executor.hpp>
#include <boost/thread/executors/executor_adaptor.hpp>
#endif

View File

@@ -0,0 +1,148 @@
// Copyright (C) 2013,2014 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
#ifndef BOOST_THREAD_EXECUTORS_EXECUTOR_HPP
#define BOOST_THREAD_EXECUTORS_EXECUTOR_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/executors/work.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
class executor
{
public:
/// type-erasure to store the works to do
typedef executors::work work;
/// executor is not copyable.
BOOST_THREAD_NO_COPYABLE(executor)
executor() {}
/**
* \par Effects
* Destroys the executor.
*
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
virtual ~executor() {};
/**
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
virtual void close() = 0;
/**
* \par Returns
* Whether the pool is closed for submissions.
*/
virtual bool closed() = 0;
/**
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
virtual void submit(BOOST_THREAD_RV_REF(work) closure) = 0;
// virtual void submit(work& closure) = 0;
/**
* \par Requires
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
*
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
work w ((closure));
submit(boost::move(w));
}
#endif
void submit(void (*closure)())
{
work w ((closure));
submit(boost::move(w));
}
template <typename Closure>
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
//submit(work(boost::forward<Closure>(closure)));
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}
/**
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
virtual bool try_executing_one() = 0;
/**
* \par Requires
* This must be called from an scheduled task.
*
* \par Effects
* Reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
{
do {
//schedule_one_or_yield();
if ( ! try_executing_one())
{
return false;
}
} while (! pred());
return true;
}
};
}
using executors::executor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,136 @@
// Copyright (C) 2013,2014 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
#ifndef BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP
#define BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
/**
* Polymorphic adaptor of a model of Executor to an executor.
*/
template <typename Executor>
class executor_adaptor : public executor
{
Executor ex;
public:
/// type-erasure to store the works to do
typedef executor::work work;
/// executor is not copyable.
BOOST_THREAD_NO_COPYABLE(executor_adaptor)
/**
* executor_adaptor constructor
*/
#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename ...Args>
executor_adaptor(BOOST_THREAD_RV_REF(Args) ... args) : ex(boost::forward<Args>(args)...) {}
#else
/**
* executor_adaptor constructor
*/
executor_adaptor() : ex() {}
template <typename A1>
executor_adaptor(
BOOST_THREAD_FWD_REF(A1) a1
) :
ex(
boost::forward<A1>(a1)
) {}
template <typename A1, typename A2>
executor_adaptor(
BOOST_THREAD_FWD_REF(A1) a1,
BOOST_THREAD_FWD_REF(A2) a2
) :
ex(
boost::forward<A1>(a1),
boost::forward<A2>(a2)
) {}
template <typename A1, typename A2, typename A3>
executor_adaptor(
BOOST_THREAD_FWD_REF(A1) a1,
BOOST_THREAD_FWD_REF(A2) a2,
BOOST_THREAD_FWD_REF(A3) a3
) :
ex(
boost::forward<A1>(a1),
boost::forward<A2>(a2),
boost::forward<A3>(a3)
) {}
#endif
Executor& underlying_executor() { return ex; }
/**
* \b Effects: close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close() { ex.close(); }
/**
* \b Returns: whether the pool is closed for submissions.
*/
bool closed() { return ex.closed(); }
/**
* \b Effects: The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
*
* \b Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \b Throws: \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
void submit(BOOST_THREAD_RV_REF(work) closure) {
return ex.submit(boost::move(closure));
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
submit(work(closure));
}
#endif
void submit(void (*closure)())
{
submit(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
//submit(work(boost::forward<Closure>(closure)));
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}
/**
* Effects: try to execute one task.
* Returns: whether a task has been executed.
* Throws: whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one() { return ex.try_executing_one(); }
};
}
using executors::executor_adaptor;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,213 @@
// Copyright (C) 2014 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_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
#define BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/delete.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/executors/executor.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace executors
{
template <class Executor>
class executor_ref : public executor
{
Executor& ex;
public:
/// type-erasure to store the works to do
typedef executors::work work;
/// executor is not copyable.
BOOST_THREAD_NO_COPYABLE(executor_ref)
executor_ref(Executor& ex) : ex(ex) {}
/**
* \par Effects
* Destroys the executor.
*
* \par Synchronization
* The completion of all the closures happen before the completion of the executor destructor.
*/
~executor_ref() {};
/**
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close() { ex.close(); }
/**
* \par Returns
* Whether the pool is closed for submissions.
*/
bool closed() { return ex.closed(); }
/**
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the executor will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
void submit(BOOST_THREAD_RV_REF(work) closure) {
ex.submit(boost::move(closure));
}
// void submit(work& closure) {
// ex.submit(closure);
// }
/**
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one() { return ex.try_executing_one(); }
};
class generic_executor_ref
{
shared_ptr<executor> ex;
public:
/// type-erasure to store the works to do
typedef executors::work work;
template<typename Executor>
generic_executor_ref(Executor& ex)
//: ex(make_shared<executor_ref<Executor> >(ex)) // todo check why this doesn't works with C++03
: ex( new executor_ref<Executor>(ex) )
{
}
//generic_executor_ref(generic_executor_ref const& other) noexcept {}
//generic_executor_ref& operator=(generic_executor_ref const& other) noexcept {}
/**
* \par Effects
* Close the \c executor for submissions.
* The worker threads will work until there is no more closures to run.
*/
void close() { ex->close(); }
/**
* \par Returns
* Whether the pool is closed for submissions.
*/
bool closed() { return ex->closed(); }
/**
* \par Requires
* \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible.
*
* \par Effects
* The specified closure will be scheduled for execution at some point in the future.
* If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads.
*
* \par Synchronization
* Completion of closure on a particular thread happens before destruction of thread's thread local variables.
*
* \par Throws
* \c sync_queue_is_closed if the thread pool is closed.
* Whatever exception that can be throw while storing the closure.
*/
void submit(BOOST_THREAD_RV_REF(work) closure)
{
ex->submit(boost::move(closure));
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <typename Closure>
void submit(Closure & closure)
{
//work w ((closure));
//submit(boost::move(w));
submit(work(closure));
}
#endif
void submit(void (*closure)())
{
work w ((closure));
submit(boost::move(w));
//submit(work(closure));
}
template <typename Closure>
void submit(BOOST_THREAD_FWD_REF(Closure) closure)
{
work w((boost::forward<Closure>(closure)));
submit(boost::move(w));
}
// size_t num_pending_closures() const
// {
// return ex->num_pending_closures();
// }
/**
* \par Effects
* Try to execute one task.
*
* \par Returns
* Whether a task has been executed.
*
* \par Throws
* Whatever the current task constructor throws or the task() throws.
*/
bool try_executing_one() { return ex->try_executing_one(); }
/**
* \par Requires
* This must be called from an scheduled task.
*
* \par Effects
* reschedule functions until pred()
*/
template <typename Pred>
bool reschedule_until(Pred const& pred)
{
do {
//schedule_one_or_yield();
if ( ! try_executing_one())
{
return false;
}
} while (! pred());
return true;
}
};
}
using executors::executor_ref;
using executors::generic_executor_ref;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,30 @@
// (C) Copyright 2013,2014 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_EXECUTORS_WORK_HPP
#define BOOST_THREAD_EXECUTORS_WORK_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/nullary_function.hpp>
#include <boost/thread/csbl/functional.hpp>
namespace boost
{
namespace executors
{
typedef detail::nullary_function<void()> work;
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typedef detail::nullary_function<void()> work_pq;
//typedef csbl::function<void()> work_pq;
#else
typedef csbl::function<void()> work_pq;
#endif
}
} // namespace boost
#endif // BOOST_THREAD_EXECUTORS_WORK_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 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_FUTURES_FUTURE_ERROR_HPP
#define BOOST_THREAD_FUTURES_FUTURE_ERROR_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/futures/future_error_code.hpp>
#include <boost/system/error_code.hpp>
#include <stdexcept>
namespace boost
{
class BOOST_SYMBOL_VISIBLE future_error
: public std::logic_error
{
system::error_code ec_;
public:
future_error(system::error_code ec)
: logic_error(ec.message()),
ec_(ec)
{
}
const system::error_code& code() const BOOST_NOEXCEPT
{
return ec_;
}
};
class BOOST_SYMBOL_VISIBLE future_uninitialized:
public future_error
{
public:
future_uninitialized() :
future_error(system::make_error_code(future_errc::no_state))
{}
};
class BOOST_SYMBOL_VISIBLE broken_promise:
public future_error
{
public:
broken_promise():
future_error(system::make_error_code(future_errc::broken_promise))
{}
};
class BOOST_SYMBOL_VISIBLE future_already_retrieved:
public future_error
{
public:
future_already_retrieved():
future_error(system::make_error_code(future_errc::future_already_retrieved))
{}
};
class BOOST_SYMBOL_VISIBLE promise_already_satisfied:
public future_error
{
public:
promise_already_satisfied():
future_error(system::make_error_code(future_errc::promise_already_satisfied))
{}
};
class BOOST_SYMBOL_VISIBLE task_already_started:
public future_error
{
public:
task_already_started():
future_error(system::make_error_code(future_errc::promise_already_satisfied))
{}
};
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))
{}
};
}
#endif // header

View File

@@ -0,0 +1,61 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2012,2015 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_FUTURES_FUTURE_ERROR_CODE_HPP
#define BOOST_THREAD_FUTURES_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

View File

@@ -0,0 +1,30 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 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_FUTURES_FUTURE_STATUS_HPP
#define BOOST_THREAD_FUTURES_FUTURE_STATUS_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/core/scoped_enum.hpp>
namespace boost
{
//enum class future_status
BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status)
{
ready,
timeout,
deferred
}
BOOST_SCOPED_ENUM_DECLARE_END(future_status)
namespace future_state
{
enum state { uninitialized, waiting, ready, moved, deferred };
}
}
#endif // header

View File

@@ -0,0 +1,21 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 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_FUTURES_IS_FUTURE_TYPE_HPP
#define BOOST_THREAD_FUTURES_IS_FUTURE_TYPE_HPP
#include <boost/type_traits/integral_constant.hpp>
namespace boost
{
template<typename T>
struct is_future_type : false_type
{
};
}
#endif // header

View File

@@ -0,0 +1,32 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 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_FUTURES_LAUNCH_HPP
#define BOOST_THREAD_FUTURES_LAUNCH_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/core/scoped_enum.hpp>
namespace boost
{
//enum class launch
BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch)
{
none = 0,
async = 1,
deferred = 2,
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
executor = 4,
#endif
inherit = 8,
sync = 16,
any = async | deferred
}
BOOST_SCOPED_ENUM_DECLARE_END(launch)
}
#endif // header

View File

@@ -0,0 +1,74 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 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_FUTURES_WAIT_FOR_ALL_HPP
#define BOOST_THREAD_FUTURES_WAIT_FOR_ALL_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/futures/is_future_type.hpp>
#include <boost/core/enable_if.hpp>
namespace boost
{
template<typename Iterator>
typename boost::disable_if<is_future_type<Iterator>,void>::type wait_for_all(Iterator begin,Iterator end)
{
for(Iterator current=begin;current!=end;++current)
{
current->wait();
}
}
#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)
{
f1.wait();
f2.wait();
}
template<typename F1,typename F2,typename F3>
void wait_for_all(F1& f1,F2& f2,F3& f3)
{
f1.wait();
f2.wait();
f3.wait();
}
template<typename F1,typename F2,typename F3,typename F4>
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4)
{
f1.wait();
f2.wait();
f3.wait();
f4.wait();
}
template<typename F1,typename F2,typename F3,typename F4,typename F5>
void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5)
{
f1.wait();
f2.wait();
f3.wait();
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)}
}
#endif // header

View File

@@ -0,0 +1,161 @@
// (C) Copyright 2008-10 Anthony Williams
// (C) Copyright 2011-2015 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_FUTURES_WAIT_FOR_ANY_HPP
#define BOOST_THREAD_FUTURES_WAIT_FOR_ANY_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/futures/is_future_type.hpp>
#include <boost/thread/lock_algorithms.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/next_prior.hpp>
#include <boost/scoped_array.hpp>
#include <iterator>
#include <vector>
namespace boost
{
namespace detail
{
template <class Future>
class waiter_for_any_in_seq
{
struct registered_waiter;
typedef std::vector<int>::size_type count_type;
struct registered_waiter
{
typedef Future future_type;
future_type* future_;
typedef typename Future::notify_when_ready_handle notify_when_ready_handle;
notify_when_ready_handle handle;
count_type index;
registered_waiter(future_type & a_future,
notify_when_ready_handle handle_, count_type index_) :
future_(&a_future), handle(handle_), index(index_)
{
}
};
struct all_futures_lock
{
#ifdef _MANAGED
typedef std::ptrdiff_t count_type_portable;
#else
typedef count_type count_type_portable;
#endif
count_type_portable count;
boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
all_futures_lock(std::vector<registered_waiter>& waiters) :
count(waiters.size()), locks(new boost::unique_lock<boost::mutex>[count])
{
for (count_type_portable i = 0; i < count; ++i)
{
locks[i] = BOOST_THREAD_MAKE_RV_REF(boost::unique_lock<boost::mutex>(waiters[i].future_->mutex()));
}
}
void lock()
{
boost::lock(locks.get(), locks.get() + count);
}
void unlock()
{
for (count_type_portable i = 0; i < count; ++i)
{
locks[i].unlock();
}
}
};
boost::condition_variable_any cv;
std::vector<registered_waiter> waiters_;
count_type future_count;
public:
waiter_for_any_in_seq() :
future_count(0)
{
}
template <typename F>
void add(F& f)
{
if (f.valid())
{
registered_waiter waiter(f, f.notify_when_ready(cv), future_count);
try
{
waiters_.push_back(waiter);
}
catch (...)
{
f.future_->unnotify_when_ready(waiter.handle);
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(waiters_);
for (;;)
{
for (count_type i = 0; i < waiters_.size(); ++i)
{
if (waiters_[i].future_->is_ready(lk.locks[i]))
{
return waiters_[i].index;
}
}
cv.wait(lk);
}
}
~waiter_for_any_in_seq()
{
for (count_type i = 0; i < waiters_.size(); ++i)
{
waiters_[i].future_->unnotify_when_ready(waiters_[i].handle);
}
}
};
}
template <typename Iterator>
typename boost::disable_if<is_future_type<Iterator> , Iterator>::type wait_for_any(Iterator begin, Iterator end)
{
if (begin == end) return end;
detail::waiter_for_any_in_seq<typename std::iterator_traits<Iterator>::value_type> waiter;
for (Iterator current = begin; current != end; ++current)
{
waiter.add(*current);
}
return boost::next(begin, waiter.wait());
}
}
#endif // header

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -0,0 +1,16 @@
// 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_LOCKS_HPP
#define BOOST_THREAD_LOCKS_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

View File

@@ -0,0 +1,53 @@
#ifndef BOOST_THREAD_MUTEX_HPP
#define BOOST_THREAD_MUTEX_HPP
// mutex.hpp
//
// (C) Copyright 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/mutex.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/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<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

View File

@@ -0,0 +1,44 @@
#ifndef BOOST_THREAD_ONCE_HPP
#define BOOST_THREAD_ONCE_HPP
// once.hpp
//
// (C) Copyright 2006-7 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/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
#include <boost/config/abi_prefix.hpp>
namespace boost
{
// template<class Callable, class ...Args> void
// call_once(once_flag& flag, Callable&& func, Args&&... args);
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);
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,429 @@
#ifndef BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
#define BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-10 Anthony Williams
// (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>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
namespace this_thread
{
void BOOST_THREAD_DECL interruption_point();
}
#endif
namespace thread_cv_detail
{
template<typename MutexType>
struct lock_on_exit
{
MutexType* m;
lock_on_exit():
m(0)
{}
void activate(MutexType& m_)
{
m_.unlock();
m=&m_;
}
~lock_on_exit()
{
if(m)
{
m->lock();
}
}
};
}
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);
pthread_mutex_t* the_mutex = &internal_mutex;
guard.activate(m);
#else
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
#endif
do {
res = pthread_cond_wait(&cond,the_mutex);
} while (res == EINTR);
}
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
this_thread::interruption_point();
#endif
if(res)
{
boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_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, "boost::condition_variable::do_wait_until() failed precondition mutex not owned"));
}
#endif
int cond_res;
{
#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);
pthread_mutex_t* the_mutex = &internal_mutex;
guard.activate(m);
#else
pthread_mutex_t* the_mutex = m.mutex()->native_handle();
#endif
cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout);
}
#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, "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));
}
class condition_variable_any
{
pthread_mutex_t internal_mutex;
pthread_cond_t cond;
public:
BOOST_THREAD_NO_COPYABLE(condition_variable_any)
condition_variable_any()
{
int const res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init"));
}
int const res2 = detail::monotonic_pthread_cond_init(cond);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in detail::monotonic_pthread_cond_init"));
}
}
~condition_variable_any()
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
BOOST_VERIFY(!pthread_cond_destroy(&cond));
}
template<typename lock_type>
void wait(lock_type& m)
{
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, "boost::condition_variable_any::wait() failed in pthread_cond_wait"));
}
}
template<typename lock_type,typename predicate_type>
void wait(lock_type& m,predicate_type pred)
{
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)
{
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& abs_time)
{
return timed_wait(m,system_time(abs_time));
}
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration)
{
return timed_wait(m,get_system_time()+wait_duration);
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& abs_time, predicate_type pred)
{
while (!pred())
{
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& abs_time, predicate_type pred)
{
return timed_wait(m,system_time(abs_time),pred);
}
template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
{
return timed_wait(m,get_system_time()+wait_duration,pred);
}
#endif
#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type,class Duration>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
wait_until(lock,
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
return system_clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
template <class lock_type, class Clock, class Duration>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
}
template <class lock_type, class Rep, class Period>
cv_status
wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
steady_clock::time_point c_now = steady_clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(d));
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
}
template <class lock_type>
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 = boost::detail::to_timespec(d);
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
#endif
#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type, class Duration>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<chrono::steady_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
wait_until(lock,
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
return steady_clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
template <class lock_type, class Clock, class Duration>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
steady_clock::time_point s_now = steady_clock::now();
typename Clock::time_point c_now = Clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
}
template <class lock_type, class Rep, class Period>
cv_status
wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
steady_clock::time_point c_now = steady_clock::now();
wait_until(lock, c_now + ceil<nanoseconds>(d));
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
}
template <class lock_type>
inline cv_status wait_until(
lock_type& lock,
chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
if (do_wait_until(lock, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
#endif
#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type, class Clock, class Duration, class Predicate>
bool
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
}
return true;
}
template <class lock_type, class Rep, class Period, class Predicate>
bool
wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
}
#endif
void notify_one() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
void notify_all() BOOST_NOEXCEPT
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
}
private: // used by boost::thread::try_join_until
template <class lock_type>
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, "boost::condition_variable_any::do_wait_until() failed in pthread_cond_timedwait"));
}
return true;
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,360 @@
#ifndef BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
#define BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#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/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
{
namespace detail {
inline int monotonic_pthread_cond_init(pthread_cond_t& cond) {
#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
pthread_condattr_t attr;
int res = pthread_condattr_init(&attr);
if (res)
{
return res;
}
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
res=pthread_cond_init(&cond,&attr);
pthread_condattr_destroy(&attr);
return res;
#else
return pthread_cond_init(&cond,NULL);
#endif
}
}
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 res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init"));
}
#endif
res = detail::monotonic_pthread_cond_init(cond);
if (res)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
#endif
boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init"));
}
}
~condition_variable()
{
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_ASSERT(!ret);
}
void wait(unique_lock<mutex>& m);
template<typename predicate_type>
void wait(unique_lock<mutex>& m,predicate_type pred)
{
while(!pred()) wait(m);
}
#if defined BOOST_THREAD_USES_DATETIME
inline bool timed_wait(
unique_lock<mutex>& m,
boost::system_time const& abs_time)
{
#if defined BOOST_THREAD_WAIT_BUG
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::to_timespec(abs_time);
return do_wait_until(m, timeout);
#endif
}
bool timed_wait(
unique_lock<mutex>& m,
xtime const& abs_time)
{
return timed_wait(m,system_time(abs_time));
}
template<typename duration_type>
bool timed_wait(
unique_lock<mutex>& m,
duration_type const& wait_duration)
{
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 timed_wait(m,get_system_time()+wait_duration);
}
template<typename predicate_type>
bool timed_wait(
unique_lock<mutex>& m,
boost::system_time const& abs_time,predicate_type pred)
{
while (!pred())
{
if(!timed_wait(m, abs_time))
return pred();
}
return true;
}
template<typename predicate_type>
bool timed_wait(
unique_lock<mutex>& m,
xtime const& abs_time,predicate_type pred)
{
return timed_wait(m,system_time(abs_time),pred);
}
template<typename duration_type,typename predicate_type>
bool timed_wait(
unique_lock<mutex>& m,
duration_type const& wait_duration,predicate_type pred)
{
if (wait_duration.is_pos_infinity())
{
while (!pred())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
}
return true;
}
if (wait_duration.is_special())
{
return pred();
}
return timed_wait(m,get_system_time()+wait_duration,pred);
}
#endif
#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class Duration>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
wait_until(lock,
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
return system_clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
template <class Clock, class Duration>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
}
template <class Rep, class Period>
cv_status
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
steady_clock::time_point c_now = steady_clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(d));
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
}
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 = boost::detail::to_timespec(d);
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
#endif
#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class Duration>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<chrono::steady_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<steady_clock, nanoseconds> nano_sys_tmpt;
wait_until(lock,
nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
return steady_clock::now() < t ? cv_status::no_timeout :
cv_status::timeout;
}
template <class Clock, class Duration>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
steady_clock::time_point s_now = steady_clock::now();
typename Clock::time_point c_now = Clock::now();
wait_until(lock, s_now + ceil<nanoseconds>(t - c_now));
return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout;
}
template <class Rep, class Period>
cv_status
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d)
{
using namespace chrono;
steady_clock::time_point c_now = steady_clock::now();
wait_until(lock, c_now + ceil<nanoseconds>(d));
return steady_clock::now() - c_now < d ? cv_status::no_timeout :
cv_status::timeout;
}
inline cv_status wait_until(
unique_lock<mutex>& lk,
chrono::time_point<chrono::steady_clock, chrono::nanoseconds> tp)
{
using namespace chrono;
nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
if (do_wait_until(lk, ts)) return cv_status::no_timeout;
else return cv_status::timeout;
}
#endif
#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC
#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration, class Predicate>
bool
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
}
return true;
}
template <class Rep, class Period, class Predicate>
bool
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
}
#endif
#define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE
typedef pthread_cond_t* native_handle_type;
native_handle_type native_handle()
{
return &cond;
}
void notify_one() BOOST_NOEXCEPT;
void notify_all() BOOST_NOEXCEPT;
};
BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,361 @@
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_MUTEX_HPP
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011,2012,2015 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/assert.hpp>
#include <pthread.h>
#include <boost/throw_exception.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/thread/exceptions.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>
#include <errno.h>
#include <boost/thread/pthread/timespec.hpp>
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#if (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \
|| (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21)
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#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:
pthread_mutex_t m;
public:
BOOST_THREAD_NO_COPYABLE(mutex)
mutex()
{
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost:: mutex constructor failed in pthread_mutex_init"));
}
}
~mutex()
{
int const res = posix::pthread_mutex_destroy(&m);
boost::ignore_unused(res);
BOOST_ASSERT(!res);
}
void lock()
{
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()
{
int res = posix::pthread_mutex_unlock(&m);
(void)res;
BOOST_ASSERT(res == 0);
// if (res)
// {
// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
// }
}
bool try_lock()
{
int res;
do
{
res = pthread_mutex_trylock(&m);
} while (res == EINTR);
if (res==EBUSY)
{
return false;
}
return !res;
}
#define BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
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;
class timed_mutex
{
private:
pthread_mutex_t m;
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
pthread_cond_t cond;
bool is_locked;
#endif
public:
BOOST_THREAD_NO_COPYABLE(timed_mutex)
timed_mutex()
{
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init"));
}
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!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;
#endif
}
~timed_mutex()
{
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)
{
return timed_lock(get_system_time()+relative_time);
}
bool timed_lock(boost::xtime const & absolute_time)
{
return timed_lock(system_time(absolute_time));
}
#endif
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
void lock()
{
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()
{
int res = posix::pthread_mutex_unlock(&m);
(void)res;
BOOST_ASSERT(res == 0);
// if (res)
// {
// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock"));
// }
}
bool try_lock()
{
int res;
do
{
res = pthread_mutex_trylock(&m);
} while (res == EINTR);
if (res==EBUSY)
{
return false;
}
return !res;
}
private:
bool do_try_lock_until(struct timespec const &timeout)
{
int const res=pthread_mutex_timedlock(&m,&timeout);
BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
public:
#else
void lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
while(is_locked)
{
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
}
is_locked=true;
}
void unlock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
is_locked=false;
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
bool try_lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked)
{
return false;
}
is_locked=true;
return true;
}
private:
bool do_try_lock_until(struct timespec const &timeout)
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
while(is_locked)
{
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
if(cond_res==ETIMEDOUT)
{
return false;
}
BOOST_ASSERT(!cond_res);
}
is_locked=true;
return true;
}
public:
#endif
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(system_time const & 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)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<nanoseconds>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
return try_lock_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
{
//using namespace chrono;
chrono::nanoseconds d = tp.time_since_epoch();
timespec ts = boost::detail::to_timespec(d);
return do_try_lock_until(ts);
}
#endif
#define BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
#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
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,540 @@
#ifndef BOOST_THREAD_PTHREAD_ONCE_HPP
#define BOOST_THREAD_PTHREAD_ONCE_HPP
// once.hpp
//
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <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/core/no_exceptions_support.hpp>
#include <boost/bind.hpp>
#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>
#include <boost/cstdint.hpp>
#include <pthread.h>
#include <csignal>
namespace boost
{
struct once_flag;
#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
namespace thread_detail
{
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)
}
#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
{
BOOST_THREAD_NO_COPYABLE(once_flag)
BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT
: epoch(BOOST_ONCE_INITIAL_FLAG_VALUE)
{}
private:
volatile thread_detail::uintmax_atomic_t epoch;
#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);
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
{
volatile thread_detail::uintmax_atomic_t epoch;
};
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
#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 thread_detail
{
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
#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)
{
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))
) 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();
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)),
thread_detail::decay_copy(boost::forward<T1>(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;
}
}
#endif
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -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);
}
}
#if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
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 // __SUNPRO_CC
#endif
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,64 @@
#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
#define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <pthread.h>
#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace pthread
{
class pthread_mutex_scoped_lock
{
pthread_mutex_t* m;
bool locked;
public:
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
m(m_),locked(true)
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
void unlock()
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
locked=false;
}
~pthread_mutex_scoped_lock()
{
if(locked)
{
unlock();
}
}
};
class pthread_mutex_scoped_unlock
{
pthread_mutex_t* m;
public:
explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_):
m(m_)
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
}
~pthread_mutex_scoped_unlock()
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
};
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,716 @@
#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#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>
namespace boost
{
class shared_mutex
{
private:
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;
bool exclusive_waiting_blocked;
};
state_data state;
boost::mutex state_change;
boost::condition_variable shared_cond;
boost::condition_variable exclusive_cond;
boost::condition_variable upgrade_cond;
void release_waiters()
{
exclusive_cond.notify_one();
shared_cond.notify_all();
}
public:
BOOST_THREAD_NO_COPYABLE(shared_mutex)
shared_mutex()
{
}
~shared_mutex()
{
}
void lock_shared()
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock_shared())
{
shared_cond.wait(lk);
}
state.lock_shared();
}
bool try_lock_shared()
{
boost::unique_lock<boost::mutex> lk(state_change);
if(!state.can_lock_shared())
{
return false;
}
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;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(!state.can_lock_shared())
{
if(!shared_cond.timed_wait(lk,timeout))
{
return false;
}
}
state.lock_shared();
return true;
}
template<typename TimeDuration>
bool timed_lock_shared(TimeDuration const & relative_time)
{
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)
{
return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
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.lock_shared();
return true;
}
#endif
void unlock_shared()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
state.unlock_shared();
if (! state.more_shared())
{
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();
}
}
void lock()
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while (state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
exclusive_cond.wait(lk);
}
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;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
if(!exclusive_cond.timed_wait(lk,timeout))
{
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=false;
release_waiters();
return false;
}
break;
}
}
state.exclusive=true;
return true;
}
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
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)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time))
{
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=false;
release_waiters();
return false;
}
break;
}
}
state.exclusive=true;
return true;
}
#endif
bool try_lock()
{
boost::unique_lock<boost::mutex> lk(state_change);
if(state.shared_count || state.exclusive)
{
return false;
}
else
{
state.exclusive=true;
return true;
}
}
void unlock()
{
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;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
shared_cond.wait(lk);
}
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;
#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))
{
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
}
break;
}
}
state.lock_shared();
state.upgrade=true;
return true;
}
template<typename TimeDuration>
bool timed_lock_upgrade(TimeDuration const & relative_time)
{
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)
{
return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_upgrade_until(const chrono::time_point<Clock, Duration>& abs_time)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#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))
{
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
}
break;
}
}
state.lock_shared();
state.upgrade=true;
return true;
}
#endif
bool try_lock_upgrade()
{
boost::unique_lock<boost::mutex> lk(state_change);
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
}
else
{
state.lock_shared();
state.upgrade=true;
state.assert_lock_upgraded();
return true;
}
}
void unlock_upgrade()
{
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();
}
}
// Upgrade <-> Exclusive
void unlock_upgrade_and_lock()
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#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::unique_lock<boost::mutex> lk(state_change);
state.assert_locked();
state.exclusive=false;
state.upgrade=true;
state.lock_shared();
state.exclusive_waiting_blocked=false;
state.assert_lock_upgraded();
release_waiters();
}
bool try_unlock_upgrade_and_lock()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_upgraded();
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& state.upgrade
&& state.shared_count==1)
{
state.shared_count=0;
state.exclusive=true;
state.upgrade=false;
state.assert_locked();
return true;
}
return false;
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool
try_unlock_upgrade_and_lock_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_upgrade_and_lock_until(
chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool
try_unlock_upgrade_and_lock_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_upgraded();
if (state.shared_count != 1)
{
for (;;)
{
cv_status status = shared_cond.wait_until(lk,abs_time);
if (state.shared_count == 1)
break;
if(status == cv_status::timeout)
return false;
}
}
state.upgrade=false;
state.exclusive=true;
state.exclusive_waiting_blocked=false;
state.shared_count=0;
return true;
}
#endif
// Shared <-> Exclusive
void unlock_and_lock_shared()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_locked();
state.exclusive=false;
state.lock_shared();
state.exclusive_waiting_blocked=false;
release_waiters();
}
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& !state.upgrade
&& state.shared_count==1)
{
state.shared_count=0;
state.exclusive=true;
return true;
}
return false;
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool
try_unlock_shared_and_lock_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_shared_and_lock_until(
chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool
try_unlock_shared_and_lock_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
if (state.shared_count != 1)
{
for (;;)
{
cv_status status = shared_cond.wait_until(lk,abs_time);
if (state.shared_count == 1)
break;
if(status == cv_status::timeout)
return false;
}
}
state.upgrade=false;
state.exclusive=true;
state.exclusive_waiting_blocked=false;
state.shared_count=0;
return true;
}
#endif
#endif
// Shared <-> Upgrade
void unlock_upgrade_and_lock_shared()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_upgraded();
state.upgrade=false;
state.exclusive_waiting_blocked=false;
release_waiters();
}
#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS
bool try_unlock_shared_and_lock_upgrade()
{
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
if( !state.exclusive
&& !state.exclusive_waiting_blocked
&& !state.upgrade
)
{
state.upgrade=true;
return true;
}
return false;
}
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool
try_unlock_shared_and_lock_upgrade_for(
const chrono::duration<Rep, Period>& rel_time)
{
return try_unlock_shared_and_lock_upgrade_until(
chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool
try_unlock_shared_and_lock_upgrade_until(
const chrono::time_point<Clock, Duration>& abs_time)
{
#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
boost::this_thread::disable_interruption do_not_disturb;
#endif
boost::unique_lock<boost::mutex> lk(state_change);
state.assert_lock_shared();
if( state.exclusive
|| state.exclusive_waiting_blocked
|| state.upgrade
)
{
for (;;)
{
cv_status status = exclusive_cond.wait_until(lk,abs_time);
if( ! state.exclusive
&& ! state.exclusive_waiting_blocked
&& ! state.upgrade
)
break;
if(status == cv_status::timeout)
return false;
}
}
state.upgrade=true;
return true;
}
#endif
#endif
};
typedef shared_mutex upgrade_mutex;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,292 @@
#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
#define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/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/assert.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#endif
#include <map>
#include <vector>
#include <utility>
#if defined(__ANDROID__)
# ifndef PAGE_SIZE
# define PAGE_SIZE 4096
# endif
#endif
#include <pthread.h>
#include <unistd.h>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class thread_attributes {
public:
thread_attributes() BOOST_NOEXCEPT {
int res = pthread_attr_init(&val_);
BOOST_VERIFY(!res && "pthread_attr_init failed");
}
~thread_attributes() {
int res = pthread_attr_destroy(&val_);
BOOST_VERIFY(!res && "pthread_attr_destroy failed");
}
// stack
void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
if (size==0) return;
std::size_t page_size = getpagesize();
#ifdef PTHREAD_STACK_MIN
if (size<PTHREAD_STACK_MIN) size=PTHREAD_STACK_MIN;
#endif
size = ((size+page_size-1)/page_size)*page_size;
int res = pthread_attr_setstacksize(&val_, size);
BOOST_VERIFY(!res && "pthread_attr_setstacksize failed");
}
std::size_t get_stack_size() const BOOST_NOEXCEPT {
std::size_t size;
int res = pthread_attr_getstacksize(&val_, &size);
BOOST_VERIFY(!res && "pthread_attr_getstacksize failed");
return size;
}
#define BOOST_THREAD_DEFINES_THREAD_ATTRIBUTES_NATIVE_HANDLE
typedef pthread_attr_t native_handle_type;
native_handle_type* native_handle() BOOST_NOEXCEPT {
return &val_;
}
const native_handle_type* native_handle() const BOOST_NOEXCEPT {
return &val_;
}
private:
pthread_attr_t val_;
};
class thread;
namespace detail
{
struct shared_state_base;
struct tss_cleanup_function;
struct thread_exit_callback_node;
struct tss_data_node
{
boost::shared_ptr<boost::detail::tss_cleanup_function> func;
void* value;
tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
void* value_):
func(func_),value(value_)
{}
};
struct thread_data_base;
typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
struct BOOST_THREAD_DECL thread_data_base:
enable_shared_from_this<thread_data_base>
{
thread_data_ptr self;
pthread_t thread_handle;
boost::mutex data_mutex;
boost::condition_variable done_condition;
boost::mutex sleep_mutex;
boost::condition_variable sleep_condition;
bool done;
bool join_started;
bool joined;
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
std::map<void const*,boost::detail::tss_data_node> tss_data;
//#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
pthread_mutex_t* cond_mutex;
pthread_cond_t* current_cond;
//#endif
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
bool interrupt_enabled;
bool interrupt_requested;
//#endif
thread_data_base():
thread_handle(0),
done(false),join_started(false),joined(false),
thread_exit_callbacks(0),
//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
cond_mutex(0),
current_cond(0),
//#endif
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;
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;
pthread_mutex_t* m;
bool set;
void check_for_interruption()
{
#ifndef BOOST_NO_EXCEPTIONS
if(thread_info->interrupt_requested)
{
thread_info->interrupt_requested=false;
throw thread_interrupted(); // BOOST_NO_EXCEPTIONS protected
}
#endif
}
void operator=(interruption_checker&);
public:
explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond):
thread_info(detail::get_current_thread_data()),m(cond_mutex),
set(thread_info && thread_info->interrupt_enabled)
{
if(set)
{
lock_guard<mutex> guard(thread_info->data_mutex);
check_for_interruption();
thread_info->cond_mutex=cond_mutex;
thread_info->current_cond=cond;
BOOST_VERIFY(!pthread_mutex_lock(m));
}
else
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
}
~interruption_checker()
{
if(set)
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
lock_guard<mutex> guard(thread_info->data_mutex);
thread_info->cond_mutex=NULL;
thread_info->current_cond=NULL;
}
else
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
}
}
};
#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)
{
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::no_interruption_point::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<>
#endif
inline void sleep(system_time const& abs_time)
{
return boost::this_thread::hiden::sleep_until(boost::detail::to_timespec(abs_time));
}
template<typename TimeDuration>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
{
this_thread::sleep(get_system_time()+rel_time);
}
#endif // BOOST_THREAD_USES_DATETIME
} // this_thread
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,242 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2008 Anthony Williams
#ifndef THREAD_HEAP_ALLOC_PTHREAD_HPP
#define THREAD_HEAP_ALLOC_PTHREAD_HPP
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
template<typename T>
inline T* heap_new()
{
return new T();
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{
return new T(static_cast<A1&&>(a1));
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1&& a1,A2&& a2)
{
return new T(static_cast<A1&&>(a1),static_cast<A2&&>(a2));
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1&& a1,A2&& a2,A3&& a3)
{
return new T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3));
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1&& a1,A2&& a2,A3&& a3,A4&& a4)
{
return new T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3),static_cast<A4&&>(a4));
}
#else
template<typename T,typename A1>
inline T* heap_new_impl(A1 a1)
{
return new T(a1);
}
template<typename T,typename A1,typename A2>
inline T* heap_new_impl(A1 a1,A2 a2)
{
return new T(a1,a2);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3)
{
return new T(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4)
{
return new T(a1,a2,a3,a4);
}
template<typename T,typename A1>
inline T* heap_new(A1 const& a1)
{
return heap_new_impl<T,A1 const&>(a1);
}
template<typename T,typename A1>
inline T* heap_new(A1& a1)
{
return heap_new_impl<T,A1&>(a1);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2 const& a2)
{
return heap_new_impl<T,A1 const&,A2 const&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1& a1,A2 const& a2)
{
return heap_new_impl<T,A1&,A2 const&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2& a2)
{
return heap_new_impl<T,A1 const&,A2&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1& a1,A2& a2)
{
return heap_new_impl<T,A1&,A2&>(a1,a2);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3)
{
return heap_new_impl<T,A1&,A2&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3)
{
return heap_new_impl<T,A1&,A2 const&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3)
{
return heap_new_impl<T,A1 const&,A2&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2& a2,A3& a3)
{
return heap_new_impl<T,A1&,A2&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
#endif
template<typename T>
inline void heap_delete(T* data)
{
delete data;
}
template<typename T>
struct do_heap_delete
{
void operator()(T* data) const
{
detail::heap_delete(data);
}
};
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,120 @@
#ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP
#define BOOST_THREAD_PTHREAD_TIMESPEC_HPP
// (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
{
#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>
#endif

View File

@@ -0,0 +1,50 @@
#ifndef BOOST_THREAD_SHARED_MUTEX_HPP
#define BOOST_THREAD_SHARED_MUTEX_HPP
// shared_mutex.hpp
//
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#if defined(BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN)
#include <boost/thread/pthread/shared_mutex.hpp>
#else
#include <boost/thread/win32/shared_mutex.hpp>
#endif
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
//#include <boost/thread/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
{
typedef shared_mutex shared_timed_mutex;
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

View File

@@ -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

View File

@@ -0,0 +1,55 @@
#ifndef BOOST_THREAD_TIME_HPP
#define BOOST_THREAD_TIME_HPP
// (C) Copyright 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/date_time/time_clock.hpp>
#include <boost/date_time/microsec_time_clock.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
typedef boost::posix_time::ptime system_time;
inline system_time get_system_time()
{
#if defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
return boost::date_time::microsec_clock<system_time>::universal_time();
#else // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
return boost::date_time::second_clock<system_time>::universal_time();
#endif // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)
}
namespace detail
{
inline system_time get_system_time_sentinel()
{
return system_time(boost::posix_time::pos_infin);
}
inline unsigned long get_milliseconds_until(system_time const& target_time)
{
if(target_time.is_pos_infinity())
{
return ~(unsigned long)0;
}
system_time const now=get_system_time();
if(target_time<=now)
{
return 0;
}
return static_cast<unsigned long>((target_time-now).total_milliseconds()+1);
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,113 @@
#ifndef BOOST_THREAD_TSS_HPP
#define BOOST_THREAD_TSS_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
#include <boost/thread/detail/config.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/detail/thread_heap_alloc.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
struct tss_cleanup_function
{
virtual ~tss_cleanup_function()
{}
virtual void operator()(void* data)=0;
};
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
BOOST_THREAD_DECL void* get_tss_data(void const* key);
}
template <typename T>
class thread_specific_ptr
{
private:
thread_specific_ptr(thread_specific_ptr&);
thread_specific_ptr& operator=(thread_specific_ptr&);
struct delete_data:
detail::tss_cleanup_function
{
void operator()(void* data)
{
delete static_cast<T*>(data);
}
};
struct run_custom_cleanup_function:
detail::tss_cleanup_function
{
void (*cleanup_function)(T*);
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
cleanup_function(cleanup_function_)
{}
void operator()(void* data)
{
cleanup_function(static_cast<T*>(data));
}
};
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
public:
typedef T element_type;
thread_specific_ptr():
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
{}
explicit thread_specific_ptr(void (*func_)(T*))
{
if(func_)
{
cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
}
}
~thread_specific_ptr()
{
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,true);
}
T* get() const
{
return static_cast<T*>(detail::get_tss_data(this));
}
T* operator->() const
{
return get();
}
typename boost::detail::sp_dereference< T >::type operator*() const
{
return *get();
}
T* release()
{
T* const temp=get();
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
return temp;
}
void reset(T* new_value=0)
{
T* const current_value=get();
if(current_value!=new_value)
{
detail::set_tss_data(this,cleanup,new_value,true);
}
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,155 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2011 Vicente J. Botet Escriba
#ifndef BOOST_THREAD_V2_THREAD_HPP
#define BOOST_THREAD_V2_THREAD_HPP
#include <boost/thread/detail/config.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/condition_variable.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;
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)
{
using namespace chrono;
mutex mut;
condition_variable cv;
unique_lock<mutex> lk(mut);
while (Clock::now() < t)
cv.wait_until(lk, t);
}
#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC && defined BOOST_CHRONO_HAS_CLOCK_STEADY
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);
}
}
#elif defined 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)
{
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())
{
//system_clock::time_point c_timeout = time_point_cast<system_clock::duration>(system_clock::now() + ceil<nanoseconds>(d));
system_clock::time_point c_timeout = system_clock::now() + ceil<system_clock::duration>(d);
sleep_until(c_timeout);
}
}
#endif
#endif
}
}
#endif

View File

@@ -0,0 +1,279 @@
#ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
#define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
// basic_timed_mutex_win32.hpp
//
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#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>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
struct basic_timed_mutex
{
BOOST_STATIC_CONSTANT(unsigned char,lock_flag_bit=31);
BOOST_STATIC_CONSTANT(unsigned char,event_set_flag_bit=30);
BOOST_STATIC_CONSTANT(long,lock_flag_value=1<<lock_flag_bit);
BOOST_STATIC_CONSTANT(long,event_set_flag_value=1<<event_set_flag_bit);
long active_count;
void* event;
void initialize()
{
active_count=0;
event=0;
}
void destroy()
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4312)
#endif
void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event,0);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
if(old_event)
{
win32::CloseHandle(old_event);
}
}
bool try_lock() BOOST_NOEXCEPT
{
return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
}
void lock()
{
if(try_lock())
{
return;
}
long old_count=active_count;
mark_waiting_and_try_lock(old_count);
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
do
{
unsigned const retval(win32::WaitForSingleObjectEx(sem, ::boost::detail::win32::infinite,0));
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);
}
while(!lock_acquired);
}
}
void mark_waiting_and_try_lock(long& old_count)
{
for(;;)
{
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;
}
}
void clear_waiting_and_try_lock(long& old_count)
{
old_count&=~lock_flag_value;
old_count|=event_set_flag_value;
for(;;)
{
long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
if(current==old_count)
{
break;
}
old_count=current;
}
}
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(::boost::system_time const& wait_until)
{
if(try_lock())
{
return true;
}
long old_count=active_count;
mark_waiting_and_try_lock(old_count);
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
do
{
if(win32::WaitForSingleObjectEx(sem,::boost::detail::get_milliseconds_until(wait_until),0)!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
}
return true;
}
template<typename Duration>
bool timed_lock(Duration const& timeout)
{
return timed_lock(get_system_time()+timeout);
}
bool timed_lock(boost::xtime const& timeout)
{
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)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
if(try_lock())
{
return true;
}
long old_count=active_count;
mark_waiting_and_try_lock(old_count);
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
do
{
chrono::time_point<chrono::system_clock, chrono::system_clock::duration> now = chrono::system_clock::now();
if (tp<=now) {
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-now);
if(win32::WaitForSingleObjectEx(sem,static_cast<unsigned long>(rel_time.count()),0)!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
clear_waiting_and_try_lock(old_count);
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
}
return true;
}
#endif
void unlock()
{
long const offset=lock_flag_value;
long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
if(!(old_count&event_set_flag_value) && (old_count>offset))
{
if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
{
win32::SetEvent(get_event());
}
}
}
private:
void* get_event()
{
void* current_event=::boost::detail::interlocked_read_acquire(&event);
if(!current_event)
{
void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset);
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4311)
#pragma warning(disable:4312)
#endif
void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
if(old_event!=0)
{
win32::CloseHandle(new_event);
return old_event;
}
else
{
return new_event;
}
}
return current_event;
}
};
}
}
#define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,567 @@
#ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
#define BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/thread_data.hpp>
#include <boost/thread/win32/thread_data.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/thread/cv_status.hpp>
#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>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <limits.h>
#include <algorithm>
#include <vector>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
class basic_cv_list_entry;
void intrusive_ptr_add_ref(basic_cv_list_entry * p);
void intrusive_ptr_release(basic_cv_list_entry * p);
class basic_cv_list_entry
{
private:
detail::win32::handle_manager semaphore;
detail::win32::handle_manager wake_sem;
long waiters;
bool notified;
long references;
public:
BOOST_THREAD_NO_COPYABLE(basic_cv_list_entry)
explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_):
semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)),
wake_sem(wake_sem_.duplicate()),
waiters(1),notified(false),references(0)
{}
static bool no_waiters(boost::intrusive_ptr<basic_cv_list_entry> const& entry)
{
return !detail::interlocked_read_acquire(&entry->waiters);
}
void add_waiter()
{
BOOST_INTERLOCKED_INCREMENT(&waiters);
}
void remove_waiter()
{
BOOST_INTERLOCKED_DECREMENT(&waiters);
}
void release(unsigned count_to_release)
{
notified=true;
detail::win32::ReleaseSemaphore(semaphore,count_to_release,0);
}
void release_waiters()
{
release(detail::interlocked_read_acquire(&waiters));
}
bool is_notified() const
{
return notified;
}
bool wait(timeout abs_time)
{
return this_thread::interruptible_wait(semaphore,abs_time);
}
bool woken()
{
unsigned long const woken_result=detail::win32::WaitForSingleObjectEx(wake_sem,0,0);
BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0));
return woken_result==0;
}
friend void intrusive_ptr_add_ref(basic_cv_list_entry * p);
friend void intrusive_ptr_release(basic_cv_list_entry * p);
};
inline void intrusive_ptr_add_ref(basic_cv_list_entry * p)
{
BOOST_INTERLOCKED_INCREMENT(&p->references);
}
inline void intrusive_ptr_release(basic_cv_list_entry * p)
{
if(!BOOST_INTERLOCKED_DECREMENT(&p->references))
{
delete p;
}
}
class basic_condition_variable
{
boost::mutex internal_mutex;
long total_count;
unsigned active_generation_count;
typedef basic_cv_list_entry list_entry;
typedef boost::intrusive_ptr<list_entry> entry_ptr;
typedef std::vector<entry_ptr> generation_list;
generation_list generations;
detail::win32::handle_manager wake_sem;
void wake_waiters(long count_to_wake)
{
detail::interlocked_write_release(&total_count,total_count-count_to_wake);
detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
}
template<typename lock_type>
struct relocker
{
BOOST_THREAD_NO_COPYABLE(relocker)
lock_type& lock;
bool unlocked;
relocker(lock_type& lock_):
lock(lock_),unlocked(false)
{}
void unlock()
{
lock.unlock();
unlocked=true;
}
~relocker()
{
if(unlocked)
{
lock.lock();
}
}
};
entry_ptr get_wait_entry()
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
if(!wake_sem)
{
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
BOOST_ASSERT(wake_sem);
}
detail::interlocked_write_release(&total_count,total_count+1);
if(generations.empty() || generations.back()->is_notified())
{
entry_ptr new_entry(new list_entry(wake_sem));
generations.push_back(new_entry);
return new_entry;
}
else
{
generations.back()->add_waiter();
return generations.back();
}
}
struct entry_manager
{
entry_ptr const entry;
boost::mutex& internal_mutex;
BOOST_THREAD_NO_COPYABLE(entry_manager)
entry_manager(entry_ptr const& entry_, boost::mutex& mutex_):
entry(entry_), internal_mutex(mutex_)
{}
~entry_manager()
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
entry->remove_waiter();
}
list_entry* operator->()
{
return entry.get();
}
};
protected:
template<typename lock_type>
bool do_wait(lock_type& lock,timeout abs_time)
{
relocker<lock_type> locker(lock);
entry_manager entry(get_wait_entry(), internal_mutex);
locker.unlock();
bool woken=false;
while(!woken)
{
if(!entry->wait(abs_time))
{
return false;
}
woken=entry->woken();
}
return woken;
}
template<typename lock_type,typename predicate_type>
bool do_wait(lock_type& m,timeout const& abs_time,predicate_type pred)
{
while (!pred())
{
if(!do_wait(m, abs_time))
return pred();
}
return true;
}
basic_condition_variable(const basic_condition_variable& other);
basic_condition_variable& operator=(const basic_condition_variable& other);
public:
basic_condition_variable():
total_count(0),active_generation_count(0),wake_sem(0)
{}
~basic_condition_variable()
{}
void notify_one() BOOST_NOEXCEPT
{
if(detail::interlocked_read_acquire(&total_count))
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
if(!total_count)
{
return;
}
wake_waiters(1);
for(generation_list::iterator it=generations.begin(),
end=generations.end();
it!=end;++it)
{
(*it)->release(1);
}
generations.erase(std::remove_if(generations.begin(),generations.end(),&basic_cv_list_entry::no_waiters),generations.end());
}
}
void notify_all() BOOST_NOEXCEPT
{
if(detail::interlocked_read_acquire(&total_count))
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
if(!total_count)
{
return;
}
wake_waiters(total_count);
for(generation_list::iterator it=generations.begin(),
end=generations.end();
it!=end;++it)
{
(*it)->release_waiters();
}
generations.clear();
wake_sem=detail::win32::handle(0);
}
}
};
}
class condition_variable:
private detail::basic_condition_variable
{
public:
BOOST_THREAD_NO_COPYABLE(condition_variable)
condition_variable()
{}
using detail::basic_condition_variable::notify_one;
using detail::basic_condition_variable::notify_all;
void wait(unique_lock<mutex>& m)
{
do_wait(m,detail::timeout::sentinel());
}
template<typename predicate_type>
void wait(unique_lock<mutex>& m,predicate_type pred)
{
while(!pred()) wait(m);
}
#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);
}
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time)
{
return do_wait(m,system_time(abs_time));
}
template<typename duration_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
{
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>
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& abs_time,predicate_type pred)
{
return do_wait(m,abs_time,pred);
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& abs_time,predicate_type pred)
{
return do_wait(m,system_time(abs_time),pred);
}
template<typename duration_type,typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
{
if (wait_duration.is_pos_infinity())
{
while (!pred())
{
wait(m); // or do_wait(m,detail::timeout::sentinel());
}
return true;
}
if (wait_duration.is_special())
{
return pred();
}
return do_wait(m,wait_duration.total_milliseconds(),pred);
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Clock, class Duration>
cv_status
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
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;
}
template <class Rep, class Period>
cv_status
wait_for(
unique_lock<mutex>& lock,
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 :
cv_status::timeout;
}
template <class Clock, class Duration, class Predicate>
bool
wait_until(
unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
}
return true;
}
template <class Rep, class Period, class Predicate>
bool
wait_for(
unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
}
#endif
};
class condition_variable_any:
private detail::basic_condition_variable
{
public:
BOOST_THREAD_NO_COPYABLE(condition_variable_any)
condition_variable_any()
{}
using detail::basic_condition_variable::notify_one;
using detail::basic_condition_variable::notify_all;
template<typename lock_type>
void wait(lock_type& m)
{
do_wait(m,detail::timeout::sentinel());
}
template<typename lock_type,typename predicate_type>
void wait(lock_type& m,predicate_type pred)
{
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)
{
return do_wait(m,abs_time);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::xtime const& abs_time)
{
return do_wait(m,system_time(abs_time));
}
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration)
{
return do_wait(m,wait_duration.total_milliseconds());
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred)
{
return do_wait(m,abs_time,pred);
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred)
{
return do_wait(m,system_time(abs_time),pred);
}
template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
{
return do_wait(m,wait_duration.total_milliseconds(),pred);
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class lock_type, class Clock, class Duration>
cv_status
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
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;
}
template <class lock_type, class Rep, class Period>
cv_status
wait_for(
lock_type& lock,
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 :
cv_status::timeout;
}
template <class lock_type, class Clock, class Duration, class Predicate>
bool
wait_until(
lock_type& lock,
const chrono::time_point<Clock, Duration>& t,
Predicate pred)
{
while (!pred())
{
if (wait_until(lock, t) == cv_status::timeout)
return pred();
}
return true;
}
template <class lock_type, class Rep, class Period, class Predicate>
bool
wait_for(
lock_type& lock,
const chrono::duration<Rep, Period>& d,
Predicate pred)
{
return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred));
}
#endif
};
BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,77 @@
#ifndef BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP
#define BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP
// interlocked_read_win32.hpp
//
// (C) Copyright 2005-8 Anthony Williams
// (C) Copyright 2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/detail/interlocked.hpp>
#include <boost/thread/detail/config.hpp>
#include <boost/config/abi_prefix.hpp>
#ifdef BOOST_MSVC
namespace boost
{
namespace detail
{
// Since VS2005 volatile reads always acquire
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
{
long const res=*x;
return res;
}
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
{
void* const res=*x;
return res;
}
// Since VS2005 volatile writes always release
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
{
*x=value;
}
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
{
*x=value;
}
}
}
#else
namespace boost
{
namespace detail
{
inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT
{
return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0);
}
inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT
{
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
}
inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT
{
BOOST_INTERLOCKED_EXCHANGE(x,value);
}
inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT
{
BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value);
}
}
}
#endif
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,72 @@
#ifndef BOOST_THREAD_WIN32_MUTEX_HPP
#define BOOST_THREAD_WIN32_MUTEX_HPP
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/win32/basic_timed_mutex.hpp>
#include <boost/thread/exceptions.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>
namespace boost
{
namespace detail
{
typedef ::boost::detail::basic_timed_mutex underlying_mutex;
}
class mutex:
public ::boost::detail::underlying_mutex
{
public:
BOOST_THREAD_NO_COPYABLE(mutex)
mutex()
{
initialize();
}
~mutex()
{
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;
class timed_mutex:
public ::boost::detail::basic_timed_mutex
{
public:
BOOST_THREAD_NO_COPYABLE(timed_mutex)
timed_mutex()
{
initialize();
}
~timed_mutex()
{
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
};
}
#include <boost/config/abi_suffix.hpp>
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,903 @@
#ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
// (C) Copyright 2006-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#include <boost/detail/interlocked.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/static_assert.hpp>
#include <limits.h>
#include <boost/thread/thread_time.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#include <boost/chrono/ceil.hpp>
#endif
#include <boost/thread/detail/delete.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class shared_mutex
{
private:
struct state_data
{
unsigned shared_count:11,
shared_waiting:11,
exclusive:1,
upgrade:1,
exclusive_waiting:7,
exclusive_waiting_blocked:1;
friend bool operator==(state_data const& lhs,state_data const& rhs)
{
return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
}
};
template<typename T>
T interlocked_compare_exchange(T* target,T new_value,T comparand)
{
BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long));
long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target),
*reinterpret_cast<long*>(&new_value),
*reinterpret_cast<long*>(&comparand));
return *reinterpret_cast<T const*>(&res);
}
enum
{
unlock_sem = 0,
exclusive_sem = 1
};
state_data state;
detail::win32::handle semaphores[2];
detail::win32::handle upgrade_sem;
void release_waiters(state_data old_state)
{
if(old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
}
if(old_state.shared_waiting || old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
}
}
void release_shared_waiters(state_data old_state)
{
if(old_state.shared_waiting || old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
}
}
public:
BOOST_THREAD_NO_COPYABLE(shared_mutex)
shared_mutex()
{
semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX);
if (!semaphores[exclusive_sem])
{
detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX);
boost::throw_exception(thread_resource_error());
}
upgrade_sem=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX);
if (!upgrade_sem)
{
detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX);
detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX);
boost::throw_exception(thread_resource_error());
}
state_data state_={0,0,0,0,0,0};
state=state_;
}
~shared_mutex()
{
detail::win32::CloseHandle(upgrade_sem);
detail::win32::CloseHandle(semaphores[unlock_sem]);
detail::win32::CloseHandle(semaphores[exclusive_sem]);
}
bool try_lock_shared()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
return !(old_state.exclusive| old_state.exclusive_waiting_blocked);
}
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(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
++new_state.shared_waiting;
if(!new_state.shared_waiting)
{
boost::throw_exception(boost::lock_error());
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
boost::throw_exception(boost::lock_error());
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
unsigned long const res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until), 0);
if(res==detail::win32::timeout)
{
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
if(new_state.shared_waiting)
{
--new_state.shared_waiting;
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
return false;
}
BOOST_ASSERT(res==0);
}
}
#endif
#ifdef BOOST_THREAD_USES_CHRONO
template <class Rep, class Period>
bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
{
return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_shared_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_shared_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
++new_state.shared_waiting;
if(!new_state.shared_waiting)
{
boost::throw_exception(boost::lock_error());
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
boost::throw_exception(boost::lock_error());
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
chrono::system_clock::time_point n = chrono::system_clock::now();
unsigned long res;
if (tp>n) {
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n);
res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],
static_cast<unsigned long>(rel_time.count()), 0);
} else {
res=detail::win32::timeout;
}
if(res==detail::win32::timeout)
{
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
if(new_state.shared_waiting)
{
--new_state.shared_waiting;
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
return false;
}
BOOST_ASSERT(res==0);
}
}
#endif
void unlock_shared()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
if(last_reader)
{
if(new_state.upgrade)
{
new_state.upgrade=false;
new_state.exclusive=true;
}
else
{
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
if(last_reader)
{
if(old_state.upgrade)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0);
}
else
{
release_waiters(old_state);
}
}
break;
}
old_state=current_state;
}
}
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()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
return false;
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
return true;
}
#if defined BOOST_THREAD_USES_DATETIME
bool timed_lock(boost::system_time const& wait_until)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
++new_state.exclusive_waiting;
if(!new_state.exclusive_waiting)
{
boost::throw_exception(boost::lock_error());
}
new_state.exclusive_waiting_blocked=true;
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
#ifndef UNDER_CE
const bool wait_all = true;
#else
const bool wait_all = false;
#endif
unsigned long const wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until), 0);
if(wait_res==detail::win32::timeout)
{
for(;;)
{
bool must_notify = false;
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
if(new_state.exclusive_waiting)
{
if(!--new_state.exclusive_waiting)
{
new_state.exclusive_waiting_blocked=false;
must_notify = true;
}
}
}
else
{
new_state.exclusive=true;
}
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;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
return false;
}
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)
{
return try_lock_until(chrono::steady_clock::now() + rel_time);
}
template <class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
{
using namespace chrono;
system_clock::time_point s_now = system_clock::now();
typename Clock::time_point c_now = Clock::now();
return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
}
template <class Duration>
bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
{
using namespace chrono;
typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
}
bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
++new_state.exclusive_waiting;
if(!new_state.exclusive_waiting)
{
boost::throw_exception(boost::lock_error());
}
new_state.exclusive_waiting_blocked=true;
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
#ifndef UNDER_CE
const bool wait_all = true;
#else
const bool wait_all = false;
#endif
chrono::system_clock::time_point n = chrono::system_clock::now();
unsigned long wait_res;
if (tp>n) {
chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,
static_cast<unsigned long>(rel_time.count()), 0);
} else {
wait_res=detail::win32::timeout;
}
if(wait_res==detail::win32::timeout)
{
for(;;)
{
bool must_notify = false;
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
if(new_state.exclusive_waiting)
{
if(!--new_state.exclusive_waiting)
{
new_state.exclusive_waiting_blocked=false;
must_notify = true;
}
}
}
else
{
new_state.exclusive=true;
}
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;
}
old_state=current_state;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
return false;
}
BOOST_ASSERT(wait_res<2);
}
}
#endif
void unlock()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
new_state.exclusive=false;
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
release_waiters(old_state);
}
void lock_upgrade()
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
{
++new_state.shared_waiting;
if(!new_state.shared_waiting)
{
boost::throw_exception(boost::lock_error());
}
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
boost::throw_exception(boost::lock_error());
}
new_state.upgrade=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade))
{
return;
}
BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],detail::win32::infinite, 0));
}
}
bool try_lock_upgrade()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
{
return false;
}
else
{
++new_state.shared_count;
if(!new_state.shared_count)
{
return false;
}
new_state.upgrade=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
return true;
}
void unlock_upgrade()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
new_state.upgrade=false;
bool const last_reader=!--new_state.shared_count;
new_state.shared_waiting=0;
if(last_reader)
{
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
if(last_reader)
{
release_waiters(old_state);
}
else {
release_shared_waiters(old_state);
}
// #7720
//else {
// release_waiters(old_state);
//}
break;
}
old_state=current_state;
}
}
void unlock_upgrade_and_lock()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
if(last_reader)
{
new_state.upgrade=false;
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
if(!last_reader)
{
BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite, 0));
}
break;
}
old_state=current_state;
}
}
void unlock_and_lock_upgrade()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
new_state.exclusive=false;
new_state.upgrade=true;
++new_state.shared_count;
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
release_waiters(old_state);
}
// bool try_unlock_upgrade_and_lock()
// {
// return false;
// }
//#ifdef BOOST_THREAD_USES_CHRONO
// template <class Rep, class Period>
// bool
// try_unlock_upgrade_and_lock_for(
// const chrono::duration<Rep, Period>& rel_time)
// {
// return try_unlock_upgrade_and_lock_until(
// chrono::steady_clock::now() + rel_time);
// }
// template <class Clock, class Duration>
// bool
// try_unlock_upgrade_and_lock_until(
// const chrono::time_point<Clock, Duration>& abs_time)
// {
// return false;
// }
//#endif
void unlock_and_lock_shared()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
new_state.exclusive=false;
++new_state.shared_count;
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
release_waiters(old_state);
}
void unlock_upgrade_and_lock_shared()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
new_state.upgrade=false;
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
release_waiters(old_state);
}
};
typedef shared_mutex upgrade_mutex;
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,328 @@
#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
#define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2008 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#include <boost/thread/detail/config.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/thread_heap_alloc.hpp>
#include <boost/predef/platform.h>
#include <boost/intrusive_ptr.hpp>
#ifdef BOOST_THREAD_USES_CHRONO
#include <boost/chrono/system_clocks.hpp>
#endif
#include <map>
#include <vector>
#include <utility>
#include <boost/config/abi_prefix.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4251)
#endif
namespace boost
{
class condition_variable;
class mutex;
class thread_attributes {
public:
thread_attributes() BOOST_NOEXCEPT {
val_.stack_size = 0;
//val_.lpThreadAttributes=0;
}
~thread_attributes() {
}
// stack size
void set_stack_size(std::size_t size) BOOST_NOEXCEPT {
val_.stack_size = size;
}
std::size_t get_stack_size() const BOOST_NOEXCEPT {
return val_.stack_size;
}
//void set_security(LPSECURITY_ATTRIBUTES lpThreadAttributes)
//{
// val_.lpThreadAttributes=lpThreadAttributes;
//}
//LPSECURITY_ATTRIBUTES get_security()
//{
// return val_.lpThreadAttributes;
//}
struct win_attrs {
std::size_t stack_size;
//LPSECURITY_ATTRIBUTES lpThreadAttributes;
};
typedef win_attrs native_handle_type;
native_handle_type* native_handle() {return &val_;}
const native_handle_type* native_handle() const {return &val_;}
private:
win_attrs val_;
};
namespace detail
{
struct shared_state_base;
struct tss_cleanup_function;
struct thread_exit_callback_node;
struct tss_data_node
{
boost::shared_ptr<boost::detail::tss_cleanup_function> func;
void* value;
tss_data_node(boost::shared_ptr<boost::detail::tss_cleanup_function> func_,
void* value_):
func(func_),value(value_)
{}
};
struct thread_data_base;
void intrusive_ptr_add_ref(thread_data_base * p);
void intrusive_ptr_release(thread_data_base * p);
struct BOOST_THREAD_DECL thread_data_base
{
long count;
// Win32 threading APIs are not available in store apps so
// use abstraction on top of Windows::System::Threading.
#if BOOST_PLAT_WINDOWS_RUNTIME
detail::win32::scoped_winrt_thread thread_handle;
#else
detail::win32::handle_manager thread_handle;
#endif
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
unsigned id;
std::map<void const*,boost::detail::tss_data_node> tss_data;
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(),
thread_exit_callbacks(0),
id(0),
tss_data(),
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();
friend void intrusive_ptr_add_ref(thread_data_base * p)
{
BOOST_INTERLOCKED_INCREMENT(&p->count);
}
friend void intrusive_ptr_release(thread_data_base * p)
{
if(!BOOST_INTERLOCKED_DECREMENT(&p->count))
{
detail::heap_delete(p);
}
}
#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;
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
{
win32::ticks_type start;
uintmax_t milliseconds;
bool relative;
boost::system_time abs_time;
static unsigned long const max_non_infinite_wait=0xfffffffe;
timeout(uintmax_t milliseconds_):
start(win32::GetTickCount64_()()),
milliseconds(milliseconds_),
relative(true)
//,
// abs_time(boost::get_system_time())
{}
timeout(boost::system_time const& abs_time_):
start(win32::GetTickCount64_()()),
milliseconds(0),
relative(false),
abs_time(abs_time_)
{}
struct BOOST_SYMBOL_VISIBLE remaining_time
{
bool more;
unsigned long milliseconds;
remaining_time(uintmax_t remaining):
more(remaining>max_non_infinite_wait),
milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
{}
};
remaining_time remaining_milliseconds() const
{
if(is_sentinel())
{
return remaining_time(win32::infinite);
}
else if(relative)
{
win32::ticks_type const now=win32::GetTickCount64_()();
win32::ticks_type const elapsed=now-start;
return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
}
else
{
system_time const now=get_system_time();
if(abs_time<=now)
{
return remaining_time(0);
}
return remaining_time((abs_time-now).total_milliseconds()+1);
}
}
bool is_sentinel() const
{
return milliseconds==~uintmax_t(0);
}
static timeout sentinel()
{
return timeout(sentinel_type());
}
private:
struct sentinel_type
{};
explicit timeout(sentinel_type):
start(0),milliseconds(~uintmax_t(0)),relative(true)
{}
};
inline uintmax_t pin_to_zero(intmax_t value)
{
return (value<0)?0u:(uintmax_t)value;
}
}
namespace this_thread
{
void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT;
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
inline void interruptible_wait(uintmax_t milliseconds)
{
interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
}
inline BOOST_SYMBOL_VISIBLE void interruptible_wait(system_time const& abs_time)
{
interruptible_wait(detail::win32::invalid_handle_value,abs_time);
}
template<typename TimeDuration>
inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time)
{
interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
}
inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time)
{
interruptible_wait(abs_time);
}
// #11322 sleep_for() nanoseconds overload will always return too early on windows
//#ifdef BOOST_THREAD_USES_CHRONO
// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns)
// {
// interruptible_wait(chrono::duration_cast<chrono::milliseconds>(ns).count());
// }
//#endif
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);
}
// #11322 sleep_for() nanoseconds overload will always return too early on windows
//#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

View File

@@ -0,0 +1,409 @@
// 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
#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>
namespace boost
{
namespace detail
{
namespace win32
{
using ::GetProcessHeap;
using ::HeapAlloc;
using ::HeapFree;
}
}
}
#else
# ifdef HeapAlloc
# undef HeapAlloc
# endif
namespace boost
{
namespace detail
{
namespace win32
{
extern "C"
{
__declspec(dllimport) handle __stdcall GetProcessHeap();
__declspec(dllimport) void* __stdcall HeapAlloc(handle,unsigned long,ulong_ptr);
__declspec(dllimport) int __stdcall HeapFree(handle,unsigned long,void*);
}
}
}
}
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
inline void* allocate_raw_heap_memory(unsigned size)
{
void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);
if(!heap_memory)
{
boost::throw_exception(std::bad_alloc());
}
return heap_memory;
}
inline void free_raw_heap_memory(void* heap_memory)
{
BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0);
}
template<typename T>
inline T* heap_new()
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
BOOST_TRY
{
T* const data=new (heap_memory) T();
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
BOOST_CATCH_END
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
BOOST_TRY
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1));
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
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));
BOOST_TRY
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2));
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
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));
BOOST_TRY
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3));
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
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));
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;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
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));
BOOST_TRY
{
T* const data=new (heap_memory) T(a1);
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
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));
BOOST_TRY
{
T* const data=new (heap_memory) T(a1,a2);
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
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));
BOOST_TRY
{
T* const data=new (heap_memory) T(a1,a2,a3);
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
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));
BOOST_TRY
{
T* const data=new (heap_memory) T(a1,a2,a3,a4);
return data;
}
BOOST_CATCH(...)
{
free_raw_heap_memory(heap_memory);
BOOST_RETHROW
}
BOOST_CATCH_END
}
template<typename T,typename A1>
inline T* heap_new(A1 const& a1)
{
return heap_new_impl<T,A1 const&>(a1);
}
template<typename T,typename A1>
inline T* heap_new(A1& a1)
{
return heap_new_impl<T,A1&>(a1);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2 const& a2)
{
return heap_new_impl<T,A1 const&,A2 const&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1& a1,A2 const& a2)
{
return heap_new_impl<T,A1&,A2 const&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2& a2)
{
return heap_new_impl<T,A1 const&,A2&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1& a1,A2& a2)
{
return heap_new_impl<T,A1&,A2&>(a1,a2);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3)
{
return heap_new_impl<T,A1&,A2&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3)
{
return heap_new_impl<T,A1&,A2 const&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3)
{
return heap_new_impl<T,A1 const&,A2&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2& a2,A3& a3)
{
return heap_new_impl<T,A1&,A2&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
#endif
template<typename T>
inline void heap_delete(T* data)
{
data->~T();
free_raw_heap_memory(data);
}
template<typename T>
struct do_heap_delete
{
void operator()(T* data) const
{
detail::heap_delete(data);
}
};
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,669 @@
#ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP
#define BOOST_WIN32_THREAD_PRIMITIVES_HPP
// win32_thread_primitives.hpp
//
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2007 David Deakins
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
#include <boost/predef/platform.h>
#include <boost/throw_exception.hpp>
#include <boost/assert.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/detail/interlocked.hpp>
//#include <boost/detail/winapi/synchronization.hpp>
#include <algorithm>
#if BOOST_PLAT_WINDOWS_RUNTIME
#include <thread>
#endif
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
namespace boost
{
namespace detail
{
namespace win32
{
typedef HANDLE handle;
typedef SYSTEM_INFO system_info;
typedef unsigned __int64 ticks_type;
typedef FARPROC farproc_t;
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;
unsigned const create_event_initial_set = 0x00000002;
unsigned const create_event_manual_reset = 0x00000001;
unsigned const event_all_access = EVENT_ALL_ACCESS;
unsigned const semaphore_all_access = SEMAPHORE_ALL_ACCESS;
# ifdef BOOST_NO_ANSI_APIS
# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA
using ::CreateMutexW;
using ::CreateEventW;
using ::CreateSemaphoreW;
# else
using ::CreateMutexExW;
using ::CreateEventExW;
using ::CreateSemaphoreExW;
# endif
using ::OpenEventW;
using ::GetModuleHandleW;
# else
using ::CreateMutexA;
using ::CreateEventA;
using ::OpenEventA;
using ::CreateSemaphoreA;
using ::GetModuleHandleA;
# endif
#if BOOST_PLAT_WINDOWS_RUNTIME
using ::GetNativeSystemInfo;
using ::GetTickCount64;
#else
using ::GetSystemInfo;
using ::GetTickCount;
#endif
using ::CloseHandle;
using ::ReleaseMutex;
using ::ReleaseSemaphore;
using ::SetEvent;
using ::ResetEvent;
using ::WaitForMultipleObjectsEx;
using ::WaitForSingleObjectEx;
using ::GetCurrentProcessId;
using ::GetCurrentThreadId;
using ::GetCurrentThread;
using ::GetCurrentProcess;
using ::DuplicateHandle;
#if !BOOST_PLAT_WINDOWS_RUNTIME
using ::SleepEx;
using ::Sleep;
using ::QueueUserAPC;
using ::GetProcAddress;
#endif
}
}
}
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
# ifdef UNDER_CE
# ifndef WINAPI
# ifndef _WIN32_WCE_EMULATION
# define WINAPI __cdecl // Note this doesn't match the desktop definition
# else
# define WINAPI __stdcall
# endif
# endif
# ifdef __cplusplus
extern "C" {
# endif
typedef int BOOL;
typedef unsigned long DWORD;
typedef void* HANDLE;
# include <kfuncs.h>
# ifdef __cplusplus
}
# endif
# endif
# ifdef __cplusplus
extern "C" {
# endif
struct _SYSTEM_INFO;
# ifdef __cplusplus
}
#endif
namespace boost
{
namespace detail
{
namespace win32
{
# ifdef _WIN64
typedef unsigned __int64 ulong_ptr;
# else
typedef unsigned long ulong_ptr;
# endif
typedef void* handle;
typedef _SYSTEM_INFO system_info;
typedef unsigned __int64 ticks_type;
typedef int (__stdcall *farproc_t)();
unsigned const infinite=~0U;
unsigned const timeout=258U;
handle const invalid_handle_value=(handle)(-1);
unsigned const event_modify_state=2;
unsigned const synchronize=0x100000u;
unsigned const wait_abandoned=0x00000080u;
unsigned const create_event_initial_set = 0x00000002;
unsigned const create_event_manual_reset = 0x00000001;
unsigned const event_all_access = 0x1F0003;
unsigned const semaphore_all_access = 0x1F0003;
extern "C"
{
struct _SECURITY_ATTRIBUTES;
# ifdef BOOST_NO_ANSI_APIS
# if defined(BOOST_USE_WINAPI_VERSION) && ( BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA )
__declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
__declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
# else
__declspec(dllimport) void* __stdcall CreateMutexExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long);
__declspec(dllimport) void* __stdcall CreateEventExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long);
__declspec(dllimport) void* __stdcall CreateSemaphoreExW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*,unsigned long,unsigned long);
# endif
__declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*);
__declspec(dllimport) void* __stdcall GetModuleHandleW(wchar_t const*);
# else
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
__declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*);
__declspec(dllimport) void* __stdcall GetModuleHandleA(char const*);
# endif
#if BOOST_PLAT_WINDOWS_RUNTIME
__declspec(dllimport) void __stdcall GetNativeSystemInfo(_SYSTEM_INFO*);
__declspec(dllimport) ticks_type __stdcall GetTickCount64();
#else
__declspec(dllimport) void __stdcall GetSystemInfo(_SYSTEM_INFO*);
__declspec(dllimport) unsigned long __stdcall GetTickCount();
#endif
__declspec(dllimport) int __stdcall CloseHandle(void*);
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
__declspec(dllimport) unsigned long __stdcall WaitForSingleObjectEx(void*,unsigned long,int);
__declspec(dllimport) unsigned long __stdcall WaitForMultipleObjectsEx(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds,int bAlertable);
__declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
__declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
#if !BOOST_PLAT_WINDOWS_RUNTIME
__declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
__declspec(dllimport) void __stdcall Sleep(unsigned long);
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) farproc_t __stdcall GetProcAddress(void *, const char *);
#endif
# ifndef UNDER_CE
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
__declspec(dllimport) void* __stdcall GetCurrentThread();
__declspec(dllimport) void* __stdcall GetCurrentProcess();
__declspec(dllimport) int __stdcall SetEvent(void*);
__declspec(dllimport) int __stdcall ResetEvent(void*);
# else
using ::GetCurrentProcessId;
using ::GetCurrentThreadId;
using ::GetCurrentThread;
using ::GetCurrentProcess;
using ::SetEvent;
using ::ResetEvent;
# endif
}
}
}
}
#else
# error "Win32 functions not available"
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
namespace win32
{
namespace detail { typedef ticks_type (__stdcall *gettickcount64_t)(); }
#if !BOOST_PLAT_WINDOWS_RUNTIME
extern "C"
{
#ifdef _MSC_VER
long _InterlockedCompareExchange(long volatile *, long, long);
#pragma intrinsic(_InterlockedCompareExchange)
#elif defined(__MINGW64_VERSION_MAJOR)
long _InterlockedCompareExchange(long volatile *, long, long);
#else
// Mingw doesn't provide intrinsics
#define _InterlockedCompareExchange InterlockedCompareExchange
#endif
}
// 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;
}
#else
#endif
inline detail::gettickcount64_t GetTickCount64_()
{
static detail::gettickcount64_t gettickcount64impl;
if(gettickcount64impl)
return gettickcount64impl;
// GetTickCount and GetModuleHandle are not allowed in the Windows Runtime,
// and kernel32 isn't used in Windows Phone.
#if BOOST_PLAT_WINDOWS_RUNTIME
gettickcount64impl = &GetTickCount64;
#else
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;
#endif
return gettickcount64impl;
}
enum event_type
{
auto_reset_event=false,
manual_reset_event=true
};
enum initial_event_state
{
event_initially_reset=false,
event_initially_set=true
};
inline handle create_event(
#if !defined(BOOST_NO_ANSI_APIS)
const char *mutex_name,
#else
const wchar_t *mutex_name,
#endif
event_type type,
initial_event_state state)
{
#if !defined(BOOST_NO_ANSI_APIS)
handle const res = win32::CreateEventA(0, type, state, mutex_name);
#elif defined(BOOST_USE_WINAPI_VERSION) && ( BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA )
handle const res = win32::CreateEventW(0, type, state, mutex_name);
#else
handle const res = win32::CreateEventExW(
0,
mutex_name,
type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0,
event_all_access);
#endif
return res;
}
inline handle create_anonymous_event(event_type type,initial_event_state state)
{
handle const res = create_event(0, type, state);
if(!res)
{
boost::throw_exception(thread_resource_error());
}
return res;
}
inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count)
{
#if !defined(BOOST_NO_ANSI_APIS)
handle const res=win32::CreateSemaphoreA(0,initial_count,max_count,0);
#else
#if defined(BOOST_USE_WINAPI_VERSION) && ( BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA )
handle const res=win32::CreateSemaphoreEx(0,initial_count,max_count,0,0);
#else
handle const res=win32::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access);
#endif
#endif
return res;
}
inline handle create_anonymous_semaphore(long initial_count,long max_count)
{
handle const res=create_anonymous_semaphore_nothrow(initial_count,max_count);
if(!res)
{
boost::throw_exception(thread_resource_error());
}
return res;
}
inline handle duplicate_handle(handle source)
{
handle const current_process=GetCurrentProcess();
long const same_access_flag=2;
handle new_handle=0;
bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
if(!success)
{
boost::throw_exception(thread_resource_error());
}
return new_handle;
}
inline void release_semaphore(handle semaphore,long count)
{
BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
}
inline void get_system_info(system_info *info)
{
#if BOOST_PLAT_WINDOWS_RUNTIME
win32::GetNativeSystemInfo(info);
#else
win32::GetSystemInfo(info);
#endif
}
inline void sleep(unsigned long milliseconds)
{
if(milliseconds == 0)
{
#if BOOST_PLAT_WINDOWS_RUNTIME
std::this_thread::yield();
#else
::boost::detail::win32::Sleep(0);
#endif
}
else
{
#if BOOST_PLAT_WINDOWS_RUNTIME
::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0);
#else
::boost::detail::win32::Sleep(milliseconds);
#endif
}
}
#if BOOST_PLAT_WINDOWS_RUNTIME
class BOOST_THREAD_DECL scoped_winrt_thread
{
public:
scoped_winrt_thread() : m_completionHandle(invalid_handle_value)
{}
~scoped_winrt_thread()
{
if (m_completionHandle != ::boost::detail::win32::invalid_handle_value)
{
CloseHandle(m_completionHandle);
}
}
typedef unsigned(__stdcall * thread_func)(void *);
bool start(thread_func address, void *parameter, unsigned int *thrdId);
handle waitable_handle() const
{
BOOST_ASSERT(m_completionHandle != ::boost::detail::win32::invalid_handle_value);
return m_completionHandle;
}
private:
handle m_completionHandle;
};
#endif
class BOOST_THREAD_DECL handle_manager
{
private:
handle handle_to_manage;
handle_manager(handle_manager&);
handle_manager& operator=(handle_manager&);
void cleanup()
{
if(handle_to_manage && handle_to_manage!=invalid_handle_value)
{
BOOST_VERIFY(CloseHandle(handle_to_manage));
}
}
public:
explicit handle_manager(handle handle_to_manage_):
handle_to_manage(handle_to_manage_)
{}
handle_manager():
handle_to_manage(0)
{}
handle_manager& operator=(handle new_handle)
{
cleanup();
handle_to_manage=new_handle;
return *this;
}
operator handle() const
{
return handle_to_manage;
}
handle duplicate() const
{
return duplicate_handle(handle_to_manage);
}
void swap(handle_manager& other)
{
std::swap(handle_to_manage,other.handle_to_manage);
}
handle release()
{
handle const res=handle_to_manage;
handle_to_manage=0;
return res;
}
bool operator!() const
{
return !handle_to_manage;
}
~handle_manager()
{
cleanup();
}
};
}
}
}
#if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE)
namespace boost
{
namespace detail
{
namespace win32
{
#if _MSC_VER==1400
extern "C" unsigned char _interlockedbittestandset(long *a,long b);
extern "C" unsigned char _interlockedbittestandreset(long *a,long b);
#else
extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b);
extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b);
#endif
#pragma intrinsic(_interlockedbittestandset)
#pragma intrinsic(_interlockedbittestandreset)
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
return _interlockedbittestandset(x,bit)!=0;
}
inline bool interlocked_bit_test_and_reset(long* x,long bit)
{
return _interlockedbittestandreset(x,bit)!=0;
}
}
}
}
#define BOOST_THREAD_BTS_DEFINED
#elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86)
namespace boost
{
namespace detail
{
namespace win32
{
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
#ifndef BOOST_INTEL_CXX_VERSION
__asm {
mov eax,bit;
mov edx,x;
lock bts [edx],eax;
setc al;
};
#else
bool ret;
__asm {
mov eax,bit
mov edx,x
lock bts [edx],eax
setc al
mov ret, al
};
return ret;
#endif
}
inline bool interlocked_bit_test_and_reset(long* x,long bit)
{
#ifndef BOOST_INTEL_CXX_VERSION
__asm {
mov eax,bit;
mov edx,x;
lock btr [edx],eax;
setc al;
};
#else
bool ret;
__asm {
mov eax,bit
mov edx,x
lock btr [edx],eax
setc al
mov ret, al
};
return ret;
#endif
}
}
}
}
#define BOOST_THREAD_BTS_DEFINED
#endif
#ifndef BOOST_THREAD_BTS_DEFINED
namespace boost
{
namespace detail
{
namespace win32
{
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
long const value=1<<bit;
long old=*x;
do
{
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old);
if(current==old)
{
break;
}
old=current;
}
while(true) ;
return (old&value)!=0;
}
inline bool interlocked_bit_test_and_reset(long* x,long bit)
{
long const value=1<<bit;
long old=*x;
do
{
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old);
if(current==old)
{
break;
}
old=current;
}
while(true) ;
return (old&value)!=0;
}
}
}
}
#endif
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,93 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_XTIME_WEK070601_HPP
#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>
#include <boost/date_time/posix_time/conversion.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost {
enum xtime_clock_types
{
TIME_UTC_=1
// TIME_TAI,
// TIME_MONOTONIC,
// TIME_PROCESS,
// TIME_THREAD,
// TIME_LOCAL,
// TIME_SYNC,
// TIME_RESOLUTION
};
struct xtime
{
#if defined(BOOST_NO_INT64_T)
typedef int_fast32_t xtime_sec_t; //INT_FAST32_MIN <= sec <= INT_FAST32_MAX
#else
typedef int_fast64_t xtime_sec_t; //INT_FAST64_MIN <= sec <= INT_FAST64_MAX
#endif
typedef int_fast32_t xtime_nsec_t; //0 <= xtime.nsec < NANOSECONDS_PER_SECOND
xtime_sec_t sec;
xtime_nsec_t nsec;
operator system_time() const
{
return boost::posix_time::from_time_t(0)+
boost::posix_time::seconds(static_cast<long>(sec))+
#ifdef BOOST_DATE_TIME_HAS_NANOSECONDS
boost::posix_time::nanoseconds(nsec);
#else
boost::posix_time::microseconds((nsec+500)/1000);
#endif
}
};
inline xtime get_xtime(boost::system_time const& abs_time)
{
xtime res;
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
res.sec=static_cast<xtime::xtime_sec_t>(time_since_epoch.total_seconds());
res.nsec=static_cast<xtime::xtime_nsec_t>(time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second()));
return res;
}
inline int xtime_get(struct xtime* xtp, int clock_type)
{
if (clock_type == TIME_UTC_)
{
*xtp=get_xtime(get_system_time());
return clock_type;
}
return 0;
}
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
{
if (xt1.sec == xt2.sec)
return (int)(xt1.nsec - xt2.nsec);
else
return (xt1.sec > xt2.sec) ? 1 : -1;
}
} // namespace boost
#include <boost/config/abi_suffix.hpp>
#endif
#endif //BOOST_XTIME_WEK070601_HPP