Skip to content

Commit

Permalink
spsc_queue: Add tests to verify compatibility with move-only and copy…
Browse files Browse the repository at this point in the history
…-only types

Also:
    * Fix an issue spsc_queue::reset() would not compile for move-only types
    * Fix an issue where having BOOST_NO_CXX11_RVALUE_REFERENCES defined would break compiles
  • Loading branch information
srjek committed Mar 2, 2017
1 parent 94ceb42 commit 8589b4f
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 2 deletions.
5 changes: 3 additions & 2 deletions include/boost/lockfree/spsc_queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,8 @@ class ringbuffer_base
template< class OutputIterator >
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
typename boost::disable_if< typename boost::is_constructible<T, T>::type, OutputIterator>::type
#else
OutputIterator
#endif
move_and_delete( T * first, T * last, OutputIterator out )
{
Expand Down Expand Up @@ -1092,8 +1094,7 @@ class spsc_queue:
if ( !boost::has_trivial_destructor<T>::value ) {
// make sure to call all destructors!

T dummy_element;
while (pop(dummy_element))
while (pop())
{}
} else {
base_type::write_index_.store(0, memory_order_relaxed);
Expand Down
159 changes: 159 additions & 0 deletions test/spsc_queue_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include <iostream>
#include <memory>
#include <utility>

#include "test_helpers.hpp"
#include "test_common.hpp"
Expand Down Expand Up @@ -405,3 +406,161 @@ BOOST_AUTO_TEST_CASE( spsc_queue_reset_test )

BOOST_REQUIRE(f.empty());
}

struct immovable_type
{
int value;

immovable_type() : value(0) {}
immovable_type(int x) : value(x) {}
immovable_type(const immovable_type& other) : value(other.value) {}

immovable_type& operator=(const immovable_type& other)
{
this->value = other.value;
return *this;
}

#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
#ifndef BOOST_NO_CX11_RVALUE_REFERENCES
immovable_type(immovable_type&&) = delete;
immovable_type& operator=(immovable_type&&) = delete;
#endif
#endif
};

struct test_immovable_object
{
test_immovable_object(int i):
i(i)
{}

void operator()(immovable_type arg) const
{
BOOST_REQUIRE_EQUAL(arg.value, i);
}

int i;
};

BOOST_AUTO_TEST_CASE( spsc_queue_immovable_object_test )
{
spsc_queue<immovable_type, capacity<64> > f;

f.emplace( 9001 );
f.emplace( 9002 );
f.push( immovable_type(9003) );

immovable_type x(9004);
immovable_type push_array[2];
push_array[0] = x;
push_array[1] = x;
f.push(push_array, 2);

immovable_type pop_array[2];
f.pop(pop_array, 2);
BOOST_CHECK_EQUAL( pop_array[0].value, 9001 );
BOOST_CHECK_EQUAL( pop_array[1].value, 9002 );

f.consume_one( test_immovable_object(9003) );
f.consume_all( test_immovable_object(9004) );

f.emplace( 42 );
f.emplace( 42 );
f.reset();
}

#ifndef BOOST_NO_CX11_RVALUE_REFERENCES
struct refcount_handle
{
int* p_refcount;

refcount_handle() : p_refcount( nullptr ) {}
refcount_handle(int* x) : p_refcount(x)
{
if (p_refcount != nullptr)
{
*p_refcount += 1;
}
}
~refcount_handle()
{
if (p_refcount != nullptr)
{
*p_refcount -= 1;
}
}

refcount_handle(const refcount_handle& other) = delete;
refcount_handle& operator=(const refcount_handle&) = delete;

refcount_handle& operator=(refcount_handle&& other)
{
if (this->p_refcount != nullptr)
{
*p_refcount -= 1;
}

this->p_refcount = other.p_refcount;
other.p_refcount = nullptr;
return *this;
}
refcount_handle(refcount_handle&& other)
: p_refcount( other.p_refcount )
{
other.p_refcount = nullptr;
}
};

struct test_refcount_handle
{
test_refcount_handle(int* p_refcount):
p_refcount(p_refcount)
{}

void operator()(refcount_handle& arg) const
{
BOOST_REQUIRE_EQUAL(arg.p_refcount, p_refcount);
}

int* p_refcount;
};

BOOST_AUTO_TEST_CASE( spsc_queue_refcount_test )
{
spsc_queue<refcount_handle, capacity<64> > f;

int refcount = 0;

f.emplace( &refcount );
f.emplace( &refcount );
f.emplace( &refcount );
f.emplace( &refcount );
BOOST_CHECK_EQUAL( refcount, 4 );

f.push( std::move( refcount_handle(&refcount) ) );

BOOST_CHECK_EQUAL( refcount, 5 );

{
refcount_handle pop_array[2];
f.pop(pop_array, 2);
BOOST_CHECK_EQUAL( pop_array[0].p_refcount, &refcount );
BOOST_CHECK_EQUAL( pop_array[1].p_refcount, &refcount );

BOOST_CHECK_EQUAL( refcount, 5 );
}
BOOST_CHECK_EQUAL( refcount, 3 );

f.consume_one( test_refcount_handle(&refcount) );
BOOST_CHECK_EQUAL( refcount, 2 );
f.consume_all( test_refcount_handle(&refcount) );
BOOST_CHECK_EQUAL( refcount, 0 );

f.emplace( &refcount );
f.emplace( &refcount );
BOOST_CHECK_EQUAL( refcount, 2 );
f.reset();
BOOST_CHECK_EQUAL( refcount, 0 );
}
#endif

0 comments on commit 8589b4f

Please sign in to comment.