diff options
Diffstat (limited to 'boost/lockfree')
-rw-r--r-- | boost/lockfree/detail/atomic.hpp | 6 | ||||
-rw-r--r-- | boost/lockfree/detail/copy_payload.hpp | 2 | ||||
-rw-r--r-- | boost/lockfree/detail/freelist.hpp | 8 | ||||
-rw-r--r-- | boost/lockfree/detail/parameter.hpp | 7 | ||||
-rw-r--r-- | boost/lockfree/detail/prefix.hpp | 40 | ||||
-rw-r--r-- | boost/lockfree/detail/tagged_ptr.hpp | 2 | ||||
-rw-r--r-- | boost/lockfree/detail/tagged_ptr_dcas.hpp | 11 | ||||
-rw-r--r-- | boost/lockfree/detail/tagged_ptr_ptrcompression.hpp | 6 | ||||
-rw-r--r-- | boost/lockfree/lockfree_forward.hpp | 72 | ||||
-rw-r--r-- | boost/lockfree/policies.hpp | 4 | ||||
-rw-r--r-- | boost/lockfree/queue.hpp | 19 | ||||
-rw-r--r-- | boost/lockfree/spsc_queue.hpp | 30 | ||||
-rw-r--r-- | boost/lockfree/stack.hpp | 239 |
13 files changed, 365 insertions, 81 deletions
diff --git a/boost/lockfree/detail/atomic.hpp b/boost/lockfree/detail/atomic.hpp index d15474ada9..6083800f0f 100644 --- a/boost/lockfree/detail/atomic.hpp +++ b/boost/lockfree/detail/atomic.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2013 Tim Blechmann +// Copyright (C) 2011-2013, 2016 Tim Blechmann // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -51,7 +51,7 @@ #endif // BOOST_LOCKFREE_FORCE_STD_ATOMIC -#if defined(BOOST_LOCKFREE_NO_HDR_ATOMIC) +#if defined(BOOST_LOCKFREE_NO_HDR_ATOMIC) || defined(BOOST_LOCKFREE_FORCE_BOOST_ATOMIC) #include <boost/atomic.hpp> #else #include <atomic> @@ -61,7 +61,7 @@ namespace boost { namespace lockfree { namespace detail { -#if defined(BOOST_LOCKFREE_NO_HDR_ATOMIC) +#if defined(BOOST_LOCKFREE_NO_HDR_ATOMIC) || defined(BOOST_LOCKFREE_FORCE_BOOST_ATOMIC) using boost::atomic; using boost::memory_order_acquire; using boost::memory_order_consume; diff --git a/boost/lockfree/detail/copy_payload.hpp b/boost/lockfree/detail/copy_payload.hpp index 75b1b52a2b..5972da7c64 100644 --- a/boost/lockfree/detail/copy_payload.hpp +++ b/boost/lockfree/detail/copy_payload.hpp @@ -1,6 +1,6 @@ // boost lockfree: copy_payload helper // -// Copyright (C) 2011 Tim Blechmann +// Copyright (C) 2011, 2016 Tim Blechmann // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/boost/lockfree/detail/freelist.hpp b/boost/lockfree/detail/freelist.hpp index 3a134e29b9..48dbb508f5 100644 --- a/boost/lockfree/detail/freelist.hpp +++ b/boost/lockfree/detail/freelist.hpp @@ -49,6 +49,7 @@ class freelist_stack: typedef tagged_ptr<freelist_node> tagged_node_ptr; public: + typedef T * index_t; typedef tagged_ptr<T> tagged_node_handle; template <typename Allocator> @@ -254,7 +255,9 @@ private: atomic<tagged_node_ptr> pool_; }; -class tagged_index +class +BOOST_ALIGNMENT( 4 ) // workaround for bugs in MSVC +tagged_index { public: typedef boost::uint16_t tag_t; @@ -396,8 +399,6 @@ class fixed_size_freelist: tagged_index next; }; - typedef tagged_index::index_t index_t; - void initialize(void) { T * nodes = NodeStorage::nodes(); @@ -415,6 +416,7 @@ class fixed_size_freelist: public: typedef tagged_index tagged_node_handle; + typedef tagged_index::index_t index_t; template <typename Allocator> fixed_size_freelist (Allocator const & alloc, std::size_t count): diff --git a/boost/lockfree/detail/parameter.hpp b/boost/lockfree/detail/parameter.hpp index 2e2b068bed..e5db1206e5 100644 --- a/boost/lockfree/detail/parameter.hpp +++ b/boost/lockfree/detail/parameter.hpp @@ -1,6 +1,6 @@ // boost lockfree // -// Copyright (C) 2011 Tim Blechmann +// Copyright (C) 2011, 2016 Tim Blechmann // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -10,6 +10,11 @@ #define BOOST_LOCKFREE_DETAIL_PARAMETER_HPP #include <boost/lockfree/policies.hpp> +#include <boost/parameter/parameters.hpp> +#include <boost/parameter/binding.hpp> + +#include <boost/mpl/void.hpp> + namespace boost { namespace lockfree { diff --git a/boost/lockfree/detail/prefix.hpp b/boost/lockfree/detail/prefix.hpp index 6ed9446cb0..0c9f29af16 100644 --- a/boost/lockfree/detail/prefix.hpp +++ b/boost/lockfree/detail/prefix.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2009 Tim Blechmann +// Copyright (C) 2009, 2016 Tim Blechmann // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -11,46 +11,14 @@ BOOST_LOCKFREE_CACHELINE_BYTES: size of a cache line BOOST_LOCKFREE_PTR_COMPRESSION: use tag/pointer compression to utilize parts of the virtual address space as tag (at least 16bit) - BOOST_LOCKFREE_DCAS_ALIGNMENT: symbol used for aligning structs at cache line - boundaries */ #define BOOST_LOCKFREE_CACHELINE_BYTES 64 -#ifdef _MSC_VER +#include <boost/predef.h> -#define BOOST_LOCKFREE_CACHELINE_ALIGNMENT __declspec(align(BOOST_LOCKFREE_CACHELINE_BYTES)) - -#if defined(_M_IX86) - #define BOOST_LOCKFREE_DCAS_ALIGNMENT -#elif defined(_M_X64) || defined(_M_IA64) - #define BOOST_LOCKFREE_PTR_COMPRESSION 1 - #define BOOST_LOCKFREE_DCAS_ALIGNMENT __declspec(align(16)) -#endif - -#endif /* _MSC_VER */ - -#ifdef __GNUC__ - -#define BOOST_LOCKFREE_CACHELINE_ALIGNMENT __attribute__((aligned(BOOST_LOCKFREE_CACHELINE_BYTES))) - -#if defined(__i386__) || defined(__ppc__) - #define BOOST_LOCKFREE_DCAS_ALIGNMENT -#elif defined(__x86_64__) - #define BOOST_LOCKFREE_PTR_COMPRESSION 1 - #define BOOST_LOCKFREE_DCAS_ALIGNMENT __attribute__((aligned(16))) -#elif defined(__alpha__) - // LATER: alpha may benefit from pointer compression. but what is the maximum size of the address space? - #define BOOST_LOCKFREE_DCAS_ALIGNMENT -#endif -#endif /* __GNUC__ */ - -#ifndef BOOST_LOCKFREE_DCAS_ALIGNMENT -#define BOOST_LOCKFREE_DCAS_ALIGNMENT /*BOOST_LOCKFREE_DCAS_ALIGNMENT*/ -#endif - -#ifndef BOOST_LOCKFREE_CACHELINE_ALIGNMENT -#define BOOST_LOCKFREE_CACHELINE_ALIGNMENT /*BOOST_LOCKFREE_CACHELINE_ALIGNMENT*/ +#ifdef BOOST_ARCH_X86_64 +#define BOOST_LOCKFREE_PTR_COMPRESSION 1 #endif #endif /* BOOST_LOCKFREE_PREFIX_HPP_INCLUDED */ diff --git a/boost/lockfree/detail/tagged_ptr.hpp b/boost/lockfree/detail/tagged_ptr.hpp index f70a2c751a..10ab2e9126 100644 --- a/boost/lockfree/detail/tagged_ptr.hpp +++ b/boost/lockfree/detail/tagged_ptr.hpp @@ -1,6 +1,6 @@ // tagged pointer, for aba prevention // -// Copyright (C) 2008 Tim Blechmann +// Copyright (C) 2008, 2016 Tim Blechmann // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/boost/lockfree/detail/tagged_ptr_dcas.hpp b/boost/lockfree/detail/tagged_ptr_dcas.hpp index 6cb5a0616b..83718daea2 100644 --- a/boost/lockfree/detail/tagged_ptr_dcas.hpp +++ b/boost/lockfree/detail/tagged_ptr_dcas.hpp @@ -1,6 +1,6 @@ // tagged pointer, for aba prevention // -// Copyright (C) 2008 Tim Blechmann +// Copyright (C) 2008, 2016 Tim Blechmann // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -12,13 +12,16 @@ #include <cstddef> /* for std::size_t */ #include <limits> +#include <boost/predef.h> -namespace boost { +namespace boost { namespace lockfree { -namespace detail { +namespace detail { + + template <class T> -class BOOST_LOCKFREE_DCAS_ALIGNMENT tagged_ptr +class BOOST_ALIGNMENT(2 * sizeof(void*)) tagged_ptr { public: typedef std::size_t tag_t; diff --git a/boost/lockfree/detail/tagged_ptr_ptrcompression.hpp b/boost/lockfree/detail/tagged_ptr_ptrcompression.hpp index 15d383018c..bcf6e34f6b 100644 --- a/boost/lockfree/detail/tagged_ptr_ptrcompression.hpp +++ b/boost/lockfree/detail/tagged_ptr_ptrcompression.hpp @@ -1,6 +1,6 @@ // tagged pointer, for aba prevention // -// Copyright (C) 2008, 2009 Tim Blechmann, based on code by Cory Nelson +// Copyright (C) 2008, 2009, 2016 Tim Blechmann, based on code by Cory Nelson // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -13,13 +13,13 @@ #include <limits> #include <boost/cstdint.hpp> - +#include <boost/predef.h> namespace boost { namespace lockfree { namespace detail { -#if defined (__x86_64__) || defined (_M_X64) +#ifdef BOOST_ARCH_X86_64 template <class T> class tagged_ptr diff --git a/boost/lockfree/lockfree_forward.hpp b/boost/lockfree/lockfree_forward.hpp new file mode 100644 index 0000000000..b1d72b32d2 --- /dev/null +++ b/boost/lockfree/lockfree_forward.hpp @@ -0,0 +1,72 @@ +// Copyright (C) 2008-2016 Tim Blechmann +// +// 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_LOCKFREE_FORWARD_HPP_INCLUDED +#define BOOST_LOCKFREE_FORWARD_HPP_INCLUDED + + +#ifndef BOOST_DOXYGEN_INVOKED + +#include <cstddef> // size_t + +#include <boost/config.hpp> + +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES +#include <boost/parameter/aux_/void.hpp> +#endif + +namespace boost { +namespace lockfree { + +// policies +template <bool IsFixedSized> +struct fixed_sized; + +template <size_t Size> +struct capacity; + +template <class Alloc> +struct allocator; + + +// data structures + +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES +template <typename T, + class A0 = boost::parameter::void_, + class A1 = boost::parameter::void_, + class A2 = boost::parameter::void_> +#else +template <typename T, typename ...Options> +#endif +class queue; + +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES +template <typename T, + class A0 = boost::parameter::void_, + class A1 = boost::parameter::void_, + class A2 = boost::parameter::void_> +#else +template <typename T, typename ...Options> +#endif +class stack; + +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES +template <typename T, + class A0 = boost::parameter::void_, + class A1 = boost::parameter::void_> +#else +template <typename T, typename ...Options> +#endif +class spsc_queue; + +} +} + +#endif // BOOST_DOXYGEN_INVOKED + +#endif // BOOST_LOCKFREE_FORWARD_HPP_INCLUDED diff --git a/boost/lockfree/policies.hpp b/boost/lockfree/policies.hpp index cec9b57f89..cf43ad22f3 100644 --- a/boost/lockfree/policies.hpp +++ b/boost/lockfree/policies.hpp @@ -9,10 +9,9 @@ #ifndef BOOST_LOCKFREE_POLICIES_HPP_INCLUDED #define BOOST_LOCKFREE_POLICIES_HPP_INCLUDED -#include <boost/parameter.hpp> +#include <boost/parameter/aux_/template_keyword.hpp> #include <boost/mpl/bool.hpp> #include <boost/mpl/size_t.hpp> -#include <boost/mpl/void.hpp> namespace boost { namespace lockfree { @@ -56,4 +55,3 @@ struct allocator: } #endif /* BOOST_LOCKFREE_POLICIES_HPP_INCLUDED */ - diff --git a/boost/lockfree/queue.hpp b/boost/lockfree/queue.hpp index 4c982c4dd4..aa46f54229 100644 --- a/boost/lockfree/queue.hpp +++ b/boost/lockfree/queue.hpp @@ -15,7 +15,7 @@ #include <boost/static_assert.hpp> #include <boost/type_traits/has_trivial_assign.hpp> #include <boost/type_traits/has_trivial_destructor.hpp> -#include <boost/config.hpp> // for BOOST_LIKELY +#include <boost/config.hpp> // for BOOST_LIKELY & BOOST_ALIGNMENT #include <boost/lockfree/detail/atomic.hpp> #include <boost/lockfree/detail/copy_payload.hpp> @@ -23,6 +23,8 @@ #include <boost/lockfree/detail/parameter.hpp> #include <boost/lockfree/detail/tagged_ptr.hpp> +#include <boost/lockfree/lockfree_forward.hpp> + #ifdef BOOST_HAS_PRAGMA_ONCE #pragma once #endif @@ -70,13 +72,10 @@ typedef parameter::parameters<boost::parameter::optional<tag::allocator>, * - T must have a trivial destructor * * */ -#ifndef BOOST_DOXYGEN_INVOKED -template <typename T, - class A0 = boost::parameter::void_, - class A1 = boost::parameter::void_, - class A2 = boost::parameter::void_> +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES +template <typename T, class A0, class A1, class A2> #else -template <typename T, ...Options> +template <typename T, typename ...Options> #endif class queue { @@ -91,7 +90,11 @@ private: BOOST_STATIC_ASSERT((boost::has_trivial_assign<T>::value)); #endif +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES typedef typename detail::queue_signature::bind<A0, A1, A2>::type bound_args; +#else + typedef typename detail::queue_signature::bind<Options...>::type bound_args; +#endif static const bool has_capacity = detail::extract_capacity<bound_args>::has_capacity; static const size_t capacity = detail::extract_capacity<bound_args>::capacity + 1; // the queue uses one dummy node @@ -99,7 +102,7 @@ private: static const bool node_based = !(has_capacity || fixed_sized); static const bool compile_time_sized = has_capacity; - struct BOOST_LOCKFREE_CACHELINE_ALIGNMENT node + struct BOOST_ALIGNMENT(BOOST_LOCKFREE_CACHELINE_BYTES) node { typedef typename detail::select_tagged_handle<node, node_based>::tagged_handle_type tagged_node_handle; typedef typename detail::select_tagged_handle<node, node_based>::handle_type handle_type; diff --git a/boost/lockfree/spsc_queue.hpp b/boost/lockfree/spsc_queue.hpp index 5ecfb2a21e..7903d2cdf3 100644 --- a/boost/lockfree/spsc_queue.hpp +++ b/boost/lockfree/spsc_queue.hpp @@ -28,6 +28,8 @@ #include <boost/lockfree/detail/parameter.hpp> #include <boost/lockfree/detail/prefix.hpp> +#include <boost/lockfree/lockfree_forward.hpp> + #ifdef BOOST_HAS_PRAGMA_ONCE #pragma once #endif @@ -626,10 +628,18 @@ public: } }; +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES template <typename T, typename A0, typename A1> +#else +template <typename T, typename ...Options> +#endif struct make_ringbuffer { +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES typedef typename ringbuffer_signature::bind<A0, A1>::type bound_args; +#else + typedef typename ringbuffer_signature::bind<Options...>::type bound_args; +#endif typedef extract_capacity<bound_args> extract_capacity_t; @@ -669,22 +679,32 @@ struct make_ringbuffer * - T must have a default constructor * - T must be copyable * */ -#ifndef BOOST_DOXYGEN_INVOKED -template <typename T, - class A0 = boost::parameter::void_, - class A1 = boost::parameter::void_> +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES +template <typename T, class A0, class A1> #else -template <typename T, ...Options> +template <typename T, typename ...Options> #endif class spsc_queue: +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES public detail::make_ringbuffer<T, A0, A1>::ringbuffer_type +#else + public detail::make_ringbuffer<T, Options...>::ringbuffer_type +#endif { private: #ifndef BOOST_DOXYGEN_INVOKED + +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES typedef typename detail::make_ringbuffer<T, A0, A1>::ringbuffer_type base_type; static const bool runtime_sized = detail::make_ringbuffer<T, A0, A1>::runtime_sized; typedef typename detail::make_ringbuffer<T, A0, A1>::allocator allocator_arg; +#else + typedef typename detail::make_ringbuffer<T, Options...>::ringbuffer_type base_type; + static const bool runtime_sized = detail::make_ringbuffer<T, Options...>::runtime_sized; + typedef typename detail::make_ringbuffer<T, Options...>::allocator allocator_arg; +#endif + struct implementation_defined { diff --git a/boost/lockfree/stack.hpp b/boost/lockfree/stack.hpp index 6db986c87b..23488b1ad0 100644 --- a/boost/lockfree/stack.hpp +++ b/boost/lockfree/stack.hpp @@ -9,11 +9,11 @@ #include <boost/assert.hpp> #include <boost/checked_delete.hpp> +#include <boost/core/no_exceptions_support.hpp> #include <boost/integer_traits.hpp> #include <boost/static_assert.hpp> #include <boost/tuple/tuple.hpp> -#include <boost/type_traits/has_trivial_assign.hpp> -#include <boost/type_traits/has_trivial_destructor.hpp> +#include <boost/type_traits/is_copy_constructible.hpp> #include <boost/lockfree/detail/atomic.hpp> #include <boost/lockfree/detail/copy_payload.hpp> @@ -21,6 +21,8 @@ #include <boost/lockfree/detail/parameter.hpp> #include <boost/lockfree/detail/tagged_ptr.hpp> +#include <boost/lockfree/lockfree_forward.hpp> + #ifdef BOOST_HAS_PRAGMA_ONCE #pragma once #endif @@ -58,22 +60,22 @@ typedef parameter::parameters<boost::parameter::optional<tag::allocator>, * \b Requirements: * - T must have a copy constructor * */ -#ifndef BOOST_DOXYGEN_INVOKED -template <typename T, - class A0 = boost::parameter::void_, - class A1 = boost::parameter::void_, - class A2 = boost::parameter::void_> +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES +template <typename T, class A0, class A1, class A2> #else -template <typename T, ...Options> +template <typename T, typename ...Options> #endif class stack { private: #ifndef BOOST_DOXYGEN_INVOKED - BOOST_STATIC_ASSERT(boost::has_trivial_assign<T>::value); - BOOST_STATIC_ASSERT(boost::has_trivial_destructor<T>::value); + BOOST_STATIC_ASSERT(boost::is_copy_constructible<T>::value); +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES typedef typename detail::stack_signature::bind<A0, A1, A2>::type bound_args; +#else + typedef typename detail::stack_signature::bind<Options...>::type bound_args; +#endif static const bool has_capacity = detail::extract_capacity<bound_args>::has_capacity; static const size_t capacity = detail::extract_capacity<bound_args>::capacity; @@ -253,7 +255,7 @@ private: node * new_top_node = end_node; end_node->next = NULL; - try { + BOOST_TRY { /* link nodes */ for (; it != end; ++it) { node * newnode = pool.template construct<Threadsafe, Bounded>(*it); @@ -262,14 +264,16 @@ private: newnode->next = new_top_node; new_top_node = newnode; } - } catch (...) { + } BOOST_CATCH (...) { for (node * current_node = new_top_node; current_node != NULL;) { node * next = current_node->next; pool.template destruct<Threadsafe>(current_node); current_node = next; } - throw; + BOOST_RETHROW; } + BOOST_CATCH_END + ret = it; return make_tuple(new_top_node, end_node); } @@ -555,6 +559,215 @@ public: return element_count; } + /** consumes all elements via a functor + * + * atomically pops all elements from the stack and applies the functor on each object + * + * \returns number of elements that are consumed + * + * \note Thread-safe and non-blocking, if functor is thread-safe and non-blocking + * */ + template <typename Functor> + size_t consume_all_atomic(Functor & f) + { + size_t element_count = 0; + tagged_node_handle old_tos = tos.load(detail::memory_order_consume); + + for (;;) { + node * old_tos_pointer = pool.get_pointer(old_tos); + if (!old_tos_pointer) + return 0; + + tagged_node_handle new_tos(typename pool_t::index_t(NULL), old_tos.get_next_tag()); + + if (tos.compare_exchange_weak(old_tos, new_tos)) + break; + } + + tagged_node_handle nodes_to_consume = old_tos; + + for(;;) { + node * node_pointer = pool.get_pointer(nodes_to_consume); + f(node_pointer->v); + element_count += 1; + + node * next_node = pool.get_pointer(node_pointer->next); + + if (!next_node) { + pool.template destruct<true>(nodes_to_consume); + break; + } + + tagged_node_handle next(pool.get_handle(next_node), nodes_to_consume.get_next_tag()); + pool.template destruct<true>(nodes_to_consume); + nodes_to_consume = next; + } + + return element_count; + } + + /// \copydoc boost::lockfree::stack::consume_all_atomic(Functor & rhs) + template <typename Functor> + size_t consume_all_atomic(Functor const & f) + { + size_t element_count = 0; + tagged_node_handle old_tos = tos.load(detail::memory_order_consume); + + for (;;) { + node * old_tos_pointer = pool.get_pointer(old_tos); + if (!old_tos_pointer) + return 0; + + tagged_node_handle new_tos(typename pool_t::index_t(NULL), old_tos.get_next_tag()); + + if (tos.compare_exchange_weak(old_tos, new_tos)) + break; + } + + tagged_node_handle nodes_to_consume = old_tos; + + for(;;) { + node * node_pointer = pool.get_pointer(nodes_to_consume); + f(node_pointer->v); + element_count += 1; + + node * next_node = pool.get_pointer(node_pointer->next); + + if (!next_node) { + pool.template destruct<true>(nodes_to_consume); + break; + } + + tagged_node_handle next(pool.get_handle(next_node), nodes_to_consume.get_next_tag()); + pool.template destruct<true>(nodes_to_consume); + nodes_to_consume = next; + } + + return element_count; + } + + /** consumes all elements via a functor + * + * atomically pops all elements from the stack and applies the functor on each object in reversed order + * + * \returns number of elements that are consumed + * + * \note Thread-safe and non-blocking, if functor is thread-safe and non-blocking + * */ + template <typename Functor> + size_t consume_all_atomic_reversed(Functor & f) + { + size_t element_count = 0; + tagged_node_handle old_tos = tos.load(detail::memory_order_consume); + + for (;;) { + node * old_tos_pointer = pool.get_pointer(old_tos); + if (!old_tos_pointer) + return 0; + + tagged_node_handle new_tos(pool.null_handle(), old_tos.get_next_tag()); + + if (tos.compare_exchange_weak(old_tos, new_tos)) + break; + } + + tagged_node_handle nodes_to_consume = old_tos; + + node * last_node_pointer = NULL; + tagged_node_handle nodes_in_reversed_order; + for(;;) { + node * node_pointer = pool.get_pointer(nodes_to_consume); + node * next_node = pool.get_pointer(node_pointer->next); + + node_pointer->next = pool.get_handle(last_node_pointer); + last_node_pointer = node_pointer; + + if (!next_node) { + nodes_in_reversed_order = nodes_to_consume; + break; + } + + tagged_node_handle next(pool.get_handle(next_node), nodes_to_consume.get_next_tag()); + nodes_to_consume = next; + } + + for(;;) { + node * node_pointer = pool.get_pointer(nodes_in_reversed_order); + f(node_pointer->v); + element_count += 1; + + node * next_node = pool.get_pointer(node_pointer->next); + + if (!next_node) { + pool.template destruct<true>(nodes_in_reversed_order); + break; + } + + tagged_node_handle next(pool.get_handle(next_node), nodes_in_reversed_order.get_next_tag()); + pool.template destruct<true>(nodes_in_reversed_order); + nodes_in_reversed_order = next; + } + + return element_count; + } + + /// \copydoc boost::lockfree::stack::consume_all_atomic_reversed(Functor & rhs) + template <typename Functor> + size_t consume_all_atomic_reversed(Functor const & f) + { + size_t element_count = 0; + tagged_node_handle old_tos = tos.load(detail::memory_order_consume); + + for (;;) { + node * old_tos_pointer = pool.get_pointer(old_tos); + if (!old_tos_pointer) + return 0; + + tagged_node_handle new_tos(pool.null_handle(), old_tos.get_next_tag()); + + if (tos.compare_exchange_weak(old_tos, new_tos)) + break; + } + + tagged_node_handle nodes_to_consume = old_tos; + + node * last_node_pointer = NULL; + tagged_node_handle nodes_in_reversed_order; + for(;;) { + node * node_pointer = pool.get_pointer(nodes_to_consume); + node * next_node = pool.get_pointer(node_pointer->next); + + node_pointer->next = pool.get_handle(last_node_pointer); + last_node_pointer = node_pointer; + + if (!next_node) { + nodes_in_reversed_order = nodes_to_consume; + break; + } + + tagged_node_handle next(pool.get_handle(next_node), nodes_to_consume.get_next_tag()); + nodes_to_consume = next; + } + + for(;;) { + node * node_pointer = pool.get_pointer(nodes_in_reversed_order); + f(node_pointer->v); + element_count += 1; + + node * next_node = pool.get_pointer(node_pointer->next); + + if (!next_node) { + pool.template destruct<true>(nodes_in_reversed_order); + break; + } + + tagged_node_handle next(pool.get_handle(next_node), nodes_in_reversed_order.get_next_tag()); + pool.template destruct<true>(nodes_in_reversed_order); + nodes_in_reversed_order = next; + } + + return element_count; + } /** * \return true, if stack is empty. * |