From 03f5ca639020ed90350efacaff291094e19f4031 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Wed, 20 May 2026 11:57:36 +0800 Subject: [PATCH 1/5] cleanups: improve use of concepts --- include/boost/lockfree/queue.hpp | 48 +++++++++++++++++------- include/boost/lockfree/spsc_queue.hpp | 54 +++++++++++++++++++++++---- include/boost/lockfree/stack.hpp | 48 ++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 22 deletions(-) diff --git a/include/boost/lockfree/queue.hpp b/include/boost/lockfree/queue.hpp index 9be5fb6..7e910dd 100644 --- a/include/boost/lockfree/queue.hpp +++ b/include/boost/lockfree/queue.hpp @@ -177,8 +177,6 @@ class queue requires( has_capacity ) #endif : - head_( tagged_node_handle( 0, 0 ) ), - tail_( tagged_node_handle( 0, 0 ) ), pool( node_allocator(), capacity ) { // Don't use BOOST_STATIC_ASSERT() here since it will be evaluated when compiling @@ -191,10 +189,13 @@ class queue * * \pre Must specify a capacity<> argument * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + template < typename U > + requires( has_capacity ) +#else template < typename U, typename Enabler = std::enable_if< has_capacity > > +#endif explicit queue( typename boost::allocator_rebind< node_allocator, U >::type const& alloc ) : - head_( tagged_node_handle( 0, 0 ) ), - tail_( tagged_node_handle( 0, 0 ) ), pool( alloc, capacity ) { initialize(); @@ -204,10 +205,14 @@ class queue * * \pre Must specify a capacity<> argument * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + explicit queue( allocator const& alloc ) + requires( has_capacity ) + : +#else template < typename Enabler = std::enable_if< has_capacity > > explicit queue( allocator const& alloc ) : - head_( tagged_node_handle( 0, 0 ) ), - tail_( tagged_node_handle( 0, 0 ) ), +#endif pool( alloc, capacity ) { initialize(); @@ -219,10 +224,14 @@ class queue * * \pre Must \b not specify a capacity<> argument * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + explicit queue( size_type n ) + requires( !has_capacity ) + : +#else template < typename Enabler = std::enable_if< !has_capacity > > explicit queue( size_type n ) : - head_( tagged_node_handle( 0, 0 ) ), - tail_( tagged_node_handle( 0, 0 ) ), +#endif pool( node_allocator(), n + 1 ) { initialize(); @@ -234,10 +243,13 @@ class queue * * \pre Must \b not specify a capacity<> argument * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + template < typename U > + requires( !has_capacity ) +#else template < typename U, typename Enabler = std::enable_if< !has_capacity > > +#endif queue( size_type n, typename boost::allocator_rebind< node_allocator, U >::type const& alloc ) : - head_( tagged_node_handle( 0, 0 ) ), - tail_( tagged_node_handle( 0, 0 ) ), pool( alloc, n + 1 ) { initialize(); @@ -249,10 +261,14 @@ class queue * * \pre Must \b not specify a capacity<> argument * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + queue( size_type n, allocator const& alloc ) + requires( !has_capacity ) + : +#else template < typename Enabler = std::enable_if< !has_capacity > > queue( size_type n, allocator const& alloc ) : - head_( tagged_node_handle( 0, 0 ) ), - tail_( tagged_node_handle( 0, 0 ) ), +#endif pool( alloc, n + 1 ) { initialize(); @@ -625,8 +641,12 @@ class queue private: #ifndef BOOST_DOXYGEN_INVOKED - atomic< tagged_node_handle > head_; - alignas( detail::cacheline_bytes ) atomic< tagged_node_handle > tail_; + atomic< tagged_node_handle > head_ { + tagged_node_handle( 0, 0 ), + }; + alignas( detail::cacheline_bytes ) atomic< tagged_node_handle > tail_ { + tagged_node_handle( 0, 0 ), + }; pool_t pool; #endif diff --git a/include/boost/lockfree/spsc_queue.hpp b/include/boost/lockfree/spsc_queue.hpp index b2a4fcc..2205026 100644 --- a/include/boost/lockfree/spsc_queue.hpp +++ b/include/boost/lockfree/spsc_queue.hpp @@ -43,13 +43,11 @@ class ringbuffer_base #ifndef BOOST_DOXYGEN_INVOKED protected: typedef std::size_t size_t; - alignas( cacheline_bytes ) atomic< size_t > write_index_; - alignas( cacheline_bytes ) atomic< size_t > read_index_; + alignas( cacheline_bytes ) atomic< size_t > write_index_ {}; + alignas( cacheline_bytes ) atomic< size_t > read_index_ {}; protected: - ringbuffer_base( void ) : - write_index_( 0 ), - read_index_( 0 ) + ringbuffer_base( void ) {} static size_t next_index( size_t arg, size_t max_size ) @@ -653,7 +651,12 @@ class spsc_queue : public detail::make_ringbuffer< T, Options... >::ringbuffer_t * * \note This is just for API compatibility: an allocator isn't actually needed */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + template < typename U > + requires( !runtime_sized ) +#else template < typename U, typename Enabler = std::enable_if< !runtime_sized > > +#endif explicit spsc_queue( typename boost::allocator_rebind< allocator, U >::type const& ) {} @@ -663,16 +666,27 @@ class spsc_queue : public detail::make_ringbuffer< T, Options... >::ringbuffer_t * * \note This is just for API compatibility: an allocator isn't actually needed */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + explicit spsc_queue( allocator const& ) + requires( !runtime_sized ) +#else template < typename Enabler = std::enable_if< !runtime_sized > > explicit spsc_queue( allocator const& ) +#endif {} /** Constructs a spsc_queue for element_count elements * * \pre spsc_queue must be configured to be sized at run-time */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + explicit spsc_queue( size_type element_count ) + requires( runtime_sized ) +#else template < typename Enabler = std::enable_if< runtime_sized > > - explicit spsc_queue( size_type element_count ) : + explicit spsc_queue( size_type element_count ) +#endif + : base_type( element_count ) {} @@ -680,7 +694,12 @@ class spsc_queue : public detail::make_ringbuffer< T, Options... >::ringbuffer_t * * \pre spsc_queue must be configured to be sized at run-time */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + template < typename U > + requires( runtime_sized ) +#else template < typename U, typename Enabler = std::enable_if< runtime_sized > > +#endif spsc_queue( size_type element_count, typename boost::allocator_rebind< allocator, U >::type const& alloc ) : base_type( alloc, element_count ) {} @@ -689,8 +708,14 @@ class spsc_queue : public detail::make_ringbuffer< T, Options... >::ringbuffer_t * * \pre spsc_queue must be configured to be sized at run-time */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + spsc_queue( size_type element_count, allocator_arg const& alloc ) + requires( runtime_sized ) +#else template < typename Enabler = std::enable_if< runtime_sized > > - spsc_queue( size_type element_count, allocator_arg const& alloc ) : + spsc_queue( size_type element_count, allocator_arg const& alloc ) +#endif + : base_type( alloc, element_count ) {} @@ -739,7 +764,12 @@ class spsc_queue : public detail::make_ringbuffer< T, Options... >::ringbuffer_t * * \note Thread-safe and wait-free */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + template < typename U > + requires( std::is_convertible_v< T, U > ) +#else template < typename U, typename Enabler = std::enable_if< std::is_convertible< T, U >::value > > +#endif bool pop( U& ret ) { return consume_one( [ & ]( T&& t ) { @@ -866,8 +896,16 @@ class spsc_queue : public detail::make_ringbuffer< T, Options... >::ringbuffer_t * * \note Thread-safe and wait-free * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) template < typename OutputIterator > - typename std::enable_if< !std::is_convertible< T, OutputIterator >::value, size_type >::type pop( OutputIterator it ) + requires( !std::is_convertible_v< T, OutputIterator > ) + size_type +#else + template < typename OutputIterator, + typename Enabler = std::enable_if< !std::is_convertible< T, OutputIterator >::value > > + typename std::enable_if< !std::is_convertible< T, OutputIterator >::value, size_type >::type +#endif + pop( OutputIterator it ) { return base_type::pop_to_output_iterator( it ); } diff --git a/include/boost/lockfree/stack.hpp b/include/boost/lockfree/stack.hpp index b92ed61..75b7d0e 100644 --- a/include/boost/lockfree/stack.hpp +++ b/include/boost/lockfree/stack.hpp @@ -155,7 +155,12 @@ class stack * * \pre Must specify a capacity<> argument * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + template < typename U > + requires( has_capacity ) +#else template < typename U, typename Enabler = std::enable_if< has_capacity > > +#endif explicit stack( typename boost::allocator_rebind< node_allocator, U >::type const& alloc ) : pool( alloc, capacity ) { @@ -166,8 +171,14 @@ class stack * * \pre Must specify a capacity<> argument * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + explicit stack( allocator const& alloc ) + requires( has_capacity ) + : +#else template < typename Enabler = std::enable_if< has_capacity > > explicit stack( allocator const& alloc ) : +#endif pool( alloc, capacity ) { initialize(); @@ -179,8 +190,14 @@ class stack * * \pre Must \b not specify a capacity<> argument * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + explicit stack( size_type n ) + requires( !has_capacity ) + : +#else template < typename Enabler = std::enable_if< !has_capacity > > explicit stack( size_type n ) : +#endif pool( node_allocator(), n ) { initialize(); @@ -198,7 +215,12 @@ class stack * * \pre Must \b not specify a capacity<> argument * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + template < typename U > + requires( !has_capacity ) +#else template < typename U, typename Enabler = std::enable_if< !has_capacity > > +#endif stack( size_type n, typename boost::allocator_rebind< node_allocator, U >::type const& alloc ) : pool( alloc, n ) { @@ -211,8 +233,14 @@ class stack * * \pre Must \b not specify a capacity<> argument * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + stack( size_type n, node_allocator const& alloc ) + requires( !has_capacity ) + : +#else template < typename Enabler = std::enable_if< !has_capacity > > stack( size_type n, node_allocator const& alloc ) : +#endif pool( alloc, n ) { initialize(); @@ -224,8 +252,13 @@ class stack * \note thread-safe, may block if memory allocator blocks * * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + void reserve( size_type n ) + requires( !has_capacity ) +#else template < typename Enabler = std::enable_if< !has_capacity > > void reserve( size_type n ) +#endif { pool.template reserve< true >( n ); } @@ -236,8 +269,13 @@ class stack * \note not thread-safe, may block if memory allocator blocks * * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + void reserve_unsafe( size_type n ) + requires( !has_capacity ) +#else template < typename Enabler = std::enable_if< !has_capacity > > void reserve_unsafe( size_type n ) +#endif { pool.template reserve< false >( n ); } @@ -547,7 +585,12 @@ class stack * \note Thread-safe and non-blocking * * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + template < typename U > + requires( std::is_convertible_v< T, U > ) +#else template < typename U, typename Enabler = std::enable_if< std::is_convertible< T, U >::value > > +#endif bool pop( U& ret ) { return consume_one( [ & ]( T&& arg ) { @@ -613,7 +656,12 @@ class stack * \note Not thread-safe, but non-blocking * * */ +#if !defined( BOOST_NO_CXX20_HDR_CONCEPTS ) + template < typename U > + requires( std::is_convertible_v< T, U > ) +#else template < typename U, typename Enabler = std::enable_if< std::is_convertible< T, U >::value > > +#endif bool unsynchronized_pop( U& ret ) { tagged_node_handle old_tos = tos.load( detail::memory_order_relaxed ); From 9a4842946a14dd3929f5f08806b56ce28f93f6dd Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Wed, 20 May 2026 12:55:50 +0800 Subject: [PATCH 2/5] tests: subdir test - fix transitive dependenies --- .github/workflows/ci.yml | 13 +++++++++++++ test/cmake_subdir_test/CMakeLists.txt | 15 ++++----------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 71a67dd..d5dde3d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -353,6 +353,9 @@ jobs: git submodule update --init tools/boostdep python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + # HACK: boost.functional seems to be missing? + git submodule update --init libs/functional + - name: Use library with add_subdirectory run: | cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test @@ -409,6 +412,8 @@ jobs: git submodule update --init tools/boostdep python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + git submodule update --init libs/functional + - name: Configure run: | cd ../boost-root @@ -475,6 +480,8 @@ jobs: git submodule update --init tools/boostdep python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + git submodule update --init libs/functional + - name: Configure run: | cd ../boost-root @@ -527,6 +534,8 @@ jobs: git submodule update --init tools/boostdep python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + git submodule update --init libs/functional + - name: Use library with add_subdirectory (Debug) shell: cmd run: | @@ -580,6 +589,8 @@ jobs: git submodule update --init tools/boostdep python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + git submodule update --init libs/functional + - name: Configure shell: cmd run: | @@ -651,6 +662,8 @@ jobs: git submodule update --init tools/boostdep python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + git submodule update --init libs/functional + - name: Configure shell: cmd run: | diff --git a/test/cmake_subdir_test/CMakeLists.txt b/test/cmake_subdir_test/CMakeLists.txt index d838496..7a4441a 100644 --- a/test/cmake_subdir_test/CMakeLists.txt +++ b/test/cmake_subdir_test/CMakeLists.txt @@ -10,25 +10,17 @@ add_subdirectory(../.. boostorg/lockfree) set(deps align - array assert atomic config core - integer - iterator - mpl parameter predef - tuple - type_traits utility # transitive bind - concept_check container_hash - conversion describe detail function @@ -36,13 +28,14 @@ set(deps functional fusion io - move mp11 + mpl optional preprocessor - smart_ptr - typeof throw_exception + tuple + type_traits + typeof winapi ) From 3e8d32634fdc6c898129e54f81236f497f7b3c14 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Wed, 20 May 2026 19:08:40 +0800 Subject: [PATCH 3/5] add BOOST_MAY_ALIAS attributes --- include/boost/lockfree/detail/freelist.hpp | 4 ++-- include/boost/lockfree/queue.hpp | 6 +++--- include/boost/lockfree/stack.hpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/lockfree/detail/freelist.hpp b/include/boost/lockfree/detail/freelist.hpp index 1b49c3f..23776b7 100644 --- a/include/boost/lockfree/detail/freelist.hpp +++ b/include/boost/lockfree/detail/freelist.hpp @@ -39,7 +39,7 @@ namespace boost { namespace lockfree { namespace detail { template < typename T, typename Alloc = std::allocator< T > > class alignas( cacheline_bytes ) freelist_stack : Alloc { - struct freelist_node + struct BOOST_MAY_ALIAS freelist_node { tagged_ptr< freelist_node > next; }; @@ -395,7 +395,7 @@ struct runtime_sized_freelist_storage : boost::alignment::aligned_allocator_adap template < typename T, typename NodeStorage = runtime_sized_freelist_storage< T > > class fixed_size_freelist : NodeStorage { - struct freelist_node + struct BOOST_MAY_ALIAS freelist_node { tagged_index next; }; diff --git a/include/boost/lockfree/queue.hpp b/include/boost/lockfree/queue.hpp index 7e910dd..9609ebe 100644 --- a/include/boost/lockfree/queue.hpp +++ b/include/boost/lockfree/queue.hpp @@ -104,7 +104,7 @@ class queue static constexpr bool node_based = !( has_capacity || fixed_sized ); static constexpr bool compile_time_sized = has_capacity; - struct alignas( detail::cacheline_bytes ) node + struct BOOST_MAY_ALIAS 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; @@ -125,8 +125,8 @@ class queue node( void ) {} - atomic< tagged_node_handle > next; - T data; + alignas( detail::cacheline_bytes ) atomic< tagged_node_handle > next; + T data; }; typedef detail::extract_allocator_t< bound_args, node > node_allocator; diff --git a/include/boost/lockfree/stack.hpp b/include/boost/lockfree/stack.hpp index 75b7d0e..d5696d5 100644 --- a/include/boost/lockfree/stack.hpp +++ b/include/boost/lockfree/stack.hpp @@ -82,7 +82,7 @@ class stack static const bool node_based = !( has_capacity || fixed_sized ); static const bool compile_time_sized = has_capacity; - struct node + struct BOOST_MAY_ALIAS node { node( const T& val ) : v( val ) From 444a6ca0ce3251126393131a9dea361363fab365 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Wed, 20 May 2026 21:21:01 +0800 Subject: [PATCH 4/5] ci: fix ccache keys --- .github/workflows/ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d5dde3d..6cd2510 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -151,8 +151,11 @@ jobs: if: env.B2_USE_CCACHE with: path: ~/.ccache - key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}-${{github.sha}} - restore-keys: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}- + key: ccache-${{matrix.os}}-${{matrix.compiler}}-${{ hashFiles('**/*.cpp', '**/*.hpp', '**/*.c', '**/*.h') }} + restore-keys: | + ccache-${{matrix.os}}-${{matrix.compiler}}- + ccache-${{matrix.os}}- + ccache- - name: Install packages if: matrix.install From fc568f4f2ab63f596eb291fd3ef3b379962214d3 Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Wed, 20 May 2026 21:51:09 +0800 Subject: [PATCH 5/5] ci: reorder bjam/clang/win32 builds --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6cd2510..2950f6b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -242,7 +242,7 @@ jobs: os: windows-2022 supported: true - toolset: clang-win - cxxstd: "14,17,20,latest" + cxxstd: "latest,20,17,14" addrmd: 32,64 os: windows-2022 supported: true