Skip to content

Commit

Permalink
modernisation: introduce uses_optional api
Browse files Browse the repository at this point in the history
  • Loading branch information
timblechmann committed May 4, 2024
1 parent 5e9bc81 commit 8e5e4eb
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 5 deletions.
11 changes: 6 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.23 AND BOOST_LOCKFREE_USE_FILE_SET)
include/boost/lockfree/policies.hpp
include/boost/lockfree/queue.hpp
include/boost/lockfree/lockfree_forward.hpp
include/boost/lockfree/detail/prefix.hpp
include/boost/lockfree/detail/copy_payload.hpp
include/boost/lockfree/detail/tagged_ptr_dcas.hpp
include/boost/lockfree/detail/tagged_ptr.hpp
include/boost/lockfree/detail/tagged_ptr_ptrcompression.hpp
include/boost/lockfree/detail/atomic.hpp
include/boost/lockfree/detail/copy_payload.hpp
include/boost/lockfree/detail/freelist.hpp
include/boost/lockfree/detail/parameter.hpp
include/boost/lockfree/detail/prefix.hpp
include/boost/lockfree/detail/tagged_ptr.hpp
include/boost/lockfree/detail/tagged_ptr_dcas.hpp
include/boost/lockfree/detail/tagged_ptr_ptrcompression.hpp
include/boost/lockfree/detail/uses_optional.hpp
include/boost/lockfree/stack.hpp
)

Expand Down
32 changes: 32 additions & 0 deletions include/boost/lockfree/detail/uses_optional.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (C) 2023 Tim Blechmann
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_LOCKFREE_DETAIL_USES_OPTIONAL_HPP
#define BOOST_LOCKFREE_DETAIL_USES_OPTIONAL_HPP

#include <boost/config.hpp>

#ifndef BOOST_NO_CXX17_HDR_OPTIONAL

# include <optional>

namespace boost { namespace lockfree {

struct uses_optional_t
{};

# ifdef BOOST_NO_CXX17_INLINE_VARIABLES
static
# else
inline
# endif
constexpr uses_optional_t uses_optional;

}} // namespace boost::lockfree

#endif

#endif /* BOOST_LOCKFREE_DETAIL_USES_OPTIONAL_HPP */
37 changes: 37 additions & 0 deletions include/boost/lockfree/queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <boost/lockfree/detail/freelist.hpp>
#include <boost/lockfree/detail/parameter.hpp>
#include <boost/lockfree/detail/tagged_ptr.hpp>
#include <boost/lockfree/detail/uses_optional.hpp>
#include <boost/lockfree/lockfree_forward.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
Expand Down Expand Up @@ -464,6 +465,42 @@ class queue
}
}

#if !defined( BOOST_NO_CXX17_HDR_OPTIONAL ) || defined( BOOST_DOXYGEN_INVOKED )
/** Pops object from queue, returning a std::optional<>
*
* \returns `std::optional` with value if successful, `std::nullopt` if queue is empty.
*
* \note Thread-safe and non-blocking
*
* */
std::optional< T > pop( uses_optional_t )
{
T to_dequeue;
if ( pop( to_dequeue ) )
return to_dequeue;
else
return std::nullopt;
}

/** Pops object from queue, returning a std::optional<>
*
* \pre type T must be convertible to U
* \returns `std::optional` with value if successful, `std::nullopt` if queue is empty.
*
* \note Thread-safe and non-blocking
*
* */
template < typename U >
std::optional< U > pop( uses_optional_t )
{
U to_dequeue;
if ( pop( to_dequeue ) )
return to_dequeue;
else
return std::nullopt;
}
#endif

/** Pops object from queue.
*
* \post if pop operation is successful, object will be copied to ret.
Expand Down
37 changes: 37 additions & 0 deletions include/boost/lockfree/spsc_queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <boost/lockfree/detail/copy_payload.hpp>
#include <boost/lockfree/detail/parameter.hpp>
#include <boost/lockfree/detail/prefix.hpp>
#include <boost/lockfree/detail/uses_optional.hpp>
#include <boost/lockfree/lockfree_forward.hpp>

#ifdef BOOST_HAS_PRAGMA_ONCE
Expand Down Expand Up @@ -742,6 +743,42 @@ class spsc_queue : public detail::make_ringbuffer< T, Options... >::ringbuffer_t
} );
}

#if !defined( BOOST_NO_CXX17_HDR_OPTIONAL ) || defined( BOOST_DOXYGEN_INVOKED )
/** Pops object from spsc_queue, returning a std::optional<>
*
* \returns `std::optional` with value if successful, `std::nullopt` if spsc_queue is empty.
*
* \note Thread-safe and non-blocking
*
* */
std::optional< T > pop( uses_optional_t )
{
T to_dequeue;
if ( pop( to_dequeue ) )
return to_dequeue;
else
return std::nullopt;
}

/** Pops object from spsc_queue, returning a std::optional<>
*
* \pre type T must be convertible to U
* \returns `std::optional` with value if successful, `std::nullopt` if spsc_queue is empty.
*
* \note Thread-safe and non-blocking
*
* */
template < typename U >
std::optional< U > pop( uses_optional_t )
{
U to_dequeue;
if ( pop( to_dequeue ) )
return to_dequeue;
else
return std::nullopt;
}
#endif

/** Pushes as many objects from the array t as there is space.
*
* \pre only one thread is allowed to push data to the spsc_queue
Expand Down
36 changes: 36 additions & 0 deletions include/boost/lockfree/stack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <boost/lockfree/detail/freelist.hpp>
#include <boost/lockfree/detail/parameter.hpp>
#include <boost/lockfree/detail/tagged_ptr.hpp>
#include <boost/lockfree/detail/uses_optional.hpp>
#include <boost/lockfree/lockfree_forward.hpp>

#include <tuple>
Expand Down Expand Up @@ -544,6 +545,41 @@ class stack
} );
}

#if !defined( BOOST_NO_CXX17_HDR_OPTIONAL ) || defined( BOOST_DOXYGEN_INVOKED )
/** Pops object from stack, returning a std::optional<>
*
* \returns `std::optional` with value if successful, `std::nullopt` if stack is empty.
*
* \note Thread-safe and non-blocking
*
* */
std::optional< T > pop( uses_optional_t )
{
T to_dequeue;
if ( pop( to_dequeue ) )
return to_dequeue;
else
return std::nullopt;
}

/** Pops object from stack, returning a std::optional<>
*
* \pre type T must be convertible to U
* \returns `std::optional` with value if successful, `std::nullopt` if stack is empty.
*
* \note Thread-safe and non-blocking
*
* */
template < typename U >
std::optional< U > pop( uses_optional_t )
{
U to_dequeue;
if ( pop( to_dequeue ) )
return to_dequeue;
else
return std::nullopt;
}
#endif

/** Pops object from stack.
*
Expand Down
16 changes: 16 additions & 0 deletions test/queue_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,19 @@ BOOST_AUTO_TEST_CASE( move_semantics )

stk.consume_all( []( int ) {} );
}

#if !defined( BOOST_NO_CXX17_HDR_OPTIONAL )

BOOST_AUTO_TEST_CASE( queue_uses_optional )
{
boost::lockfree::queue< int > stk( 5 );

bool pop_to_nullopt = stk.pop( boost::lockfree::uses_optional ) == std::nullopt;
BOOST_TEST_REQUIRE( pop_to_nullopt );

stk.push( 53 );
bool pop_to_optional = stk.pop( boost::lockfree::uses_optional ) == 53;
BOOST_TEST_REQUIRE( pop_to_optional );
}

#endif
16 changes: 16 additions & 0 deletions test/spsc_queue_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,19 @@ BOOST_AUTO_TEST_CASE( move_semantics )

stk.consume_all( []( std::unique_ptr< int > ) {} );
}

#if !defined( BOOST_NO_CXX17_HDR_OPTIONAL )

BOOST_AUTO_TEST_CASE( queue_uses_optional )
{
boost::lockfree::spsc_queue< int > stk( 5 );

bool pop_to_nullopt = stk.pop( boost::lockfree::uses_optional ) == std::nullopt;
BOOST_TEST_REQUIRE( pop_to_nullopt );

stk.push( 53 );
bool pop_to_optional = stk.pop( boost::lockfree::uses_optional ) == 53;
BOOST_TEST_REQUIRE( pop_to_optional );
}

#endif
16 changes: 16 additions & 0 deletions test/stack_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,19 @@ BOOST_AUTO_TEST_CASE( move_semantics )

stk.consume_all( []( std::unique_ptr< int > ) {} );
}

#if !defined( BOOST_NO_CXX17_HDR_OPTIONAL )

BOOST_AUTO_TEST_CASE( queue_uses_optional )
{
boost::lockfree::stack< int > stk( 5 );

bool pop_to_nullopt = stk.pop( boost::lockfree::uses_optional ) == std::nullopt;
BOOST_TEST_REQUIRE( pop_to_nullopt );

stk.push( 53 );
bool pop_to_optional = stk.pop( boost::lockfree::uses_optional ) == 53;
BOOST_TEST_REQUIRE( pop_to_optional );
}

#endif

0 comments on commit 8e5e4eb

Please sign in to comment.