Skip to content

Commit d1460ea

Browse files
author
Maxim Egorushkin
committed
Explicitly de-alias pointers to dynamically allocated queue buffers.
1 parent 25bc9b7 commit d1460ea

File tree

2 files changed

+38
-18
lines changed

2 files changed

+38
-18
lines changed

include/atomic_queue/atomic_queue.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ constexpr T nil() noexcept {
125125
}
126126

127127
template<class T>
128-
ATOMIC_QUEUE_INLINE static void destroy_n(T* p, unsigned n) noexcept {
128+
ATOMIC_QUEUE_INLINE static void destroy_n(T* ATOMIC_QUEUE_RESTRICT p, unsigned n) noexcept {
129129
for(auto q = p + n; p != q;)
130130
(p++)->~T();
131131
}
@@ -452,8 +452,14 @@ class AtomicQueueB : private std::allocator_traits<A>::template rebind_alloc<std
452452

453453
// AtomicQueueCommon members are stored into by readers and writers.
454454
// Allocate these immutable members on another cache line which never gets invalidated by stores.
455-
alignas(CACHE_LINE_SIZE) unsigned size_;
456-
std::atomic<T>* elements_;
455+
alignas(CACHE_LINE_SIZE)
456+
unsigned size_;
457+
458+
// The C++ strict aliasing rules assume that pointers to the same decayed type may alias.
459+
// The C++ strict aliasing rules assume that pointers to any char type may alias anything and everything.
460+
// A dynamically allocated array may not alias anything else by construction.
461+
// Explicitly annotate the circular buffer array pointer as not aliasing anything else with restrict keyword.
462+
std::atomic<T>* ATOMIC_QUEUE_RESTRICT elements_;
457463

458464
ATOMIC_QUEUE_INLINE T do_pop(unsigned tail) noexcept {
459465
std::atomic<T>& q_element = details::map<SHUFFLE_BITS>(elements_, tail & (size_ - 1));
@@ -533,9 +539,15 @@ class AtomicQueueB2 : private std::allocator_traits<A>::template rebind_alloc<un
533539

534540
// AtomicQueueCommon members are stored into by readers and writers.
535541
// Allocate these immutable members on another cache line which never gets invalidated by stores.
536-
alignas(CACHE_LINE_SIZE) unsigned size_;
537-
AtomicState* states_;
538-
T* elements_;
542+
alignas(CACHE_LINE_SIZE)
543+
unsigned size_;
544+
545+
// The C++ strict aliasing rules assume that pointers to the same decayed type may alias.
546+
// The C++ strict aliasing rules assume that pointers to any char type may alias anything and everything.
547+
// A dynamically allocated array may not alias anything else by construction.
548+
// Explicitly annotate the circular buffer array pointers as not aliasing anything else with restrict keyword.
549+
AtomicState* ATOMIC_QUEUE_RESTRICT states_;
550+
T* ATOMIC_QUEUE_RESTRICT elements_;
539551

540552
static constexpr auto STATES_PER_CACHE_LINE = CACHE_LINE_SIZE / sizeof(AtomicState);
541553
static_assert(STATES_PER_CACHE_LINE, "Unexpected STATES_PER_CACHE_LINE.");

include/atomic_queue/defs.h

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,6 @@ static inline void spin_loop_pause() noexcept {}
8080

8181
namespace atomic_queue {
8282

83-
#if defined(__GNUC__) || defined(__clang__)
84-
#define ATOMIC_QUEUE_LIKELY(expr) __builtin_expect(static_cast<bool>(expr), 1)
85-
#define ATOMIC_QUEUE_UNLIKELY(expr) __builtin_expect(static_cast<bool>(expr), 0)
86-
#define ATOMIC_QUEUE_NOINLINE __attribute__((noinline))
87-
#define ATOMIC_QUEUE_INLINE inline __attribute__((always_inline))
88-
#else
89-
#define ATOMIC_QUEUE_LIKELY(expr) (expr)
90-
#define ATOMIC_QUEUE_UNLIKELY(expr) (expr)
91-
#define ATOMIC_QUEUE_NOINLINE
92-
#define ATOMIC_QUEUE_INLINE inline
93-
#endif
94-
9583
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9684

9785
auto constexpr A = std::memory_order_acquire;
@@ -106,4 +94,24 @@ auto constexpr AR = std::memory_order_acq_rel;
10694

10795
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10896

97+
#if defined(__GNUC__) || defined(__clang__)
98+
#define ATOMIC_QUEUE_LIKELY(expr) __builtin_expect(static_cast<bool>(expr), 1)
99+
#define ATOMIC_QUEUE_UNLIKELY(expr) __builtin_expect(static_cast<bool>(expr), 0)
100+
#define ATOMIC_QUEUE_NOINLINE __attribute__((noinline))
101+
#define ATOMIC_QUEUE_INLINE inline __attribute__((always_inline))
102+
#define ATOMIC_QUEUE_RESTRICT __restrict__
103+
#else
104+
#define ATOMIC_QUEUE_LIKELY(expr) (expr)
105+
#define ATOMIC_QUEUE_UNLIKELY(expr) (expr)
106+
#define ATOMIC_QUEUE_NOINLINE
107+
#define ATOMIC_QUEUE_INLINE inline
108+
#ifdef _MSC_VER
109+
#define ATOMIC_QUEUE_RESTRICT __restrict
110+
#else
111+
#define ATOMIC_QUEUE_RESTRICT
112+
#endif
113+
#endif
114+
115+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
116+
109117
#endif // ATOMIC_QUEUE_DEFS_H_INCLUDED

0 commit comments

Comments
 (0)