|
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