Boost logo

Boost-Commit :

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


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk