From da976d36bc92803e3353b5a0e603d3f3752c8403 Mon Sep 17 00:00:00 2001 From: Shovy <1826784860@qq.com> Date: Tue, 28 Jul 2026 20:07:45 +0800 Subject: [PATCH 1/3] CMake: add build compile fail test option OFF --- CMakeLists.txt | 1 + tests/CMakeLists.txt | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5446b03..53c7599 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ target_include_directories(spsc_ring_buffer INTERFACE option(BUILD_TESTING "Build unit test" ON) option(BUILD_BENCHMARKS "Build microbenchmarks" ON) +option(BUILD_COMPILE_FAIL_TESTS "Build compile failure tests" OFF) if(BUILD_TESTING) enable_testing() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 89eb527..4d204ba 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -8,6 +8,9 @@ FetchContent_Declare( set(gtest_force_shared_ctr ON CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) +if(BUILD_COMPILE_FAIL_TESTS) + add_subdirectory(compile_fail) +endif() add_executable(ring_buffer_test ring_buffer_test.cpp) From 27c0de7fa297a70e82e0cd8a9f75e8e48f8b3f64 Mon Sep 17 00:00:00 2001 From: Shovy <1826784860@qq.com> Date: Tue, 28 Jul 2026 20:10:13 +0800 Subject: [PATCH 2/3] test: add SupportsTriviallyCopyableTypes, SupportsAudioFrame tests and compile fail directory --- tests/compile_fail/CMakeLists.txt | 12 ++++++++++++ tests/compile_fail/string_type.cpp | 7 +++++++ tests/compile_fail/vector_type.cpp | 7 +++++++ tests/ring_buffer_test.cpp | 26 ++++++++++++++++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 tests/compile_fail/CMakeLists.txt create mode 100644 tests/compile_fail/string_type.cpp create mode 100644 tests/compile_fail/vector_type.cpp diff --git a/tests/compile_fail/CMakeLists.txt b/tests/compile_fail/CMakeLists.txt new file mode 100644 index 0000000..c3dd340 --- /dev/null +++ b/tests/compile_fail/CMakeLists.txt @@ -0,0 +1,12 @@ +add_executable(strTest string_type.cpp) +add_executable(vecTest vector_type.cpp) + +target_link_libraries(strTest + PRIVATE + spsc_ring_buffer +) + +target_link_libraries(vecTest + PRIVATE + spsc_ring_buffer +) \ No newline at end of file diff --git a/tests/compile_fail/string_type.cpp b/tests/compile_fail/string_type.cpp new file mode 100644 index 0000000..0cca230 --- /dev/null +++ b/tests/compile_fail/string_type.cpp @@ -0,0 +1,7 @@ +#include +#include + +int main() +{ + shovy::RingBuffer buffer(64); +} \ No newline at end of file diff --git a/tests/compile_fail/vector_type.cpp b/tests/compile_fail/vector_type.cpp new file mode 100644 index 0000000..4612bb2 --- /dev/null +++ b/tests/compile_fail/vector_type.cpp @@ -0,0 +1,7 @@ +#include +#include + +int main() +{ + shovy::RingBuffer> buffer(64); +} \ No newline at end of file diff --git a/tests/ring_buffer_test.cpp b/tests/ring_buffer_test.cpp index acb9b27..b04957c 100644 --- a/tests/ring_buffer_test.cpp +++ b/tests/ring_buffer_test.cpp @@ -149,3 +149,29 @@ TEST(RingBufferTest, BatchPopPartialWhenEmpty){ EXPECT_EQ(buffer.pop_batch(output, 8), 4); EXPECT_TRUE(buffer.empty()); } + +TEST(RingBufferTest, SupportsTriviallyCopyableTypes){ + shovy::RingBuffer intBuffer(64); + shovy::RingBuffer floatBuffer(64); + shovy::RingBuffer sizeBuffer(64); + + EXPECT_EQ(intBuffer.capacity(), 64); + EXPECT_EQ(floatBuffer.capacity(), 64); + EXPECT_EQ(sizeBuffer.capacity(), 64); +} + +TEST(RingBufferTest, SupportsAudioFrame) +{ + struct AudioFrame { + float left; + float right; + }; + + shovy::RingBuffer buffer(64); + + EXPECT_EQ(buffer.capacity(), 64); + + static_assert(std::is_trivially_copyable_v); + static_assert(!std::is_trivially_copyable_v); + static_assert(!std::is_trivially_copyable_v>); +} \ No newline at end of file From 97b1a1f12de7a0062ebec6ce0441baba9a398f98 Mon Sep 17 00:00:00 2001 From: Shovy <1826784860@qq.com> Date: Tue, 28 Jul 2026 20:11:34 +0800 Subject: [PATCH 3/3] safety: add static_assert to ensure always lock-free and trivial copyable, update CacheLineSize --- include/spsc/ring_buffer.hpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/include/spsc/ring_buffer.hpp b/include/spsc/ring_buffer.hpp index f2aadeb..a2e8d39 100644 --- a/include/spsc/ring_buffer.hpp +++ b/include/spsc/ring_buffer.hpp @@ -5,11 +5,22 @@ #include #include #include +#include namespace shovy{ template class RingBuffer{ + static_assert(std::is_trivially_copyable_v, "RingBuffer only supports trivially copyable types"); + + static_assert(std::atomic::is_always_lock_free, "RingBuffer requires lock-free atomic operations"); + +#if defined(__cpp_lib_hardware_interference_size) + static constexpr size_t CacheLineSize = std::hardware_destructive_interference_size; +#else + static constexpr size_t CacheLineSize = 64; // Fallback default for x86_64/ARM +#endif + public: explicit RingBuffer(size_t capacity) : capacity_(capacity) { if (capacity_ == 0 || (capacity_ & (capacity_ - 1)) != 0) { @@ -99,8 +110,8 @@ class RingBuffer{ private: T* buffer_; size_t capacity_; - alignas(std::hardware_destructive_interference_size) std::atomic write_idx{0}; - alignas(std::hardware_destructive_interference_size) std::atomic read_idx{0}; + alignas(CacheLineSize) std::atomic write_idx{0}; + alignas(CacheLineSize) std::atomic read_idx{0}; }; } // namespace shovy