summaryrefslogtreecommitdiff
path: root/boost/lockfree
diff options
context:
space:
mode:
Diffstat (limited to 'boost/lockfree')
-rw-r--r--boost/lockfree/detail/atomic.hpp6
-rw-r--r--boost/lockfree/detail/copy_payload.hpp2
-rw-r--r--boost/lockfree/detail/freelist.hpp8
-rw-r--r--boost/lockfree/detail/parameter.hpp7
-rw-r--r--boost/lockfree/detail/prefix.hpp40
-rw-r--r--boost/lockfree/detail/tagged_ptr.hpp2
-rw-r--r--boost/lockfree/detail/tagged_ptr_dcas.hpp11
-rw-r--r--boost/lockfree/detail/tagged_ptr_ptrcompression.hpp6
-rw-r--r--boost/lockfree/lockfree_forward.hpp72
-rw-r--r--boost/lockfree/policies.hpp4
-rw-r--r--boost/lockfree/queue.hpp19
-rw-r--r--boost/lockfree/spsc_queue.hpp30
-rw-r--r--boost/lockfree/stack.hpp239
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.
*