Skip to content

Commit

Permalink
lockfree: clean up alignment
Browse files Browse the repository at this point in the history
* use alignas
* use constexpr variable instead of preprocessor define
  • Loading branch information
timblechmann committed Dec 27, 2024
1 parent ba92d67 commit 9b1cf1d
Show file tree
Hide file tree
Showing 11 changed files with 40 additions and 35 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ jobs:
cxxstd: "14,latest"
addrmd: 32,64
os: windows-2019
supported: true
supported: false # requires _ENABLE_ATOMIC_ALIGNMENT_FIX
- toolset: msvc-14.2
cxxstd: "14,17,20,latest"
addrmd: 32,64
Expand Down
3 changes: 2 additions & 1 deletion doc/lockfree.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@ problem is the blocking emulation of lock-free atomics, which in the current imp

[section Supported Platforms & Compilers]

_lockfree_ requires a c++14 compliant compiler
_lockfree_ requires a c++14 compliant compiler. Users of MSVC are strongly recommended to use 2017 or higher. For 2015
=_ENABLE_ATOMIC_ALIGNMENT_FIX= needs to be defined.

[endsect]

Expand Down
18 changes: 8 additions & 10 deletions include/boost/lockfree/detail/freelist.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ namespace boost { namespace lockfree { namespace detail {
//----------------------------------------------------------------------------------------------------------------------

template < typename T, typename Alloc = std::allocator< T > >
class freelist_stack : Alloc
class alignas( cacheline_bytes ) freelist_stack : Alloc
{
struct freelist_node
{
Expand Down Expand Up @@ -267,8 +267,7 @@ class freelist_stack : Alloc
atomic< tagged_node_ptr > pool_;
};

class BOOST_ALIGNMENT( 4 ) // workaround for bugs in MSVC
tagged_index
class tagged_index
{
public:
typedef std::uint16_t tag_t;
Expand Down Expand Up @@ -336,7 +335,7 @@ class BOOST_ALIGNMENT( 4 ) // workaround for bugs in MSVC
//----------------------------------------------------------------------------------------------------------------------

template < typename T, std::size_t size >
struct BOOST_ALIGNMENT( BOOST_LOCKFREE_CACHELINE_BYTES ) compiletime_sized_freelist_storage
struct alignas( cacheline_bytes ) compiletime_sized_freelist_storage
{
// array-based freelists only support a 16bit address space.
BOOST_STATIC_ASSERT( size < 65536 );
Expand All @@ -353,7 +352,7 @@ struct BOOST_ALIGNMENT( BOOST_LOCKFREE_CACHELINE_BYTES ) compiletime_sized_freel
T* nodes( void ) const
{
char* data_pointer = const_cast< char* >( data.data() );
return reinterpret_cast< T* >( boost::alignment::align_up( data_pointer, BOOST_LOCKFREE_CACHELINE_BYTES ) );
return reinterpret_cast< T* >( boost::alignment::align_up( data_pointer, cacheline_bytes ) );
}

std::size_t node_count( void ) const
Expand All @@ -365,12 +364,11 @@ struct BOOST_ALIGNMENT( BOOST_LOCKFREE_CACHELINE_BYTES ) compiletime_sized_freel
//----------------------------------------------------------------------------------------------------------------------

template < typename T, typename Alloc = std::allocator< T > >
struct runtime_sized_freelist_storage :
boost::alignment::aligned_allocator_adaptor< Alloc, BOOST_LOCKFREE_CACHELINE_BYTES >
struct runtime_sized_freelist_storage : boost::alignment::aligned_allocator_adaptor< Alloc, cacheline_bytes >
{
typedef boost::alignment::aligned_allocator_adaptor< Alloc, BOOST_LOCKFREE_CACHELINE_BYTES > allocator_type;
T* nodes_;
std::size_t node_count_;
typedef boost::alignment::aligned_allocator_adaptor< Alloc, cacheline_bytes > allocator_type;
T* nodes_;
std::size_t node_count_;

template < typename Allocator >
runtime_sized_freelist_storage( Allocator const& alloc, std::size_t count ) :
Expand Down
2 changes: 1 addition & 1 deletion include/boost/lockfree/detail/parameter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ using extract_capacity_t = typename extract_capacity< bound_args >::type;
template < typename bound_args, typename T >
struct extract_allocator
{
using default_allocator = boost::alignment::aligned_allocator< T, BOOST_LOCKFREE_CACHELINE_BYTES >;
using default_allocator = boost::alignment::aligned_allocator< T, cacheline_bytes >;
using allocator_t = extract_arg_or_default_t< bound_args, tag::allocator, default_allocator >;

using has_no_allocator_t = has_no_arg_t< bound_args, tag::allocator >;
Expand Down
28 changes: 21 additions & 7 deletions include/boost/lockfree/detail/prefix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,38 @@
#ifndef BOOST_LOCKFREE_PREFIX_HPP_INCLUDED
#define BOOST_LOCKFREE_PREFIX_HPP_INCLUDED

#include <boost/predef.h>

/* this file defines the following macros:
BOOST_LOCKFREE_CACHELINE_BYTES: size of a cache line
BOOST_LOCKFREE_PTR_COMPRESSION: use tag/pointer compression to utilize parts
of the virtual address space as tag (at least 16bit)
*/

#if defined( __s390__ ) || defined( __s390x__ )
# define BOOST_LOCKFREE_CACHELINE_BYTES 256
#elif defined( powerpc ) || defined( __powerpc__ ) || defined( __ppc__ )
# define BOOST_LOCKFREE_CACHELINE_BYTES 128
namespace boost { namespace lockfree { namespace detail {

#ifdef __cpp_inline_variables
# define inline_constexpr inline
#else
# define BOOST_LOCKFREE_CACHELINE_BYTES 64
# define inline_constexpr
#endif

#include <boost/predef.h>
#if BOOST_ARCH_SYS390
inline_constexpr constexpr size_t cacheline_bytes = 256;
#elif BOOST_ARCH_PPC
inline_constexpr constexpr size_t cacheline_bytes = 128;
#elif BOOST_ARCH_ARM && ( BOOST_OS_MACOS || BOOST_OS_IOS )
// technically this is for apple's the M chips, but the A chip are probably similar
inline_constexpr constexpr size_t cacheline_bytes = 128;
#else
inline_constexpr constexpr size_t cacheline_bytes = 64;
#endif

}}} // namespace boost::lockfree::detail

#if BOOST_ARCH_X86_64 || ( ( BOOST_ARCH_ARM >= BOOST_VERSION_NUMBER( 8, 0, 0 ) ) && !BOOST_PLAT_ANDROID )
# define BOOST_LOCKFREE_PTR_COMPRESSION 1
#endif

#undef inline_constexpr

#endif /* BOOST_LOCKFREE_PREFIX_HPP_INCLUDED */
10 changes: 1 addition & 9 deletions include/boost/lockfree/detail/tagged_ptr_dcas.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,7 @@ namespace boost { namespace lockfree { namespace detail {


template < class T >
class
#if BOOST_COMP_MSVC && BOOST_ARCH_X86_64
BOOST_ALIGNMENT( 16 )
#elif BOOST_COMP_MSVC && BOOST_ARCH_X86_32
BOOST_ALIGNMENT( 8 )
#else
BOOST_ALIGNMENT( 2 * sizeof( void* ) )
#endif
tagged_ptr
class alignas( 2 * sizeof( void* ) ) tagged_ptr
{
public:
typedef std::size_t tag_t;
Expand Down
4 changes: 2 additions & 2 deletions include/boost/lockfree/queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class queue
static constexpr bool node_based = !( has_capacity || fixed_sized );
static constexpr bool compile_time_sized = has_capacity;

struct BOOST_ALIGNMENT( BOOST_LOCKFREE_CACHELINE_BYTES ) node
struct alignas( detail::cacheline_bytes ) node
{
typedef typename detail::select_tagged_handle< node, node_based >::tagged_handle_type tagged_node_handle;
typedef typename detail::select_tagged_handle< node, node_based >::handle_type handle_type;
Expand Down Expand Up @@ -606,7 +606,7 @@ class queue
private:
#ifndef BOOST_DOXYGEN_INVOKED
atomic< tagged_node_handle > head_;
static constexpr int padding_size = BOOST_LOCKFREE_CACHELINE_BYTES - sizeof( tagged_node_handle );
static constexpr int padding_size = detail::cacheline_bytes - sizeof( tagged_node_handle );
char padding1[ padding_size ];
atomic< tagged_node_handle > tail_;
char padding2[ padding_size ];
Expand Down
2 changes: 1 addition & 1 deletion include/boost/lockfree/spsc_queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class ringbuffer_base
#ifndef BOOST_DOXYGEN_INVOKED
protected:
typedef std::size_t size_t;
static constexpr int padding_size = BOOST_LOCKFREE_CACHELINE_BYTES - sizeof( 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_;
Expand Down
2 changes: 1 addition & 1 deletion include/boost/lockfree/spsc_value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ struct spsc_value
uint8_t byte;
};

static constexpr size_t cacheline_bytes = BOOST_LOCKFREE_CACHELINE_BYTES;
static constexpr size_t cacheline_bytes = detail::cacheline_bytes;

struct alignas( cacheline_bytes ) cache_aligned_value
{
Expand Down
2 changes: 1 addition & 1 deletion include/boost/lockfree/stack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,7 @@ class stack
#ifndef BOOST_DOXYGEN_INVOKED
detail::atomic< tagged_node_handle > tos;

static const int padding_size = BOOST_LOCKFREE_CACHELINE_BYTES - sizeof( tagged_node_handle );
static const int padding_size = detail::cacheline_bytes - sizeof( tagged_node_handle );
char padding[ padding_size ];

pool_t pool;
Expand Down
2 changes: 1 addition & 1 deletion test/queue_interprocess_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ int main( int argc, char* argv[] )
}
} remover;

managed_shared_memory segment( create_only, "boost_queue_interprocess_test_shm", 524288 );
managed_shared_memory segment( create_only, "boost_queue_interprocess_test_shm", 1'048'576 );
ShmemAllocator alloc_inst( segment.get_segment_manager() );

queue* q = segment.construct< queue >( "queue" )( alloc_inst );
Expand Down

0 comments on commit 9b1cf1d

Please sign in to comment.