$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r83540 - in branches/release: boost/lockfree boost/lockfree/detail libs/lockfree libs/lockfree/test
From: tim_at_[hidden]
Date: 2013-03-24 09:08:35
Author: timblechmann
Date: 2013-03-24 09:08:34 EDT (Sun, 24 Mar 2013)
New Revision: 83540
URL: http://svn.boost.org/trac/boost/changeset/83540
Log:
lockfree: merge changes from trunk
Added:
   branches/release/libs/lockfree/test/spsc_queue_stress_test.cpp
      - copied unchanged from r83537, /trunk/libs/lockfree/test/spsc_queue_stress_test.cpp
Properties modified: 
   branches/release/boost/lockfree/   (props changed)
   branches/release/libs/lockfree/   (props changed)
Text files modified: 
   branches/release/boost/lockfree/detail/freelist.hpp     |     5                                         
   branches/release/boost/lockfree/queue.hpp               |    80 ++++++++++++                            
   branches/release/boost/lockfree/spsc_queue.hpp          |    74 +++++++++++                             
   branches/release/boost/lockfree/stack.hpp               |    76 +++++++++++                             
   branches/release/libs/lockfree/test/queue_test.cpp      |    54 ++++++++                                
   branches/release/libs/lockfree/test/spsc_queue_test.cpp |   244 ++++++++------------------------------- 
   branches/release/libs/lockfree/test/stack_test.cpp      |    53 ++++++++                                
   branches/release/libs/lockfree/test/test_helpers.hpp    |    22 +++                                     
   8 files changed, 406 insertions(+), 202 deletions(-)
Modified: branches/release/boost/lockfree/detail/freelist.hpp
==============================================================================
--- branches/release/boost/lockfree/detail/freelist.hpp	(original)
+++ branches/release/boost/lockfree/detail/freelist.hpp	2013-03-24 09:08:34 EDT (Sun, 24 Mar 2013)
@@ -298,6 +298,11 @@
         return (index == rhs.index) && (tag == rhs.tag);
     }
 
+    bool operator!=(tagged_index const & rhs) const
+    {
+        return !operator==(rhs);
+    }
+
 protected:
     index_t index;
     tag_t tag;
Modified: branches/release/boost/lockfree/queue.hpp
==============================================================================
--- branches/release/boost/lockfree/queue.hpp	(original)
+++ branches/release/boost/lockfree/queue.hpp	2013-03-24 09:08:34 EDT (Sun, 24 Mar 2013)
@@ -2,7 +2,7 @@
 //  Michael, M. M. and Scott, M. L.,
 //  "simple, fast and practical non-blocking and blocking concurrent queue algorithms"
 //
-//  Copyright (C) 2008, 2009, 2010, 2011 Tim Blechmann
+//  Copyright (C) 2008-2013 Tim Blechmann
 //
 //  Distributed under the Boost Software License, Version 1.0. (See
 //  accompanying file LICENSE_1_0.txt or copy at
@@ -11,10 +11,10 @@
 #ifndef BOOST_LOCKFREE_FIFO_HPP_INCLUDED
 #define BOOST_LOCKFREE_FIFO_HPP_INCLUDED
 
-#include <memory>               /* std::auto_ptr */
-
 #include <boost/assert.hpp>
+#ifdef BOOST_NO_CXX11_DELETED_FUNCTIONS
 #include <boost/noncopyable.hpp>
+#endif
 #include <boost/static_assert.hpp>
 #include <boost/type_traits/has_trivial_assign.hpp>
 #include <boost/type_traits/has_trivial_destructor.hpp>
@@ -69,8 +69,10 @@
 #else
 template <typename T, ...Options>
 #endif
-class queue:
-    boost::noncopyable
+class queue
+#ifdef BOOST_NO_CXX11_DELETED_FUNCTIONS
+    : boost::noncopyable
+#endif
 {
 private:
 #ifndef BOOST_DOXYGEN_INVOKED
@@ -86,7 +88,7 @@
     typedef typename detail::queue_signature::bind<A0, A1, A2>::type bound_args;
 
     static const bool has_capacity = detail::extract_capacity<bound_args>::has_capacity;
-    static const size_t capacity = detail::extract_capacity<bound_args>::capacity;
+    static const size_t capacity = detail::extract_capacity<bound_args>::capacity + 1; // the queue uses one dummy node
     static const bool fixed_sized = detail::extract_fixed_sized<bound_args>::value;
     static const bool node_based = !(has_capacity || fixed_sized);
     static const bool compile_time_sized = has_capacity;
@@ -137,6 +139,12 @@
 
 #endif
 
+#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
+    queue(queue const &) = delete;
+    queue(queue &&)      = delete;
+    const queue& operator=( const queue& ) = delete;
+#endif
+
 public:
     typedef T value_type;
     typedef typename implementation_defined::allocator allocator;
@@ -458,6 +466,66 @@
         }
     }
 
+    /** consumes one element via a functor
+     *
+     *  pops one element from the queue and applies the functor on this object
+     *
+     * \returns true, if one element was consumed
+     *
+     * \note Thread-safe and non-blocking, if functor is thread-safe and non-blocking
+     * */
+    template <typename Functor>
+    bool consume_one(Functor & f)
+    {
+        T element;
+        bool success = pop(element);
+        if (success)
+            f(element);
+
+        return success;
+    }
+
+    /// \copydoc boost::lockfree::queue::consume_one(Functor & rhs)
+    template <typename Functor>
+    bool consume_one(Functor const & f)
+    {
+        T element;
+        bool success = pop(element);
+        if (success)
+            f(element);
+
+        return success;
+    }
+
+    /** consumes all elements via a functor
+     *
+     * sequentially pops all elements from the queue 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(Functor & f)
+    {
+        size_t element_count = 0;
+        while (consume_one(f))
+            element_count += 1;
+
+        return element_count;
+    }
+
+    /// \copydoc boost::lockfree::queue::consume_all(Functor & rhs)
+    template <typename Functor>
+    size_t consume_all(Functor const & f)
+    {
+        size_t element_count = 0;
+        while (consume_one(f))
+            element_count += 1;
+
+        return element_count;
+    }
+
 private:
 #ifndef BOOST_DOXYGEN_INVOKED
     atomic<tagged_node_handle> head_;
Modified: branches/release/boost/lockfree/spsc_queue.hpp
==============================================================================
--- branches/release/boost/lockfree/spsc_queue.hpp	(original)
+++ branches/release/boost/lockfree/spsc_queue.hpp	2013-03-24 09:08:34 EDT (Sun, 24 Mar 2013)
@@ -14,7 +14,9 @@
 
 #include <boost/array.hpp>
 #include <boost/assert.hpp>
+#ifdef BOOST_NO_CXX11_DELETED_FUNCTIONS
 #include <boost/noncopyable.hpp>
+#endif
 #include <boost/static_assert.hpp>
 
 #include <boost/lockfree/detail/atomic.hpp>
@@ -32,8 +34,10 @@
                              > ringbuffer_signature;
 
 template <typename T>
-class ringbuffer_base:
-    boost::noncopyable
+class ringbuffer_base
+#ifdef BOOST_NO_CXX11_DELETED_FUNCTIONS
+        : boost::noncopyable
+#endif
 {
 #ifndef BOOST_DOXYGEN_INVOKED
     typedef std::size_t size_t;
@@ -42,6 +46,12 @@
     char padding1[padding_size]; /* force read_index and write_index to different cache lines */
     atomic<size_t> read_index_;
 
+#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
+    ringbuffer_base(ringbuffer_base const &) = delete;
+    ringbuffer_base(ringbuffer_base &&)      = delete;
+    const ringbuffer_base& operator=( const ringbuffer_base& ) = delete;
+#endif
+
 protected:
     ringbuffer_base(void):
         write_index_(0), read_index_(0)
@@ -641,6 +651,66 @@
     {
         return base_type::pop(it);
     }
+
+    /** consumes one element via a functor
+     *
+     *  pops one element from the queue and applies the functor on this object
+     *
+     * \returns true, if one element was consumed
+     *
+     * \note Thread-safe and non-blocking, if functor is thread-safe and non-blocking
+     * */
+    template <typename Functor>
+    bool consume_one(Functor & f)
+    {
+        T element;
+        bool success = pop(element);
+        if (success)
+            f(element);
+
+        return success;
+    }
+
+    /// \copydoc boost::lockfree::spsc_queue::consume_one(Functor & rhs)
+    template <typename Functor>
+    bool consume_one(Functor const & f)
+    {
+        T element;
+        bool success = pop(element);
+        if (success)
+            f(element);
+
+        return success;
+    }
+
+    /** consumes all elements via a functor
+     *
+     * sequentially pops all elements from the queue 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_type consume_all(Functor & f)
+    {
+        size_type element_count = 0;
+        while (consume_one(f))
+            element_count += 1;
+
+        return element_count;
+    }
+
+    /// \copydoc boost::lockfree::spsc_queue::consume_all(Functor & rhs)
+    template <typename Functor>
+    size_type consume_all(Functor const & f)
+    {
+        size_type element_count = 0;
+        while (consume_one(f))
+            element_count += 1;
+
+        return element_count;
+    }
 };
 
 } /* namespace lockfree */
Modified: branches/release/boost/lockfree/stack.hpp
==============================================================================
--- branches/release/boost/lockfree/stack.hpp	(original)
+++ branches/release/boost/lockfree/stack.hpp	2013-03-24 09:08:34 EDT (Sun, 24 Mar 2013)
@@ -1,4 +1,4 @@
-//  Copyright (C) 2008, 2009, 2010, 2011 Tim Blechmann
+//  Copyright (C) 2008-2013 Tim Blechmann
 //
 //  Distributed under the Boost Software License, Version 1.0. (See
 //  accompanying file LICENSE_1_0.txt or copy at
@@ -10,7 +10,9 @@
 #include <boost/assert.hpp>
 #include <boost/checked_delete.hpp>
 #include <boost/integer_traits.hpp>
+#ifdef BOOST_NO_CXX11_DELETED_FUNCTIONS
 #include <boost/noncopyable.hpp>
+#endif
 #include <boost/static_assert.hpp>
 #include <boost/tuple/tuple.hpp>
 #include <boost/type_traits/has_trivial_assign.hpp>
@@ -63,8 +65,10 @@
 #else
 template <typename T, ...Options>
 #endif
-class stack:
-    boost::noncopyable
+class stack
+#ifdef BOOST_NO_CXX11_DELETED_FUNCTIONS
+    : boost::noncopyable
+#endif
 {
 private:
 #ifndef BOOST_DOXYGEN_INVOKED
@@ -108,6 +112,12 @@
 
 #endif
 
+#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
+    stack(stack const &) = delete;
+    stack(stack &&)      = delete;
+    const stack& operator=( const stack& ) = delete;
+#endif
+
 public:
     typedef T value_type;
     typedef typename implementation_defined::allocator allocator;
@@ -484,6 +494,66 @@
         return true;
     }
 
+    /** consumes one element via a functor
+     *
+     *  pops one element from the stack and applies the functor on this object
+     *
+     * \returns true, if one element was consumed
+     *
+     * \note Thread-safe and non-blocking, if functor is thread-safe and non-blocking
+     * */
+    template <typename Functor>
+    bool consume_one(Functor & f)
+    {
+        T element;
+        bool success = pop(element);
+        if (success)
+            f(element);
+
+        return success;
+    }
+
+    /// \copydoc boost::lockfree::stack::consume_one(Functor & rhs)
+    template <typename Functor>
+    bool consume_one(Functor const & f)
+    {
+        T element;
+        bool success = pop(element);
+        if (success)
+            f(element);
+
+        return success;
+    }
+
+    /** consumes all elements via a functor
+     *
+     * sequentially 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(Functor & f)
+    {
+        size_t element_count = 0;
+        while (consume_one(f))
+            element_count += 1;
+
+        return element_count;
+    }
+
+    /// \copydoc boost::lockfree::stack::consume_all(Functor & rhs)
+    template <typename Functor>
+    size_t consume_all(Functor const & f)
+    {
+        size_t element_count = 0;
+        while (consume_one(f))
+            element_count += 1;
+
+        return element_count;
+    }
+
     /**
      * \return true, if stack is empty.
      *
Modified: branches/release/libs/lockfree/test/queue_test.cpp
==============================================================================
--- branches/release/libs/lockfree/test/queue_test.cpp	(original)
+++ branches/release/libs/lockfree/test/queue_test.cpp	2013-03-24 09:08:34 EDT (Sun, 24 Mar 2013)
@@ -16,6 +16,8 @@
 
 #include <memory>
 
+#include "test_helpers.hpp"
+
 using namespace boost;
 using namespace boost::lockfree;
 using namespace std;
@@ -82,6 +84,58 @@
 }
 
 
+BOOST_AUTO_TEST_CASE( queue_consume_one_test )
+{
+    queue<int> f(64);
+
+    BOOST_WARN(f.is_lock_free());
+    BOOST_REQUIRE(f.empty());
+
+    f.push(1);
+    f.push(2);
+
+#ifdef BOOST_NO_CXX11_LAMBDAS
+    bool success1 = f.consume_one(test_equal(1));
+    bool success2 = f.consume_one(test_equal(2));
+#else
+    bool success1 = f.consume_one([] (int i) {
+        BOOST_REQUIRE_EQUAL(i, 1);
+    });
+
+    bool success2 = f.consume_one([] (int i) {
+        BOOST_REQUIRE_EQUAL(i, 2);
+    });
+#endif
+
+    BOOST_REQUIRE(success1);
+    BOOST_REQUIRE(success2);
+
+    BOOST_REQUIRE(f.empty());
+}
+
+BOOST_AUTO_TEST_CASE( queue_consume_all_test )
+{
+    queue<int> f(64);
+
+    BOOST_WARN(f.is_lock_free());
+    BOOST_REQUIRE(f.empty());
+
+    f.push(1);
+    f.push(2);
+
+#ifdef BOOST_NO_CXX11_LAMBDAS
+    size_t consumed = f.consume_all(dummy_functor());
+#else
+    size_t consumed = f.consume_all([] (int i) {
+    });
+#endif
+
+    BOOST_REQUIRE_EQUAL(consumed, 2u);
+
+    BOOST_REQUIRE(f.empty());
+}
+
+
 BOOST_AUTO_TEST_CASE( queue_convert_pop_test )
 {
     queue<int*> f(128);
Modified: branches/release/libs/lockfree/test/spsc_queue_test.cpp
==============================================================================
--- branches/release/libs/lockfree/test/spsc_queue_test.cpp	(original)
+++ branches/release/libs/lockfree/test/spsc_queue_test.cpp	2013-03-24 09:08:34 EDT (Sun, 24 Mar 2013)
@@ -6,8 +6,6 @@
 
 #include <boost/lockfree/spsc_queue.hpp>
 
-#include <boost/thread.hpp>
-
 #define BOOST_TEST_MAIN
 #ifdef BOOST_LOCKFREE_INCLUDE_TESTS
 #include <boost/test/included/unit_test.hpp>
@@ -75,6 +73,56 @@
     BOOST_REQUIRE(!stk.pop(out));
 }
 
+BOOST_AUTO_TEST_CASE( spsc_queue_consume_one_test )
+{
+    spsc_queue<int> f(64);
+
+    BOOST_WARN(f.is_lock_free());
+    BOOST_REQUIRE(f.empty());
+
+    f.push(1);
+    f.push(2);
+
+#ifdef BOOST_NO_CXX11_LAMBDAS
+    bool success1 = f.consume_one(test_equal(1));
+    bool success2 = f.consume_one(test_equal(2));
+#else
+    bool success1 = f.consume_one([] (int i) {
+        BOOST_REQUIRE_EQUAL(i, 1);
+    });
+
+    bool success2 = f.consume_one([] (int i) {
+        BOOST_REQUIRE_EQUAL(i, 2);
+    });
+#endif
+
+    BOOST_REQUIRE(success1);
+    BOOST_REQUIRE(success2);
+
+    BOOST_REQUIRE(f.empty());
+}
+
+BOOST_AUTO_TEST_CASE( spsc_queue_consume_all_test )
+{
+    spsc_queue<int> f(64);
+
+    BOOST_WARN(f.is_lock_free());
+    BOOST_REQUIRE(f.empty());
+
+    f.push(1);
+    f.push(2);
+
+#ifdef BOOST_NO_CXX11_LAMBDAS
+    size_t consumed = f.consume_all(dummy_functor());
+#else
+    size_t consumed = f.consume_all([] (int i) {
+    });
+#endif
+
+    BOOST_REQUIRE_EQUAL(consumed, 2u);
+
+    BOOST_REQUIRE(f.empty());
+}
 
 enum {
     pointer_and_size,
@@ -93,7 +141,7 @@
 
     int data[xqueue_size];
     for (size_t i = 0; i != xqueue_size; ++i)
-        data[i] = i*2;
+        data[i] = (int)i*2;
 
     switch (EnqueueMode) {
     case pointer_and_size:
@@ -149,7 +197,7 @@
 
     int data[xqueue_size];
     for (size_t i = 0; i != xqueue_size; ++i)
-        data[i] = i*2;
+        data[i] = (int)i*2;
 
     std::vector<int> vdata(data, data + xqueue_size);
 
@@ -198,7 +246,7 @@
 
     int data[xqueue_size];
     for (size_t i = 0; i != xqueue_size; ++i)
-        data[i] = i*2;
+        data[i] = (int)i*2;
 
     std::vector<int> vdata(data, data + xqueue_size);
 
@@ -243,189 +291,3 @@
     spsc_queue_buffer_pop<reference_to_array, 7, 16, 64>();
     spsc_queue_buffer_pop<output_iterator_, 7, 16, 64>();
 }
-
-
-#ifndef BOOST_LOCKFREE_STRESS_TEST
-static const boost::uint32_t nodes_per_thread = 100000;
-#else
-static const boost::uint32_t nodes_per_thread = 100000000;
-#endif
-
-struct spsc_queue_tester
-{
-    spsc_queue<int, capacity<128> > sf;
-
-    boost::lockfree::detail::atomic<long> spsc_queue_cnt, received_nodes;
-
-    static_hashed_set<int, 1<<16 > working_set;
-
-    spsc_queue_tester(void):
-        spsc_queue_cnt(0), received_nodes(0)
-    {}
-
-    void add(void)
-    {
-        for (boost::uint32_t i = 0; i != nodes_per_thread; ++i) {
-            int id = generate_id<int>();
-            working_set.insert(id);
-
-            while (sf.push(id) == false)
-            {}
-
-            ++spsc_queue_cnt;
-        }
-        running = false;
-    }
-
-    bool get_element(void)
-    {
-        int data;
-        bool success = sf.pop(data);
-
-        if (success) {
-            ++received_nodes;
-            --spsc_queue_cnt;
-            bool erased = working_set.erase(data);
-            assert(erased);
-            return true;
-        } else
-            return false;
-    }
-
-    boost::lockfree::detail::atomic<bool> running;
-
-    void get(void)
-    {
-        for(;;) {
-            bool success = get_element();
-            if (!running && !success)
-                break;
-        }
-
-        while ( get_element() );
-    }
-
-    void run(void)
-    {
-        running = true;
-
-        BOOST_REQUIRE(sf.empty());
-
-        thread reader(boost::bind(&spsc_queue_tester::get, this));
-        thread writer(boost::bind(&spsc_queue_tester::add, this));
-        cout << "reader and writer threads created" << endl;
-
-        writer.join();
-        cout << "writer threads joined. waiting for readers to finish" << endl;
-
-        reader.join();
-
-        BOOST_REQUIRE_EQUAL(received_nodes, nodes_per_thread);
-        BOOST_REQUIRE_EQUAL(spsc_queue_cnt, 0);
-        BOOST_REQUIRE(sf.empty());
-        BOOST_REQUIRE(working_set.count_nodes() == 0);
-    }
-};
-
-BOOST_AUTO_TEST_CASE( spsc_queue_test_caching )
-{
-    boost::shared_ptr<spsc_queue_tester> test1(new spsc_queue_tester);
-    test1->run();
-}
-
-struct spsc_queue_tester_buffering
-{
-    spsc_queue<int, capacity<128> > sf;
-
-    boost::lockfree::detail::atomic<long> spsc_queue_cnt;
-
-    static_hashed_set<int, 1<<16 > working_set;
-    boost::lockfree::detail::atomic<long> received_nodes;
-
-    spsc_queue_tester_buffering(void):
-        spsc_queue_cnt(0), received_nodes(0)
-    {}
-
-    static const size_t buf_size = 5;
-
-    void add(void)
-    {
-        boost::array<int, buf_size> input_buffer;
-        for (boost::uint32_t i = 0; i != nodes_per_thread; i+=buf_size) {
-            for (size_t i = 0; i != buf_size; ++i) {
-                int id = generate_id<int>();
-                working_set.insert(id);
-                input_buffer[i] = id;
-            }
-
-            size_t pushed = 0;
-
-            do {
-                pushed += sf.push(input_buffer.c_array() + pushed,
-                                  input_buffer.size()    - pushed);
-            } while (pushed != buf_size);
-
-            spsc_queue_cnt+=buf_size;
-        }
-        running = false;
-    }
-
-    bool get_elements(void)
-    {
-        boost::array<int, buf_size> output_buffer;
-
-        size_t popd = sf.pop(output_buffer.c_array(), output_buffer.size());
-
-        if (popd) {
-            received_nodes += popd;
-            spsc_queue_cnt -= popd;
-
-            for (size_t i = 0; i != popd; ++i) {
-                bool erased = working_set.erase(output_buffer[i]);
-                assert(erased);
-            }
-
-            return true;
-        } else
-            return false;
-    }
-
-    boost::lockfree::detail::atomic<bool> running;
-
-    void get(void)
-    {
-        for(;;) {
-            bool success = get_elements();
-            if (!running && !success)
-                break;
-        }
-
-        while ( get_elements() );
-    }
-
-    void run(void)
-    {
-        running = true;
-
-        thread reader(boost::bind(&spsc_queue_tester_buffering::get, this));
-        thread writer(boost::bind(&spsc_queue_tester_buffering::add, this));
-        cout << "reader and writer threads created" << endl;
-
-        writer.join();
-        cout << "writer threads joined. waiting for readers to finish" << endl;
-
-        reader.join();
-
-        BOOST_REQUIRE_EQUAL(received_nodes, nodes_per_thread);
-        BOOST_REQUIRE_EQUAL(spsc_queue_cnt, 0);
-        BOOST_REQUIRE(sf.empty());
-        BOOST_REQUIRE(working_set.count_nodes() == 0);
-    }
-};
-
-
-BOOST_AUTO_TEST_CASE( spsc_queue_test_buffering )
-{
-    boost::shared_ptr<spsc_queue_tester_buffering> test1(new spsc_queue_tester_buffering);
-    test1->run();
-}
Modified: branches/release/libs/lockfree/test/stack_test.cpp
==============================================================================
--- branches/release/libs/lockfree/test/stack_test.cpp	(original)
+++ branches/release/libs/lockfree/test/stack_test.cpp	2013-03-24 09:08:34 EDT (Sun, 24 Mar 2013)
@@ -15,6 +15,8 @@
 #include <boost/test/unit_test.hpp>
 #endif
 
+#include "test_helpers.hpp"
+
 BOOST_AUTO_TEST_CASE( simple_stack_test )
 {
     boost::lockfree::stack<long> stk(128);
@@ -107,3 +109,54 @@
     BOOST_REQUIRE(!stk.pop(out));
     BOOST_REQUIRE(stk.empty());
 }
+
+BOOST_AUTO_TEST_CASE( stack_consume_one_test )
+{
+    boost::lockfree::stack<int> f(64);
+
+    BOOST_WARN(f.is_lock_free());
+    BOOST_REQUIRE(f.empty());
+
+    f.push(1);
+    f.push(2);
+
+#ifdef BOOST_NO_CXX11_LAMBDAS
+    bool success1 = f.consume_one(test_equal(2));
+    bool success2 = f.consume_one(test_equal(1));
+#else
+    bool success1 = f.consume_one([] (int i) {
+        BOOST_REQUIRE_EQUAL(i, 2);
+    });
+
+    bool success2 = f.consume_one([] (int i) {
+        BOOST_REQUIRE_EQUAL(i, 1);
+    });
+#endif
+
+    BOOST_REQUIRE(success1);
+    BOOST_REQUIRE(success2);
+
+    BOOST_REQUIRE(f.empty());
+}
+
+BOOST_AUTO_TEST_CASE( stack_consume_all_test )
+{
+    boost::lockfree::stack<int> f(64);
+
+    BOOST_WARN(f.is_lock_free());
+    BOOST_REQUIRE(f.empty());
+
+    f.push(1);
+    f.push(2);
+
+#ifdef BOOST_NO_CXX11_LAMBDAS
+    size_t consumed = f.consume_all(dummy_functor());
+#else
+    size_t consumed = f.consume_all([] (int i) {
+    });
+#endif
+
+    BOOST_REQUIRE_EQUAL(consumed, 2u);
+
+    BOOST_REQUIRE(f.empty());
+}
Modified: branches/release/libs/lockfree/test/test_helpers.hpp
==============================================================================
--- branches/release/libs/lockfree/test/test_helpers.hpp	(original)
+++ branches/release/libs/lockfree/test/test_helpers.hpp	2013-03-24 09:08:34 EDT (Sun, 24 Mar 2013)
@@ -85,4 +85,26 @@
     mutable boost::array<boost::mutex, buckets> ref_mutex;
 };
 
+struct test_equal
+{
+    test_equal(int i):
+        i(i)
+    {}
+
+    void operator()(int arg) const
+    {
+        BOOST_REQUIRE_EQUAL(arg, i);
+    }
+
+    int i;
+};
+
+struct dummy_functor
+{
+    void operator()(int arg) const
+    {
+    }
+};
+
+
 #endif