diff options
Diffstat (limited to 'boost/context/detail')
-rw-r--r-- | boost/context/detail/apply.hpp | 55 | ||||
-rw-r--r-- | boost/context/detail/config.hpp | 59 | ||||
-rw-r--r-- | boost/context/detail/disable_overload.hpp | 40 | ||||
-rw-r--r-- | boost/context/detail/exception.hpp | 36 | ||||
-rw-r--r-- | boost/context/detail/exchange.hpp | 36 | ||||
-rw-r--r-- | boost/context/detail/fcontext.hpp | 46 | ||||
-rw-r--r-- | boost/context/detail/index_sequence.hpp | 72 | ||||
-rw-r--r-- | boost/context/detail/invoke.hpp | 58 | ||||
-rw-r--r-- | boost/context/detail/tuple.hpp | 129 |
9 files changed, 466 insertions, 65 deletions
diff --git a/boost/context/detail/apply.hpp b/boost/context/detail/apply.hpp new file mode 100644 index 0000000000..54db844b9e --- /dev/null +++ b/boost/context/detail/apply.hpp @@ -0,0 +1,55 @@ + +// Copyright Oliver Kowalke 2014. +// 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_CONTEXT_DETAIL_APPLY_H +#define BOOST_CONTEXT_DETAIL_APPLY_H + +#include <functional> +#include <tuple> +#include <type_traits> +#include <utility> + +#include <boost/config.hpp> + +#include <boost/context/detail/config.hpp> +#include <boost/context/detail/invoke.hpp> +#include <boost/context/detail/index_sequence.hpp> + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { +namespace detail { + +template< typename Fn, typename Tpl, std::size_t ... I > +auto +apply_impl( Fn && fn, Tpl && tpl, index_sequence< I ... >) + -> decltype( invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... ) ) +{ + return invoke( std::forward< Fn >( fn), std::get< I >( std::forward< Tpl >( tpl) ) ... ); +} + +template< typename Fn, typename Tpl > +auto +apply( Fn && fn, Tpl && tpl) + -> decltype( apply_impl( std::forward< Fn >( fn), + std::forward< Tpl >( tpl), + make_index_sequence< std::tuple_size< typename std::decay< Tpl >::type >::value >{}) ) +{ + return apply_impl( std::forward< Fn >( fn), + std::forward< Tpl >( tpl), + make_index_sequence< std::tuple_size< typename std::decay< Tpl >::type >::value >{}); +} + +}}} + +#ifdef BOOST_HAS_ABI_HEADERS +#include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_APPLY_H diff --git a/boost/context/detail/config.hpp b/boost/context/detail/config.hpp index 0d5fa757fa..84dd238100 100644 --- a/boost/context/detail/config.hpp +++ b/boost/context/detail/config.hpp @@ -57,32 +57,51 @@ # define BOOST_CONTEXT_SEGMENTS 10 #endif -#undef BOOST_CONTEXT_NO_EXECUTION_CONTEXT -#if defined(BOOST_NO_CXX11_CONSTEXPR) || \ - defined(BOOST_NO_CXX11_DECLTYPE) || \ - defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || \ - defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || \ + +#define BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE +// use rd6 macros for std::integer_sequence +#if defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304 +# undef BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE +#endif +// workaroud: MSVC 14 does not provide macros to test for compile-time integer sequence +#if _MSC_VER > 1800 // _MSC_VER == 1800 -> MS Visual Studio 2013 +# undef BOOST_CONTEXT_NO_INDEX_SEQUENCE +#endif +// workaround: Xcode clang feature detection +#if ! defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence >= 201304 +# if _LIBCPP_STD_VER > 11 +# undef BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE +# endif +#endif + +// workaroud: MSVC 14 does support constexpr +#if _MSC_VER > 1800 // _MSC_VER == 1800 -> MS Visual Studio 2013 +# undef BOOST_NO_CXX11_CONSTEXPR +#endif + +#undef BOOST_CONTEXT_NO_CXX11 +#if defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) || \ + defined(BOOST_NO_CXX11_CONSTEXPR) || \ + defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || \ + defined(BOOST_NO_CXX11_FINAL) || \ defined(BOOST_NO_CXX11_HDR_TUPLE) || \ - defined(BOOST_NO_CXX11_LAMBDAS) || \ defined(BOOST_NO_CXX11_NOEXCEPT) || \ defined(BOOST_NO_CXX11_NULLPTR) || \ - defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || \ defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ - defined(BOOST_NO_CXX11_VARIADIC_MACROS) || \ + defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || \ + defined(BOOST_NO_CXX11_UNIFIED_INITIALISATION_SYNTAX) || \ defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \ - defined(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES) || \ - ! defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence < 201304 -# define BOOST_CONTEXT_NO_EXECUTION_CONTEXT -#endif -// workaroud: MSVC 14 does not provide macros to test for compile-time integer sequence -#if _MSC_VER > 1800 // _MSC_VER == 1800 -> MS Visual Studio 2013 -# undef BOOST_CONTEXT_NO_EXECUTION_CONTEXT + defined(BOOST_NO_HDR_ATOMIC) || \ + defined(BOOST_NO_HDR_TUPLE) +# define BOOST_CONTEXT_NO_CXX11 #endif -// workaround: Xcode clang feature detection -#if ! defined(__cpp_lib_integer_sequence) && __cpp_lib_integer_sequence < 201304 -# if _LIBCPP_STD_VER > 11 -# undef BOOST_CONTEXT_NO_EXECUTION_CONTEXT -# endif + +#if ! defined(BOOST_EXECUTION_CONTEXT) +# if defined(BOOST_USE_SEGMENTED_STACKS) +# define BOOST_EXECUTION_CONTEXT 1 +# else +# define BOOST_EXECUTION_CONTEXT 2 +# endif #endif #endif // BOOST_CONTEXT_DETAIL_CONFIG_H diff --git a/boost/context/detail/disable_overload.hpp b/boost/context/detail/disable_overload.hpp new file mode 100644 index 0000000000..c88f916e39 --- /dev/null +++ b/boost/context/detail/disable_overload.hpp @@ -0,0 +1,40 @@ + +// Copyright Oliver Kowalke 2014. +// 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_CONTEXT_DETAIL_DISABLE_OVERLOAD_H +#define BOOST_CONTEXT_DETAIL_DISABLE_OVERLOAD_H + +#include <type_traits> + +#include <boost/config.hpp> + +#include <boost/context/detail/config.hpp> + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { +namespace detail { + +// http://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/ +template< typename X, typename Y > +using disable_overload = + typename std::enable_if< + ! std::is_base_of< + X, + typename std::decay< Y >::type + >::value + >::type; + +}}} + +#ifdef BOOST_HAS_ABI_HEADERS +#include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_DISABLE_OVERLOAD_H diff --git a/boost/context/detail/exception.hpp b/boost/context/detail/exception.hpp new file mode 100644 index 0000000000..8ffff6780a --- /dev/null +++ b/boost/context/detail/exception.hpp @@ -0,0 +1,36 @@ + +// Copyright Oliver Kowalke 2014. +// 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_CONTEXT_DETAIL_EXCEPTION_H +#define BOOST_CONTEXT_DETAIL_EXCEPTION_H + +#include <boost/config.hpp> + +#include <boost/context/detail/fcontext.hpp> + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { +namespace detail { + +struct forced_unwind { + fcontext_t fctx; + + forced_unwind( fcontext_t fctx_) : + fctx( fctx_) { + } +}; + +}}} + +#ifdef BOOST_HAS_ABI_HEADERS +#include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_EXCEPTION_H diff --git a/boost/context/detail/exchange.hpp b/boost/context/detail/exchange.hpp new file mode 100644 index 0000000000..c5ee91284e --- /dev/null +++ b/boost/context/detail/exchange.hpp @@ -0,0 +1,36 @@ + +// Copyright Oliver Kowalke 2014. +// 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_CONTEXT_DETAIL_EXCHANGE_H +#define BOOST_CONTEXT_DETAIL_EXCHANGE_H + +#include <algorithm> +#include <utility> + +#include <boost/config.hpp> + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { +namespace detail { + +template< typename T, typename U = T > +T exchange( T & t, U && nv) { + T ov = std::move( t); + t = std::forward< U >( nv); + return ov; +} + +}}} + +#ifdef BOOST_HAS_ABI_HEADERS +#include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_EXCHANGE_H diff --git a/boost/context/detail/fcontext.hpp b/boost/context/detail/fcontext.hpp new file mode 100644 index 0000000000..00cb24d941 --- /dev/null +++ b/boost/context/detail/fcontext.hpp @@ -0,0 +1,46 @@ + +// Copyright Oliver Kowalke 2009. +// 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_CONTEXT_DETAIL_FCONTEXT_H +#define BOOST_CONTEXT_DETAIL_FCONTEXT_H + +#include <boost/config.hpp> +#include <boost/cstdint.hpp> + +#include <boost/context/detail/config.hpp> + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { +namespace detail { + +typedef void* fcontext_t; + +struct transfer_t { + fcontext_t fctx; + void * data; +}; + +extern "C" BOOST_CONTEXT_DECL +transfer_t BOOST_CONTEXT_CALLDECL jump_fcontext( fcontext_t const to, void * vp); +extern "C" BOOST_CONTEXT_DECL +fcontext_t BOOST_CONTEXT_CALLDECL make_fcontext( void * sp, std::size_t size, void (* fn)( transfer_t) ); + +// based on an idea of Giovanni Derreta +extern "C" BOOST_CONTEXT_DECL +transfer_t BOOST_CONTEXT_CALLDECL ontop_fcontext( fcontext_t const to, void * vp, transfer_t (* fn)( transfer_t) ); + +}}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_FCONTEXT_H + diff --git a/boost/context/detail/index_sequence.hpp b/boost/context/detail/index_sequence.hpp new file mode 100644 index 0000000000..2d484ba062 --- /dev/null +++ b/boost/context/detail/index_sequence.hpp @@ -0,0 +1,72 @@ + +// Copyright Oliver Kowalke 2014. +// 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_CONTEXT_DETAIL_INDEX_SEQUENCE_H +#define BOOST_CONTEXT_DETAIL_INDEX_SEQUENCE_H + +#include <cstddef> + +#include <boost/config.hpp> + +#include <boost/context/detail/config.hpp> + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { +namespace detail { + +#if ! defined(BOOST_CONTEXT_NO_CXX14_INTEGER_SEQUENCE) +template< std::size_t ... I > +using index_sequence = std::index_sequence< I ... >; +template< std::size_t I > +using make_index_sequence = std::make_index_sequence< I >; +template< typename ... T > +using index_sequence_for = std::index_sequence_for< T ... >; +#else +//http://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence + +template< std::size_t ... I > +struct index_sequence { + using type = index_sequence; + using value_type = std::size_t; + static constexpr std::size_t size() { + return sizeof ... (I); + } +}; + +template< typename Seq1, typename Seq2 > +struct concat_sequence; + +template< std::size_t ... I1, std::size_t ... I2 > +struct concat_sequence< index_sequence< I1 ... >, index_sequence< I2 ... > > : public index_sequence< I1 ..., (sizeof ... (I1)+I2) ... > { +}; + +template< std::size_t I > +struct make_index_sequence : public concat_sequence< typename make_index_sequence< I/2 >::type, + typename make_index_sequence< I-I/2 >::type > { +}; + +template<> +struct make_index_sequence< 0 > : public index_sequence<> { +}; +template<> +struct make_index_sequence< 1 > : public index_sequence< 0 > { +}; + +template< typename ... T > +using index_sequence_for = make_index_sequence< sizeof ... (T) >; +#endif + +}}} + +#ifdef BOOST_HAS_ABI_HEADERS +#include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_INDEX_SEQUENCE_H diff --git a/boost/context/detail/invoke.hpp b/boost/context/detail/invoke.hpp index f63d22c3ff..5ec54800e3 100644 --- a/boost/context/detail/invoke.hpp +++ b/boost/context/detail/invoke.hpp @@ -13,6 +13,8 @@ #include <boost/config.hpp> +#include <boost/context/detail/config.hpp> + #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif @@ -21,61 +23,27 @@ namespace boost { namespace context { namespace detail { -# if _MSC_VER > 1800 +#if _MSC_VER > 1800 using std::invoke; -# else -template< typename Fn, typename ... Args > -typename std::enable_if< - ( ! std::is_member_pointer< Fn >::value && - ! std::is_function< Fn >::value && - ! std::is_function< typename std::remove_pointer< Fn >::type >::value - ), - typename std::result_of< Fn( Args ... ) >::type ->::type -invoke( Fn & fn, Args && ... args) { - return fn( std::forward< Args >( args) ... ); -} - +#else template< typename Fn, typename ... Args > typename std::enable_if< - ( std::is_member_pointer< Fn >::value && - ! std::is_function< Fn >::value && - ! std::is_function< typename std::remove_pointer< Fn >::type >::value - ), - typename std::result_of< Fn( Args ... ) >::type + std::is_member_pointer< typename std::decay< Fn >::type >::value, + typename std::result_of< Fn &&( Args && ... ) >::type >::type -invoke( Fn & fn, Args && ... args) { - return std::mem_fn( fn)( std::forward< Args >( args) ... ); +invoke( Fn && fn, Args && ... args) { + return std::mem_fn( fn)( std::forward< Args >( args) ... ); } template< typename Fn, typename ... Args > typename std::enable_if< - ( std::is_pointer< Fn >::value && - std::is_function< typename std::remove_pointer< Fn >::type >::value - ), - typename std::result_of< Fn( Args ... ) >::type + ! std::is_member_pointer< typename std::decay< Fn >::type >::value, + typename std::result_of< Fn &&( Args && ... ) >::type >::type -invoke( Fn fn, Args && ... args) { - return fn( std::forward< Args >( args) ... ); -} -# endif - -template< typename Fn, typename Tpl, std::size_t... I > -decltype( auto) do_invoke( Fn && fn, Tpl && tpl, std::index_sequence< I ... >) { - return invoke( fn, - // std::tuple_element<> does not perfect forwarding - std::forward< decltype( std::get< I >( std::declval< typename std::decay< Tpl >::type >() ) ) >( - std::get< I >( std::forward< typename std::decay< Tpl >::type >( tpl) ) ) ... ); -} - - -template< typename Fn, typename Tpl > -decltype( auto) do_invoke( Fn && fn, Tpl && tpl) { - constexpr auto Size = std::tuple_size< typename std::decay< Tpl >::type >::value; - return do_invoke( std::forward< Fn >( fn), - std::forward< Tpl >( tpl), - std::make_index_sequence< Size >{}); +invoke( Fn && fn, Args && ... args) { + return std::forward< Fn >( fn)( std::forward< Args >( args) ... ); } +#endif }}} diff --git a/boost/context/detail/tuple.hpp b/boost/context/detail/tuple.hpp new file mode 100644 index 0000000000..e1b2f867a7 --- /dev/null +++ b/boost/context/detail/tuple.hpp @@ -0,0 +1,129 @@ + +// Copyright Oliver Kowalke 2014. +// 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_CONTEXT_DETAIL_TUPLE_H +#define BOOST_CONTEXT_DETAIL_TUPLE_H + +#include <tuple> +#include <utility> + +#include <boost/config.hpp> + +#include <boost/context/detail/config.hpp> +#include <boost/context/detail/index_sequence.hpp> + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace context { +namespace detail { + +template< typename ... S, typename ... T, std::size_t ... I > +void +head_impl( std::tuple< S ... > & s, + std::tuple< T ... > & t, index_sequence< I ... >) { + t = std::tuple< T ... >{ std::get< I >( s) ... }; +} + +template< typename ... S, typename ... T, std::size_t ... I > +void +head_impl( std::tuple< S ... > && s, + std::tuple< T ... > & t, index_sequence< I ... >) { + t = std::tuple< T ... >{ std::get< I >( std::move( s) ) ... }; +} + +template< typename ... S, std::size_t ... I1, typename ... T, std::size_t ... I2 > +void +tail_impl( std::tuple< S ... > & s, index_sequence< I1 ... >, + std::tuple< T ... > & t, index_sequence< I2 ... >) { + constexpr std::size_t Idx = (sizeof...(I1)) - (sizeof...(I2)); + t = std::tuple< T ... >{ std::get< (Idx + I2) >( s) ... }; +} + +template< typename ... S, std::size_t ... I1, typename ... T, std::size_t ... I2 > +void +tail_impl( std::tuple< S ... > && s, index_sequence< I1 ... >, + std::tuple< T ... > & t, index_sequence< I2 ... >) { + constexpr std::size_t Idx = (sizeof...(I1)) - (sizeof...(I2)); + t = std::tuple< T ... >{ std::get< (Idx + I2) >( std::move( s) ) ... }; +} + +template< typename ... T > +class tuple_head; + +template< typename ... T > +class tuple_head< std::tuple< T ... > > { +private: + std::tuple< T ... > & t_; + +public: + tuple_head( std::tuple< T ... > & t) noexcept : + t_( t) { + } + + template< typename ... S > + void operator=( std::tuple< S ... > & s) { + static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size"); + head_impl( s, + t_, index_sequence_for< T ... >{} ); + } + template< typename ... S > + void operator=( std::tuple< S ... > && s) { + static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size"); + head_impl( std::move( s), + t_, index_sequence_for< T ... >{} ); + } +}; + +template< typename ... T > +class tuple_tail; + +template< typename ... T > +class tuple_tail< std::tuple< T ... > > { +private: + std::tuple< T ... > & t_; + +public: + tuple_tail( std::tuple< T ... > & t) noexcept : + t_( t) { + } + + template< typename ... S > + void operator=( std::tuple< S ... > & s) { + static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size"); + tail_impl( s, index_sequence_for< S ... >{}, + t_, index_sequence_for< T ... >{} ); + } + + template< typename ... S > + void operator=( std::tuple< S ... > && s) { + static_assert((sizeof...(T)) <= (sizeof...(S)), "invalid tuple size"); + tail_impl( std::move( s), index_sequence_for< S ... >{}, + t_, index_sequence_for< T ... >{} ); + } +}; + +template< typename ... T > +detail::tuple_head< std::tuple< T ... > > +head( std::tuple< T ... > & tpl) { + return tuple_head< std::tuple< T ... > >{ tpl }; +} + +template< typename ... T > +detail::tuple_tail< std::tuple< T ... > > +tail( std::tuple< T ... > & tpl) { + return tuple_tail< std::tuple< T ... > >{ tpl }; +} + +}}} + +#ifdef BOOST_HAS_ABI_HEADERS +#include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_CONTEXT_DETAIL_TUPLE_H |