mirror of
https://github.com/boostorg/lockfree.git
synced 2026-07-21 13:23:29 +00:00
Lockfree: remove use of atomic wrapper
std::atomic is well implemented nowadays. removing the boost.atomic wrapper code
This commit is contained in:
@@ -26,7 +26,6 @@ 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/atomic.hpp
|
||||
include/boost/lockfree/detail/copy_payload.hpp
|
||||
include/boost/lockfree/detail/freelist.hpp
|
||||
include/boost/lockfree/detail/parameter.hpp
|
||||
@@ -48,7 +47,6 @@ target_link_libraries(boost_lockfree
|
||||
INTERFACE
|
||||
Boost::align
|
||||
Boost::assert
|
||||
Boost::atomic
|
||||
Boost::config
|
||||
Boost::core
|
||||
Boost::parameter
|
||||
|
||||
@@ -8,7 +8,6 @@ require-b2 5.2 ;
|
||||
constant boost_dependencies :
|
||||
/boost/align//boost_align
|
||||
/boost/assert//boost_assert
|
||||
/boost/atomic//boost_atomic
|
||||
/boost/config//boost_config
|
||||
/boost/core//boost_core
|
||||
/boost/parameter//boost_parameter
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
// Copyright (C) 2011-2013, 2016 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_ATOMIC_HPP
|
||||
#define BOOST_LOCKFREE_DETAIL_ATOMIC_HPP
|
||||
|
||||
#if defined( BOOST_LOCKFREE_FORCE_BOOST_ATOMIC )
|
||||
# include <boost/atomic.hpp>
|
||||
#else
|
||||
# include <atomic>
|
||||
#endif
|
||||
|
||||
namespace boost { namespace lockfree {
|
||||
namespace detail {
|
||||
|
||||
#if defined( BOOST_LOCKFREE_FORCE_BOOST_ATOMIC )
|
||||
using boost::atomic;
|
||||
using boost::memory_order_acquire;
|
||||
using boost::memory_order_consume;
|
||||
using boost::memory_order_relaxed;
|
||||
using boost::memory_order_release;
|
||||
#else
|
||||
using std::atomic;
|
||||
using std::memory_order_acquire;
|
||||
using std::memory_order_consume;
|
||||
using std::memory_order_relaxed;
|
||||
using std::memory_order_release;
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
using detail::atomic;
|
||||
using detail::memory_order_acquire;
|
||||
using detail::memory_order_consume;
|
||||
using detail::memory_order_relaxed;
|
||||
using detail::memory_order_release;
|
||||
|
||||
}} // namespace boost::lockfree
|
||||
|
||||
#endif /* BOOST_LOCKFREE_DETAIL_ATOMIC_HPP */
|
||||
@@ -10,6 +10,7 @@
|
||||
#define BOOST_LOCKFREE_FREELIST_HPP_INCLUDED
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
@@ -20,7 +21,6 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <boost/lockfree/detail/atomic.hpp>
|
||||
#include <boost/lockfree/detail/parameter.hpp>
|
||||
#include <boost/lockfree/detail/tagged_ptr.hpp>
|
||||
|
||||
@@ -181,7 +181,7 @@ private:
|
||||
template < bool Bounded >
|
||||
T* allocate_impl( void )
|
||||
{
|
||||
tagged_node_ptr old_pool = pool_.load( memory_order_consume );
|
||||
tagged_node_ptr old_pool = pool_.load( std::memory_order_consume );
|
||||
|
||||
for ( ;; ) {
|
||||
if ( !old_pool.get_ptr() ) {
|
||||
@@ -206,7 +206,7 @@ private:
|
||||
template < bool Bounded >
|
||||
T* allocate_impl_unsafe( void )
|
||||
{
|
||||
tagged_node_ptr old_pool = pool_.load( memory_order_relaxed );
|
||||
tagged_node_ptr old_pool = pool_.load( std::memory_order_relaxed );
|
||||
|
||||
if ( !old_pool.get_ptr() ) {
|
||||
if ( !Bounded ) {
|
||||
@@ -220,7 +220,7 @@ private:
|
||||
freelist_node* new_pool_ptr = old_pool->next.get_ptr();
|
||||
tagged_node_ptr new_pool( new_pool_ptr, old_pool.get_next_tag() );
|
||||
|
||||
pool_.store( new_pool, memory_order_relaxed );
|
||||
pool_.store( new_pool, std::memory_order_relaxed );
|
||||
void* ptr = old_pool.get_ptr();
|
||||
return reinterpret_cast< T* >( ptr );
|
||||
}
|
||||
@@ -239,7 +239,7 @@ private:
|
||||
void deallocate_impl( T* n )
|
||||
{
|
||||
void* node = n;
|
||||
tagged_node_ptr old_pool = pool_.load( memory_order_consume );
|
||||
tagged_node_ptr old_pool = pool_.load( std::memory_order_consume );
|
||||
freelist_node* new_pool_ptr = reinterpret_cast< freelist_node* >( node );
|
||||
|
||||
for ( ;; ) {
|
||||
@@ -254,16 +254,16 @@ private:
|
||||
void deallocate_impl_unsafe( T* n )
|
||||
{
|
||||
void* node = n;
|
||||
tagged_node_ptr old_pool = pool_.load( memory_order_relaxed );
|
||||
tagged_node_ptr old_pool = pool_.load( std::memory_order_relaxed );
|
||||
freelist_node* new_pool_ptr = reinterpret_cast< freelist_node* >( node );
|
||||
|
||||
tagged_node_ptr new_pool( new_pool_ptr, old_pool.get_tag() );
|
||||
new_pool->next.set_ptr( old_pool.get_ptr() );
|
||||
|
||||
pool_.store( new_pool, memory_order_relaxed );
|
||||
pool_.store( new_pool, std::memory_order_relaxed );
|
||||
}
|
||||
|
||||
atomic< tagged_node_ptr > pool_;
|
||||
std::atomic< tagged_node_ptr > pool_;
|
||||
};
|
||||
|
||||
class alignas( 4 ) tagged_index
|
||||
@@ -559,7 +559,7 @@ protected: // allow use from subclasses
|
||||
private:
|
||||
index_t allocate_impl( void )
|
||||
{
|
||||
tagged_index old_pool = pool_.load( memory_order_consume );
|
||||
tagged_index old_pool = pool_.load( std::memory_order_consume );
|
||||
|
||||
for ( ;; ) {
|
||||
index_t index = old_pool.get_index();
|
||||
@@ -578,7 +578,7 @@ private:
|
||||
|
||||
index_t allocate_impl_unsafe( void )
|
||||
{
|
||||
tagged_index old_pool = pool_.load( memory_order_consume );
|
||||
tagged_index old_pool = pool_.load( std::memory_order_consume );
|
||||
|
||||
index_t index = old_pool.get_index();
|
||||
if ( index == null_handle() )
|
||||
@@ -589,7 +589,7 @@ private:
|
||||
|
||||
tagged_index new_pool( next_index->get_index(), old_pool.get_next_tag() );
|
||||
|
||||
pool_.store( new_pool, memory_order_relaxed );
|
||||
pool_.store( new_pool, std::memory_order_relaxed );
|
||||
return old_pool.get_index();
|
||||
}
|
||||
|
||||
@@ -605,7 +605,7 @@ private:
|
||||
void deallocate_impl( index_t index )
|
||||
{
|
||||
freelist_node* new_pool_node = reinterpret_cast< freelist_node* >( NodeStorage::nodes() + index );
|
||||
tagged_index old_pool = pool_.load( memory_order_consume );
|
||||
tagged_index old_pool = pool_.load( std::memory_order_consume );
|
||||
|
||||
for ( ;; ) {
|
||||
tagged_index new_pool( index, old_pool.get_tag() );
|
||||
@@ -619,7 +619,7 @@ private:
|
||||
void deallocate_impl_unsafe( index_t index )
|
||||
{
|
||||
freelist_node* new_pool_node = reinterpret_cast< freelist_node* >( NodeStorage::nodes() + index );
|
||||
tagged_index old_pool = pool_.load( memory_order_consume );
|
||||
tagged_index old_pool = pool_.load( std::memory_order_consume );
|
||||
|
||||
tagged_index new_pool( index, old_pool.get_tag() );
|
||||
new_pool_node->next.set_index( old_pool.get_index() );
|
||||
@@ -627,7 +627,7 @@ private:
|
||||
pool_.store( new_pool );
|
||||
}
|
||||
|
||||
atomic< tagged_index > pool_;
|
||||
std::atomic< tagged_index > pool_;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -16,12 +16,14 @@
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <optional>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/allocator_access.hpp>
|
||||
#include <boost/parameter/optional.hpp>
|
||||
#include <boost/parameter/parameters.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>
|
||||
@@ -29,7 +31,6 @@
|
||||
#include <boost/lockfree/detail/uses_optional.hpp>
|
||||
#include <boost/lockfree/lockfree_forward.hpp>
|
||||
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
# pragma warning( push )
|
||||
# pragma warning( disable : 4324 ) // structure was padded due to __declspec(align())
|
||||
@@ -42,8 +43,6 @@
|
||||
// takes an allocator of another type and rebinds it
|
||||
#endif
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace boost { namespace lockfree {
|
||||
|
||||
#ifndef BOOST_DOXYGEN_INVOKED
|
||||
@@ -113,9 +112,9 @@ private:
|
||||
data( v )
|
||||
{
|
||||
/* increment tag to avoid ABA problem */
|
||||
tagged_node_handle old_next = next.load( memory_order_relaxed );
|
||||
tagged_node_handle old_next = next.load( std::memory_order_relaxed );
|
||||
tagged_node_handle new_next( null_handle, old_next.get_next_tag() );
|
||||
next.store( new_next, memory_order_release );
|
||||
next.store( new_next, std::memory_order_release );
|
||||
}
|
||||
|
||||
node( handle_type null_handle ) :
|
||||
@@ -125,7 +124,7 @@ private:
|
||||
node( void )
|
||||
{}
|
||||
|
||||
atomic< tagged_node_handle > next;
|
||||
std::atomic< tagged_node_handle > next;
|
||||
T data;
|
||||
};
|
||||
|
||||
@@ -138,8 +137,8 @@ private:
|
||||
{
|
||||
node* n = pool.template construct< true, false >( pool.null_handle() );
|
||||
tagged_node_handle dummy_node( pool.get_handle( n ), 0 );
|
||||
head_.store( dummy_node, memory_order_relaxed );
|
||||
tail_.store( dummy_node, memory_order_release );
|
||||
head_.store( dummy_node, std::memory_order_relaxed );
|
||||
tail_.store( dummy_node, std::memory_order_release );
|
||||
}
|
||||
|
||||
struct implementation_defined
|
||||
@@ -283,7 +282,7 @@ public:
|
||||
{
|
||||
consume_all( []( const T& ) {} );
|
||||
|
||||
pool.template destruct< false >( head_.load( memory_order_relaxed ) );
|
||||
pool.template destruct< false >( head_.load( std::memory_order_relaxed ) );
|
||||
}
|
||||
|
||||
/** Check if the queue is empty
|
||||
@@ -360,12 +359,12 @@ private:
|
||||
return false;
|
||||
|
||||
for ( ;; ) {
|
||||
tagged_node_handle tail = tail_.load( memory_order_acquire );
|
||||
tagged_node_handle tail = tail_.load( std::memory_order_acquire );
|
||||
node* tail_node = pool.get_pointer( tail );
|
||||
tagged_node_handle next = tail_node->next.load( memory_order_acquire );
|
||||
tagged_node_handle next = tail_node->next.load( std::memory_order_acquire );
|
||||
node* next_ptr = pool.get_pointer( next );
|
||||
|
||||
tagged_node_handle tail2 = tail_.load( memory_order_acquire );
|
||||
tagged_node_handle tail2 = tail_.load( std::memory_order_acquire );
|
||||
if ( BOOST_LIKELY( tail == tail2 ) ) {
|
||||
if ( next_ptr == 0 ) {
|
||||
tagged_node_handle new_tail_next( node_handle, next.get_next_tag() );
|
||||
@@ -401,16 +400,16 @@ public:
|
||||
return false;
|
||||
|
||||
for ( ;; ) {
|
||||
tagged_node_handle tail = tail_.load( memory_order_relaxed );
|
||||
tagged_node_handle next = tail->next.load( memory_order_relaxed );
|
||||
tagged_node_handle tail = tail_.load( std::memory_order_relaxed );
|
||||
tagged_node_handle next = tail->next.load( std::memory_order_relaxed );
|
||||
node* next_ptr = next.get_ptr();
|
||||
|
||||
if ( next_ptr == 0 ) {
|
||||
tail->next.store( tagged_node_handle( n, next.get_next_tag() ), memory_order_relaxed );
|
||||
tail_.store( tagged_node_handle( n, tail.get_next_tag() ), memory_order_relaxed );
|
||||
tail->next.store( tagged_node_handle( n, next.get_next_tag() ), std::memory_order_relaxed );
|
||||
tail_.store( tagged_node_handle( n, tail.get_next_tag() ), std::memory_order_relaxed );
|
||||
return true;
|
||||
} else
|
||||
tail_.store( tagged_node_handle( next_ptr, tail.get_next_tag() ), memory_order_relaxed );
|
||||
tail_.store( tagged_node_handle( next_ptr, tail.get_next_tag() ), std::memory_order_relaxed );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,14 +437,14 @@ public:
|
||||
bool pop( U& ret )
|
||||
{
|
||||
for ( ;; ) {
|
||||
tagged_node_handle head = head_.load( memory_order_acquire );
|
||||
tagged_node_handle head = head_.load( std::memory_order_acquire );
|
||||
node* head_ptr = pool.get_pointer( head );
|
||||
|
||||
tagged_node_handle tail = tail_.load( memory_order_acquire );
|
||||
tagged_node_handle next = head_ptr->next.load( memory_order_acquire );
|
||||
tagged_node_handle tail = tail_.load( std::memory_order_acquire );
|
||||
tagged_node_handle next = head_ptr->next.load( std::memory_order_acquire );
|
||||
node* next_ptr = pool.get_pointer( next );
|
||||
|
||||
tagged_node_handle head2 = head_.load( memory_order_acquire );
|
||||
tagged_node_handle head2 = head_.load( std::memory_order_acquire );
|
||||
if ( BOOST_LIKELY( head == head2 ) ) {
|
||||
if ( pool.get_handle( head ) == pool.get_handle( tail ) ) {
|
||||
if ( next_ptr == 0 )
|
||||
@@ -535,10 +534,10 @@ public:
|
||||
bool unsynchronized_pop( U& ret )
|
||||
{
|
||||
for ( ;; ) {
|
||||
tagged_node_handle head = head_.load( memory_order_relaxed );
|
||||
tagged_node_handle head = head_.load( std::memory_order_relaxed );
|
||||
node* head_ptr = pool.get_pointer( head );
|
||||
tagged_node_handle tail = tail_.load( memory_order_relaxed );
|
||||
tagged_node_handle next = head_ptr->next.load( memory_order_relaxed );
|
||||
tagged_node_handle tail = tail_.load( std::memory_order_relaxed );
|
||||
tagged_node_handle next = head_ptr->next.load( std::memory_order_relaxed );
|
||||
node* next_ptr = pool.get_pointer( next );
|
||||
|
||||
if ( pool.get_handle( head ) == pool.get_handle( tail ) ) {
|
||||
@@ -603,10 +602,10 @@ public:
|
||||
|
||||
private:
|
||||
#ifndef BOOST_DOXYGEN_INVOKED
|
||||
atomic< tagged_node_handle > head_;
|
||||
std::atomic< tagged_node_handle > head_;
|
||||
static constexpr size_t padding_size = detail::cacheline_bytes - sizeof( tagged_node_handle );
|
||||
char padding1[ padding_size ];
|
||||
atomic< tagged_node_handle > tail_;
|
||||
std::atomic< tagged_node_handle > tail_;
|
||||
char padding2[ padding_size ];
|
||||
|
||||
pool_t pool;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
@@ -27,7 +28,6 @@
|
||||
#include <boost/parameter/optional.hpp>
|
||||
#include <boost/parameter/parameters.hpp>
|
||||
|
||||
#include <boost/lockfree/detail/atomic.hpp>
|
||||
#include <boost/lockfree/detail/copy_payload.hpp>
|
||||
#include <boost/lockfree/detail/parameter.hpp>
|
||||
#include <boost/lockfree/detail/prefix.hpp>
|
||||
@@ -42,11 +42,11 @@ class ringbuffer_base
|
||||
{
|
||||
#ifndef BOOST_DOXYGEN_INVOKED
|
||||
protected:
|
||||
typedef std::size_t size_t;
|
||||
static constexpr int padding_size = cacheline_bytes - sizeof( size_t );
|
||||
atomic< size_t > write_index_;
|
||||
char padding1[ padding_size ]; /* force read_index and write_index to different cache lines */
|
||||
atomic< size_t > read_index_;
|
||||
typedef std::size_t size_t;
|
||||
static constexpr int padding_size = cacheline_bytes - sizeof( size_t );
|
||||
std::atomic< size_t > write_index_;
|
||||
char padding1[ padding_size ]; /* force read_index and write_index to different cache lines */
|
||||
std::atomic< size_t > read_index_;
|
||||
|
||||
protected:
|
||||
ringbuffer_base( void ) :
|
||||
@@ -81,45 +81,45 @@ protected:
|
||||
|
||||
size_t read_available( size_t max_size ) const
|
||||
{
|
||||
size_t write_index = write_index_.load( memory_order_acquire );
|
||||
const size_t read_index = read_index_.load( memory_order_relaxed );
|
||||
size_t write_index = write_index_.load( std::memory_order_acquire );
|
||||
const size_t read_index = read_index_.load( std::memory_order_relaxed );
|
||||
return read_available( write_index, read_index, max_size );
|
||||
}
|
||||
|
||||
size_t write_available( size_t max_size ) const
|
||||
{
|
||||
size_t write_index = write_index_.load( memory_order_relaxed );
|
||||
const size_t read_index = read_index_.load( memory_order_acquire );
|
||||
size_t write_index = write_index_.load( std::memory_order_relaxed );
|
||||
const size_t read_index = read_index_.load( std::memory_order_acquire );
|
||||
return write_available( write_index, read_index, max_size );
|
||||
}
|
||||
|
||||
|
||||
bool push( const T& t, T* buffer, size_t max_size )
|
||||
{
|
||||
const size_t write_index = write_index_.load( memory_order_relaxed ); // only written from push thread
|
||||
const size_t write_index = write_index_.load( std::memory_order_relaxed ); // only written from push thread
|
||||
const size_t next = next_index( write_index, max_size );
|
||||
|
||||
if ( next == read_index_.load( memory_order_acquire ) )
|
||||
if ( next == read_index_.load( std::memory_order_acquire ) )
|
||||
return false; /* ringbuffer is full */
|
||||
|
||||
new ( buffer + write_index ) T( t ); // copy-construct
|
||||
|
||||
write_index_.store( next, memory_order_release );
|
||||
write_index_.store( next, std::memory_order_release );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool push( T&& t, T* buffer, size_t max_size )
|
||||
{
|
||||
const size_t write_index = write_index_.load( memory_order_relaxed ); // only written from push thread
|
||||
const size_t write_index = write_index_.load( std::memory_order_relaxed ); // only written from push thread
|
||||
const size_t next = next_index( write_index, max_size );
|
||||
|
||||
if ( next == read_index_.load( memory_order_acquire ) )
|
||||
if ( next == read_index_.load( std::memory_order_acquire ) )
|
||||
return false; /* ringbuffer is full */
|
||||
|
||||
new ( buffer + write_index ) T( std::forward< T >( t ) ); // move-construct
|
||||
|
||||
write_index_.store( next, memory_order_release );
|
||||
write_index_.store( next, std::memory_order_release );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -134,8 +134,8 @@ protected:
|
||||
{
|
||||
// FIXME: avoid std::distance
|
||||
|
||||
const size_t write_index = write_index_.load( memory_order_relaxed ); // only written from push thread
|
||||
const size_t read_index = read_index_.load( memory_order_acquire );
|
||||
const size_t write_index = write_index_.load( std::memory_order_relaxed ); // only written from push thread
|
||||
const size_t read_index = read_index_.load( std::memory_order_acquire );
|
||||
const size_t avail = write_available( write_index, read_index, max_size );
|
||||
|
||||
if ( avail == 0 )
|
||||
@@ -163,15 +163,15 @@ protected:
|
||||
new_write_index = 0;
|
||||
}
|
||||
|
||||
write_index_.store( new_write_index, memory_order_release );
|
||||
write_index_.store( new_write_index, std::memory_order_release );
|
||||
return last;
|
||||
}
|
||||
|
||||
template < typename Functor >
|
||||
bool consume_one( Functor&& functor, T* buffer, size_t max_size )
|
||||
{
|
||||
const size_t write_index = write_index_.load( memory_order_acquire );
|
||||
const size_t read_index = read_index_.load( memory_order_relaxed ); // only written from pop thread
|
||||
const size_t write_index = write_index_.load( std::memory_order_acquire );
|
||||
const size_t read_index = read_index_.load( std::memory_order_relaxed ); // only written from pop thread
|
||||
if ( empty( write_index, read_index ) )
|
||||
return false;
|
||||
|
||||
@@ -180,15 +180,15 @@ protected:
|
||||
object_to_consume.~T();
|
||||
|
||||
size_t next = next_index( read_index, max_size );
|
||||
read_index_.store( next, memory_order_release );
|
||||
read_index_.store( next, std::memory_order_release );
|
||||
return true;
|
||||
}
|
||||
|
||||
template < typename Functor >
|
||||
size_t consume_all( Functor&& functor, T* internal_buffer, size_t max_size )
|
||||
{
|
||||
const size_t write_index = write_index_.load( memory_order_acquire );
|
||||
const size_t read_index = read_index_.load( memory_order_relaxed ); // only written from pop thread
|
||||
const size_t write_index = write_index_.load( std::memory_order_acquire );
|
||||
const size_t read_index = read_index_.load( std::memory_order_relaxed ); // only written from pop thread
|
||||
|
||||
const size_t avail = read_available( write_index, read_index, max_size );
|
||||
|
||||
@@ -215,14 +215,14 @@ protected:
|
||||
new_read_index = 0;
|
||||
}
|
||||
|
||||
read_index_.store( new_read_index, memory_order_release );
|
||||
read_index_.store( new_read_index, std::memory_order_release );
|
||||
return output_count;
|
||||
}
|
||||
|
||||
size_t pop( T* output_buffer, size_t output_count, T* internal_buffer, size_t max_size )
|
||||
{
|
||||
const size_t write_index = write_index_.load( memory_order_acquire );
|
||||
const size_t read_index = read_index_.load( memory_order_relaxed ); // only written from pop thread
|
||||
const size_t write_index = write_index_.load( std::memory_order_acquire );
|
||||
const size_t read_index = read_index_.load( std::memory_order_relaxed ); // only written from pop thread
|
||||
|
||||
const size_t avail = read_available( write_index, read_index, max_size );
|
||||
|
||||
@@ -248,15 +248,15 @@ protected:
|
||||
new_read_index = 0;
|
||||
}
|
||||
|
||||
read_index_.store( new_read_index, memory_order_release );
|
||||
read_index_.store( new_read_index, std::memory_order_release );
|
||||
return output_count;
|
||||
}
|
||||
|
||||
template < typename OutputIterator >
|
||||
size_t pop_to_output_iterator( OutputIterator it, T* internal_buffer, size_t max_size )
|
||||
{
|
||||
const size_t write_index = write_index_.load( memory_order_acquire );
|
||||
const size_t read_index = read_index_.load( memory_order_relaxed ); // only written from pop thread
|
||||
const size_t write_index = write_index_.load( std::memory_order_acquire );
|
||||
const size_t read_index = read_index_.load( std::memory_order_relaxed ); // only written from pop thread
|
||||
|
||||
const size_t avail = read_available( write_index, read_index, max_size );
|
||||
if ( avail == 0 )
|
||||
@@ -279,19 +279,19 @@ protected:
|
||||
new_read_index = 0;
|
||||
}
|
||||
|
||||
read_index_.store( new_read_index, memory_order_release );
|
||||
read_index_.store( new_read_index, std::memory_order_release );
|
||||
return avail;
|
||||
}
|
||||
|
||||
const T& front( const T* internal_buffer ) const
|
||||
{
|
||||
const size_t read_index = read_index_.load( memory_order_relaxed ); // only written from pop thread
|
||||
const size_t read_index = read_index_.load( std::memory_order_relaxed ); // only written from pop thread
|
||||
return *( internal_buffer + read_index );
|
||||
}
|
||||
|
||||
T& front( T* internal_buffer )
|
||||
{
|
||||
const size_t read_index = read_index_.load( memory_order_relaxed ); // only written from pop thread
|
||||
const size_t read_index = read_index_.load( std::memory_order_relaxed ); // only written from pop thread
|
||||
return *( internal_buffer + read_index );
|
||||
}
|
||||
#endif
|
||||
@@ -308,8 +308,8 @@ public:
|
||||
// make sure to call all destructors!
|
||||
consume_all( []( const T& ) {} );
|
||||
} else {
|
||||
write_index_.store( 0, memory_order_relaxed );
|
||||
read_index_.store( 0, memory_order_release );
|
||||
write_index_.store( 0, std::memory_order_relaxed );
|
||||
read_index_.store( 0, std::memory_order_release );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ public:
|
||||
* */
|
||||
bool empty( void )
|
||||
{
|
||||
return empty( write_index_.load( memory_order_relaxed ), read_index_.load( memory_order_relaxed ) );
|
||||
return empty( write_index_.load( std::memory_order_relaxed ), read_index_.load( std::memory_order_relaxed ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -955,8 +955,8 @@ public:
|
||||
// make sure to call all destructors!
|
||||
consume_all( []( const T& ) {} );
|
||||
} else {
|
||||
base_type::write_index_.store( 0, memory_order_relaxed );
|
||||
base_type::read_index_.store( 0, memory_order_release );
|
||||
base_type::write_index_.store( 0, std::memory_order_relaxed );
|
||||
base_type::read_index_.store( 0, std::memory_order_release );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -15,18 +15,18 @@
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/lockfree/detail/atomic.hpp>
|
||||
#include <boost/lockfree/detail/parameter.hpp>
|
||||
#include <boost/lockfree/detail/uses_optional.hpp>
|
||||
#include <boost/lockfree/lockfree_forward.hpp>
|
||||
#include <boost/lockfree/policies.hpp>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
#include <boost/parameter/optional.hpp>
|
||||
#include <boost/parameter/parameters.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <boost/lockfree/detail/parameter.hpp>
|
||||
#include <boost/lockfree/detail/uses_optional.hpp>
|
||||
#include <boost/lockfree/lockfree_forward.hpp>
|
||||
#include <boost/lockfree/policies.hpp>
|
||||
|
||||
namespace boost { namespace lockfree {
|
||||
|
||||
@@ -264,11 +264,11 @@ private:
|
||||
std::array< cache_aligned_value, 3 > m_buffer;
|
||||
|
||||
alignas( detail::cacheline_bytes ) tagged_index m_write_index { 0 };
|
||||
alignas( detail::cacheline_bytes ) detail::atomic< tagged_index > m_available_index { 1 };
|
||||
alignas( detail::cacheline_bytes ) std::atomic< tagged_index > m_available_index { 1 };
|
||||
alignas( detail::cacheline_bytes ) tagged_index m_read_index { 2 };
|
||||
#endif
|
||||
};
|
||||
|
||||
}} // namespace boost::lockfree
|
||||
}} // namespace boost::lockfree
|
||||
|
||||
#endif /* BOOST_LOCKFREE_SPSC_VALUE_HPP_INCLUDED */
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <boost/parameter/optional.hpp>
|
||||
#include <boost/parameter/parameters.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>
|
||||
@@ -260,7 +259,7 @@ private:
|
||||
|
||||
void link_nodes_atomic( node* new_top_node, node* end_node )
|
||||
{
|
||||
tagged_node_handle old_tos = tos.load( detail::memory_order_relaxed );
|
||||
tagged_node_handle old_tos = tos.load( std::memory_order_relaxed );
|
||||
for ( ;; ) {
|
||||
tagged_node_handle new_tos( pool.get_handle( new_top_node ), old_tos.get_tag() );
|
||||
end_node->next = pool.get_handle( old_tos );
|
||||
@@ -272,12 +271,12 @@ private:
|
||||
|
||||
void link_nodes_unsafe( node* new_top_node, node* end_node )
|
||||
{
|
||||
tagged_node_handle old_tos = tos.load( detail::memory_order_relaxed );
|
||||
tagged_node_handle old_tos = tos.load( std::memory_order_relaxed );
|
||||
|
||||
tagged_node_handle new_tos( pool.get_handle( new_top_node ), old_tos.get_tag() );
|
||||
end_node->next = pool.get_handle( old_tos );
|
||||
|
||||
tos.store( new_tos, memory_order_relaxed );
|
||||
tos.store( new_tos, std::memory_order_relaxed );
|
||||
}
|
||||
|
||||
template < bool Threadsafe, bool Bounded, typename ConstIterator >
|
||||
@@ -613,7 +612,7 @@ public:
|
||||
template < typename U, typename Enabler = std::enable_if< std::is_convertible< T, U >::value > >
|
||||
bool unsynchronized_pop( U& ret )
|
||||
{
|
||||
tagged_node_handle old_tos = tos.load( detail::memory_order_relaxed );
|
||||
tagged_node_handle old_tos = tos.load( std::memory_order_relaxed );
|
||||
node* old_tos_pointer = pool.get_pointer( old_tos );
|
||||
|
||||
if ( !pool.get_pointer( old_tos ) )
|
||||
@@ -622,7 +621,7 @@ public:
|
||||
node* new_tos_ptr = pool.get_pointer( old_tos_pointer->next );
|
||||
tagged_node_handle new_tos( pool.get_handle( new_tos_ptr ), old_tos.get_next_tag() );
|
||||
|
||||
tos.store( new_tos, memory_order_relaxed );
|
||||
tos.store( new_tos, std::memory_order_relaxed );
|
||||
ret = std::move( old_tos_pointer->v );
|
||||
pool.template destruct< false >( old_tos );
|
||||
return true;
|
||||
@@ -639,7 +638,7 @@ public:
|
||||
template < typename Functor >
|
||||
bool consume_one( Functor&& f )
|
||||
{
|
||||
tagged_node_handle old_tos = tos.load( detail::memory_order_consume );
|
||||
tagged_node_handle old_tos = tos.load( std::memory_order_consume );
|
||||
|
||||
for ( ;; ) {
|
||||
node* old_tos_pointer = pool.get_pointer( old_tos );
|
||||
@@ -686,7 +685,7 @@ public:
|
||||
size_t consume_all_atomic( Functor&& f )
|
||||
{
|
||||
size_t element_count = 0;
|
||||
tagged_node_handle old_tos = tos.load( detail::memory_order_consume );
|
||||
tagged_node_handle old_tos = tos.load( std::memory_order_consume );
|
||||
|
||||
for ( ;; ) {
|
||||
node* old_tos_pointer = pool.get_pointer( old_tos );
|
||||
@@ -733,7 +732,7 @@ public:
|
||||
size_t consume_all_atomic_reversed( Functor&& f )
|
||||
{
|
||||
size_t element_count = 0;
|
||||
tagged_node_handle old_tos = tos.load( detail::memory_order_consume );
|
||||
tagged_node_handle old_tos = tos.load( std::memory_order_consume );
|
||||
|
||||
for ( ;; ) {
|
||||
node* old_tos_pointer = pool.get_pointer( old_tos );
|
||||
@@ -798,7 +797,7 @@ public:
|
||||
|
||||
private:
|
||||
#ifndef BOOST_DOXYGEN_INVOKED
|
||||
detail::atomic< tagged_node_handle > tos;
|
||||
std::atomic< tagged_node_handle > tos;
|
||||
|
||||
static const int padding_size = detail::cacheline_bytes - sizeof( tagged_node_handle );
|
||||
char padding[ padding_size ];
|
||||
|
||||
@@ -23,22 +23,20 @@
|
||||
|
||||
#include "test_helpers.hpp"
|
||||
|
||||
using boost::lockfree::detail::atomic;
|
||||
|
||||
atomic< bool > test_running( false );
|
||||
std::atomic< bool > test_running( false );
|
||||
|
||||
struct dummy
|
||||
{
|
||||
dummy( void )
|
||||
{
|
||||
if ( test_running.load( boost::lockfree::detail::memory_order_relaxed ) )
|
||||
if ( test_running.load( std::memory_order_relaxed ) )
|
||||
assert( allocated == 0 );
|
||||
allocated = 1;
|
||||
}
|
||||
|
||||
~dummy( void )
|
||||
{
|
||||
if ( test_running.load( boost::lockfree::detail::memory_order_relaxed ) )
|
||||
if ( test_running.load( std::memory_order_relaxed ) )
|
||||
assert( allocated == 1 );
|
||||
allocated = 0;
|
||||
}
|
||||
@@ -131,7 +129,7 @@ struct freelist_tester
|
||||
freelist_type fl;
|
||||
boost::lockfree::queue< dummy* > allocated_nodes;
|
||||
|
||||
atomic< bool > running;
|
||||
std::atomic< bool > running;
|
||||
static_hashed_set< dummy*, 1 << 16 > working_set;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user