$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r83275 - in trunk: boost/lockfree libs/lockfree/test
From: tim_at_[hidden]
Date: 2013-03-03 08:07:51
Author: timblechmann
Date: 2013-03-03 08:07:50 EST (Sun, 03 Mar 2013)
New Revision: 83275
URL: http://svn.boost.org/trac/boost/changeset/83275
Log:
lockfree: introduce consume_one and consume_all methods
Text files modified: 
   trunk/boost/lockfree/queue.hpp               |    62 +++++++++++++++++++++++++++++++++++++++ 
   trunk/boost/lockfree/spsc_queue.hpp          |    60 ++++++++++++++++++++++++++++++++++++++  
   trunk/boost/lockfree/stack.hpp               |    62 +++++++++++++++++++++++++++++++++++++++ 
   trunk/libs/lockfree/test/queue_test.cpp      |    54 ++++++++++++++++++++++++++++++++++      
   trunk/libs/lockfree/test/spsc_queue_test.cpp |    50 ++++++++++++++++++++++++++++++++        
   trunk/libs/lockfree/test/stack_test.cpp      |    53 ++++++++++++++++++++++++++++++++++      
   trunk/libs/lockfree/test/test_helpers.hpp    |    22 ++++++++++++++                          
   7 files changed, 361 insertions(+), 2 deletions(-)
Modified: trunk/boost/lockfree/queue.hpp
==============================================================================
--- trunk/boost/lockfree/queue.hpp	(original)
+++ trunk/boost/lockfree/queue.hpp	2013-03-03 08:07:50 EST (Sun, 03 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
@@ -466,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: trunk/boost/lockfree/spsc_queue.hpp
==============================================================================
--- trunk/boost/lockfree/spsc_queue.hpp	(original)
+++ trunk/boost/lockfree/spsc_queue.hpp	2013-03-03 08:07:50 EST (Sun, 03 Mar 2013)
@@ -651,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_t consume_all(Functor & f)
+    {
+        size_t 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_t consume_all(Functor const & f)
+    {
+        size_t element_count = 0;
+        while (consume_one(f))
+            element_count += 1;
+
+        return element_count;
+    }
 };
 
 } /* namespace lockfree */
Modified: trunk/boost/lockfree/stack.hpp
==============================================================================
--- trunk/boost/lockfree/stack.hpp	(original)
+++ trunk/boost/lockfree/stack.hpp	2013-03-03 08:07:50 EST (Sun, 03 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
@@ -494,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: trunk/libs/lockfree/test/queue_test.cpp
==============================================================================
--- trunk/libs/lockfree/test/queue_test.cpp	(original)
+++ trunk/libs/lockfree/test/queue_test.cpp	2013-03-03 08:07:50 EST (Sun, 03 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: trunk/libs/lockfree/test/spsc_queue_test.cpp
==============================================================================
--- trunk/libs/lockfree/test/spsc_queue_test.cpp	(original)
+++ trunk/libs/lockfree/test/spsc_queue_test.cpp	2013-03-03 08:07:50 EST (Sun, 03 Mar 2013)
@@ -75,6 +75,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,
Modified: trunk/libs/lockfree/test/stack_test.cpp
==============================================================================
--- trunk/libs/lockfree/test/stack_test.cpp	(original)
+++ trunk/libs/lockfree/test/stack_test.cpp	2013-03-03 08:07:50 EST (Sun, 03 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: trunk/libs/lockfree/test/test_helpers.hpp
==============================================================================
--- trunk/libs/lockfree/test/test_helpers.hpp	(original)
+++ trunk/libs/lockfree/test/test_helpers.hpp	2013-03-03 08:07:50 EST (Sun, 03 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