Skip to content

Commit e8d2214

Browse files
feat: ponyfill std::atomic_ref on OSX with Boost
1 parent 9f9a393 commit e8d2214

8 files changed

Lines changed: 91 additions & 26 deletions

File tree

CMakeLists.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ include(VcpkgDefaults)
2020
if (BUILD_TESTING OR NOT DEFINED BUILD_TESTING)
2121
list(APPEND VCPKG_MANIFEST_FEATURES "tests")
2222
endif()
23+
if (DPLX_DLOG_USE_BOOST_ATOMIC_REF)
24+
list(APPEND VCPKG_MANIFEST_FEATURES "boost-atomic-ref")
25+
endif()
2326

2427
########################################################################
2528
project(deeplog
@@ -28,6 +31,7 @@ project(deeplog
2831
)
2932

3033
include(EnforceOutOfSourceBuilds)
34+
include(CheckStdAtomicRefSupport)
3135
include(CMakeDependentOption)
3236
include(CMakePackageConfigHelpers)
3337
include(FeatureSummary)
@@ -40,6 +44,7 @@ if (BUILD_TESTING)
4044
enable_testing()
4145
endif()
4246

47+
check_std_atomic_ref_support(DPLX_DLOG_HAS_STD_ATOMIC_REF)
4348

4449
########################################################################
4550
# options
@@ -48,6 +53,7 @@ option(DPLX_DLOG_DISABLE_WORKAROUNDS "Disable all workarounds" OFF)
4853
option(DPLX_DLOG_FLAG_OUTDATED_WORKAROUNDS "Emit compiler errors for workarounds which are active, but haven't been validated for this version" OFF)
4954

5055
option(DPLX_DLOG_DISABLE_IMPLICIT_CONTEXT "Disable implicit context support via TLS" OFF)
56+
cmake_dependent_option(DPLX_DLOG_USE_BOOST_ATOMIC_REF "Use boost::atomic_ref instead of std::atomic_ref" OFF "DPLX_DLOG_HAS_STD_ATOMIC_REF" ON)
5157

5258
option(BUILD_EXAMPLES "Build the example executables" OFF)
5359

@@ -59,6 +65,10 @@ set_property(CACHE DLOG_LLFIO_TARGET PROPERTY STRINGS "hl;sl;dl")
5965
# dependencies
6066

6167
set(Boost_NO_WARN_NEW_VERSIONS ON)
68+
set(DLOG_REQUIRED_BOOST_COMPONENTS config mp11 unordered variant2)
69+
if (DPLX_DLOG_USE_BOOST_ATOMIC_REF)
70+
list(APPEND DLOG_REQUIRED_BOOST_COMPONENTS atomic)
71+
endif()
6272

6373
find_package(fmt 10 CONFIG REQUIRED)
6474

@@ -71,7 +81,7 @@ find_package(llfio CONFIG REQUIRED)
7181
find_package(concrete 0.0 CONFIG REQUIRED)
7282
find_package(deeppack 0.1 CONFIG REQUIRED)
7383

74-
find_package(Boost 1.82 REQUIRED)
84+
find_package(Boost 1.82 REQUIRED COMPONENTS ${DLOG_REQUIRED_BOOST_COMPONENTS})
7585

7686
find_package(Catch2 CONFIG)
7787
set_package_properties(Catch2 PROPERTIES

libs/deeplog/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ target_include_directories(deeplog PUBLIC
3434
target_link_libraries(deeplog PUBLIC
3535
Deeplex::deeppack
3636

37+
Boost::boost
38+
$<$<BOOL:${DPLX_DLOG_USE_BOOST_ATOMIC_REF}>:Boost::atomic>
3739
fmt::fmt
3840
llfio::${DLOG_LLFIO_TARGET}
3941
outcome::hl

libs/deeplog/src/dplx/dlog/bus/mpsc_bus.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,8 @@ auto dplx::dlog::mpsc_bus_handle::create_span_context(trace_id trace,
295295
^ traceBlob.values[3],
296296
mNumRegions);
297297
auto const ctr
298-
= std::atomic_ref<std::uint64_t>(region(regionId)->span_prng_ctr)
299-
.fetch_add(1U, std::memory_order_relaxed);
298+
= detail::atomic_ref<std::uint64_t>(region(regionId)->span_prng_ctr)
299+
.fetch_add(1U, detail::memory_order::relaxed);
300300
auto const rawTraceId
301301
= std::bit_cast<cncr::blob<std::uint64_t, 2, alignof(trace_id)>>(
302302
trace);

libs/deeplog/src/dplx/dlog/bus/mpsc_bus.hpp

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
#include <dplx/dp/macros.hpp>
2121
#include <dplx/dp/streams/memory_output_stream.hpp>
2222
#include <dplx/make.hpp>
23+
#include <dplx/predef/os.h>
2324
#include <dplx/scope_guard.hpp>
2425

2526
#include <dplx/dlog/concepts.hpp>
27+
#include <dplx/dlog/config.hpp>
2628
#include <dplx/dlog/core/file_database.hpp>
2729
#include <dplx/dlog/core/log_clock.hpp>
2830
#include <dplx/dlog/core/strong_types.hpp>
@@ -31,9 +33,23 @@
3133
#include <dplx/dlog/log_fabric.hpp>
3234
#include <dplx/dlog/source/record_output_buffer.hpp>
3335

36+
#if DPLX_DLOG_USE_BOOST_ATOMIC_REF
37+
#include <boost/atomic/atomic_ref.hpp>
38+
#endif
39+
3440
namespace dplx::dlog::detail
3541
{
3642

43+
#if DPLX_DLOG_USE_BOOST_ATOMIC_REF
44+
template <typename T>
45+
using atomic_ref = boost::atomic_ref<T>;
46+
using memory_order = boost::memory_order;
47+
#else
48+
template <typename T>
49+
using atomic_ref = std::atomic_ref<T>;
50+
using memory_order = std::memory_order;
51+
#endif
52+
3753
auto hashed_this_thread_id() noexcept -> std::uint32_t;
3854

3955
constexpr auto hash_to_index(std::uint32_t h, std::uint32_t buckets) noexcept
@@ -64,11 +80,11 @@ using mpsc_bus_info = mpsc_bus_info_v00;
6480

6581
struct mpsc_bus_region_ctrl
6682
{
67-
alignas(std::atomic_ref<std::uint32_t>::required_alignment)
83+
alignas(detail::atomic_ref<std::uint32_t>::required_alignment)
6884
std::uint32_t read_ptr;
69-
alignas(std::atomic_ref<std::uint32_t>::required_alignment)
85+
alignas(detail::atomic_ref<std::uint32_t>::required_alignment)
7086
std::uint32_t alloc_ptr;
71-
alignas(std::atomic_ref<std::uint64_t>::required_alignment) std::uint64_t
87+
alignas(detail::atomic_ref<std::uint64_t>::required_alignment) std::uint64_t
7288
span_prng_ctr;
7389

7490
std::uint8_t padding[48]; // NOLINT(cppcoreguidelines-avoid-magic-numbers)
@@ -174,7 +190,7 @@ class mpsc_bus_handle
174190
= static_cast<std::uint32_t>(sizeof(region_ctrl));
175191

176192
static constexpr std::uint32_t write_alignment
177-
= std::atomic_ref<std::uint32_t>::required_alignment;
193+
= detail::atomic_ref<std::uint32_t>::required_alignment;
178194
static constexpr std::uint32_t block_size = write_alignment;
179195
static constexpr std::uint32_t message_header_size = block_size;
180196

@@ -209,8 +225,8 @@ class mpsc_bus_handle
209225
return errc::bad;
210226
}
211227

212-
std::atomic_ref<std::uint32_t>(*mMsgCtrl).fetch_and(
213-
max_message_size, std::memory_order::release);
228+
detail::atomic_ref<std::uint32_t>(*mMsgCtrl).fetch_and(
229+
max_message_size, detail::memory_order::release);
214230
// reset();
215231
mMsgCtrl = nullptr;
216232
return outcome::success();
@@ -238,11 +254,12 @@ class mpsc_bus_handle
238254
auto *const blockData = region_data(regionId);
239255
writable_bytes block(blockData, mRegionSize - region_ctrl_overhead);
240256

241-
std::atomic_ref<std::uint32_t> const readPtr(ctx->read_ptr);
242-
std::atomic_ref<std::uint32_t> const allocPtr(ctx->alloc_ptr);
257+
detail::atomic_ref<std::uint32_t> const readPtr(ctx->read_ptr);
258+
detail::atomic_ref<std::uint32_t> const allocPtr(ctx->alloc_ptr);
243259

244-
auto const originalReadPos = readPtr.load(std::memory_order::relaxed);
245-
auto const allocPos = allocPtr.load(std::memory_order::relaxed);
260+
auto const originalReadPos
261+
= readPtr.load(detail::memory_order::relaxed);
262+
auto const allocPos = allocPtr.load(detail::memory_order::relaxed);
246263
if (allocPos == originalReadPos)
247264
{
248265
// nothing to see here
@@ -253,7 +270,7 @@ class mpsc_bus_handle
253270
scope_guard readUpdateGuard = [&readPos, &originalReadPos, &readPtr] {
254271
if (readPos != originalReadPos)
255272
{
256-
readPtr.store(readPos, std::memory_order::release);
273+
readPtr.store(readPos, detail::memory_order::release);
257274
}
258275
};
259276

@@ -276,8 +293,8 @@ class mpsc_bus_handle
276293
blockData + readPos);
277294

278295
auto const msgHead
279-
= std::atomic_ref<std::uint32_t>{*msgHeadPtr}.load(
280-
std::memory_order::acquire);
296+
= detail::atomic_ref<std::uint32_t>{*msgHeadPtr}.load(
297+
detail::memory_order::acquire);
281298
if ((msgHead & message_lock_flag) != 0U)
282299
{
283300
break;
@@ -312,9 +329,9 @@ class mpsc_bus_handle
312329

313330
for (std::size_t i = 0U; i < batchSize; ++i)
314331
{
315-
std::atomic_ref<std::uint32_t>{*infos[i].head}.fetch_or(
332+
detail::atomic_ref<std::uint32_t>{*infos[i].head}.fetch_or(
316333
message_lock_flag | message_consumed_flag,
317-
std::memory_order::relaxed);
334+
detail::memory_order::relaxed);
318335
std::memset(infos[i].content.data(),
319336
static_cast<int>(unused_block_content),
320337
infos[i].content.size());
@@ -379,12 +396,13 @@ class mpsc_bus_handle
379396
auto const regionEnd = mRegionSize - region_ctrl_overhead;
380397
auto const allocSize = cncr::round_up_p2(payloadSize, block_size);
381398

382-
std::atomic_ref<std::uint32_t> const sharedReadHand(ctx->read_ptr);
383-
std::atomic_ref<std::uint32_t> const sharedAllocHand(ctx->alloc_ptr);
399+
detail::atomic_ref<std::uint32_t> const sharedReadHand(ctx->read_ptr);
400+
detail::atomic_ref<std::uint32_t> const sharedAllocHand(ctx->alloc_ptr);
384401

385-
auto const readHand = sharedReadHand.load(std::memory_order::acquire);
402+
auto const readHand
403+
= sharedReadHand.load(detail::memory_order::acquire);
386404
std::uint32_t allocHand
387-
= sharedAllocHand.load(std::memory_order::relaxed);
405+
= sharedAllocHand.load(detail::memory_order::relaxed);
388406
// NOLINTNEXTLINE(cppcoreguidelines-init-variables)
389407
std::uint32_t payloadPosition;
390408
for (;;)
@@ -412,7 +430,7 @@ class mpsc_bus_handle
412430
}
413431

414432
if (sharedAllocHand.compare_exchange_weak(
415-
allocHand, payloadEnd, std::memory_order::relaxed))
433+
allocHand, payloadEnd, detail::memory_order::relaxed))
416434
[[likely]]
417435
{
418436
break;
@@ -424,8 +442,8 @@ class mpsc_bus_handle
424442
auto *ctrl = reinterpret_cast<std::uint32_t *>(regionData + allocHand);
425443
auto *data = regionData + payloadPosition;
426444
// NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
427-
std::atomic_ref<std::uint32_t>(*ctrl).store(
428-
payloadSize | message_lock_flag, std::memory_order::relaxed);
445+
detail::atomic_ref<std::uint32_t>(*ctrl).store(
446+
payloadSize | message_lock_flag, detail::memory_order::relaxed);
429447
out.reset(data, allocSize);
430448
out.mMsgCtrl = ctrl;
431449
return errc::success;

libs/deeplog/src/dplx/dlog/config.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,12 @@
1818
#if !defined(DPLX_DLOG_FLAG_OUTDATED_WORKAROUNDS)
1919
#define DPLX_DLOG_FLAG_OUTDATED_WORKAROUNDS 0
2020
#endif
21+
22+
#if !defined(DPLX_DLOG_USE_BOOST_ATOMIC_REF)
23+
#include <version>
24+
#if __cpp_lib_atomic_ref >= 201'806L
25+
#define DPLX_DLOG_USE_BOOST_ATOMIC_REF 0
26+
#else
27+
#define DPLX_DLOG_USE_BOOST_ATOMIC_REF 1
28+
#endif
29+
#endif
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
include_guard(DIRECTORY)
2+
include(CheckCXXSourceCompiles)
3+
4+
function(check_std_atomic_ref_support OUT_VAR)
5+
set(CMAKE_CXX_STANDARD 20)
6+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
7+
8+
check_cxx_source_compiles([=[
9+
#include <version>
10+
static_assert(__cpp_lib_atomic_ref >= 201806L);
11+
int main() {}
12+
]=] "${OUT_VAR}")
13+
set("${OUT_VAR}" "${${OUT_VAR}}" PARENT_SCOPE)
14+
endfunction()

tools/config.hpp.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#cmakedefine01 DPLX_DLOG_DISABLE_IMPLICIT_CONTEXT
1818
#cmakedefine01 DPLX_DLOG_USE_SOURCE_LOCATION
19+
#cmakedefine01 DPLX_DLOG_USE_BOOST_ATOMIC_REF
1920

2021
// NOLINTEND(cppcoreguidelines-macro-to-enum)
2122
// NOLINTEND(cppcoreguidelines-macro-usage)

vcpkg.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,18 @@
44
"version-semver": "0.0.0-beta.6",
55
"homepage": "https://github.com/deeplex/deeplog",
66
"dependencies": [
7+
{
8+
"name": "boost-atomic",
9+
"platform": "osx"
10+
},
711
"boost-config",
812
"boost-mp11",
913
"boost-unordered",
1014
"boost-variant2",
11-
"boost-winapi",
15+
{
16+
"name": "boost-winapi",
17+
"platform": "windows"
18+
},
1219
"concrete",
1320
"deeppack",
1421
"fmt",
@@ -20,6 +27,10 @@
2027
"outcome"
2128
],
2229
"features": {
30+
"boost-atomic-ref": {
31+
"description": "Use boost::atomic_ref instead of std::atomic_ref",
32+
"dependencies": [ "boost-atomic" ]
33+
},
2334
"tests": {
2435
"description": "Build the test suite",
2536
"dependencies": [ "catch2" ]

0 commit comments

Comments
 (0)