Skip to content

Commit 6005ada

Browse files
author
Maxim Egorushkin
committed
Static linkage for functions in details namespace to prevent compilers from emitting unnecessary external definitions.
1 parent 64ab128 commit 6005ada

File tree

2 files changed

+29
-18
lines changed

2 files changed

+29
-18
lines changed

include/atomic_queue/atomic_queue.h

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,19 @@ struct GetIndexShuffleBits<false, array_size, elements_per_cache_line> {
5656
// the element within the cache line) with the next N bits (which are the index of the cache line)
5757
// of the element index.
5858
template<int BITS>
59-
constexpr unsigned remap_index(unsigned index) noexcept {
59+
ATOMIC_QUEUE_INLINE static constexpr unsigned remap_index(unsigned index) noexcept {
6060
unsigned constexpr mix_mask{(1u << BITS) - 1};
6161
unsigned const mix{(index ^ (index >> BITS)) & mix_mask};
6262
return index ^ mix ^ (mix << BITS);
6363
}
6464

6565
template<>
66-
constexpr unsigned remap_index<0>(unsigned index) noexcept {
66+
ATOMIC_QUEUE_INLINE constexpr unsigned remap_index<0>(unsigned index) noexcept {
6767
return index;
6868
}
6969

7070
template<int BITS, class T>
71-
constexpr T& map(T* elements, unsigned index) noexcept {
71+
ATOMIC_QUEUE_INLINE static constexpr T& map(T* elements, unsigned index) noexcept {
7272
return elements[remap_index<BITS>(index)];
7373
}
7474

@@ -87,30 +87,30 @@ constexpr T& map(T* elements, unsigned index) noexcept {
8787
// ++a;
8888

8989
template<class T>
90-
constexpr T decrement(T x) noexcept {
90+
ATOMIC_QUEUE_INLINE static constexpr T decrement(T x) noexcept {
9191
return x - 1;
9292
}
9393

9494
template<class T>
95-
constexpr T increment(T x) noexcept {
95+
ATOMIC_QUEUE_INLINE static constexpr T increment(T x) noexcept {
9696
return x + 1;
9797
}
9898

9999
template<class T>
100-
constexpr T or_equal(T x, unsigned u) noexcept {
100+
ATOMIC_QUEUE_INLINE static constexpr T or_equal(T x, unsigned u) noexcept {
101101
return x | x >> u;
102102
}
103103

104104
template<class T, class... Args>
105-
constexpr T or_equal(T x, unsigned u, Args... rest) noexcept {
105+
ATOMIC_QUEUE_INLINE static constexpr T or_equal(T x, unsigned u, Args... rest) noexcept {
106106
return or_equal(or_equal(x, u), rest...);
107107
}
108108

109-
constexpr uint32_t round_up_to_power_of_2(uint32_t a) noexcept {
109+
ATOMIC_QUEUE_INLINE static constexpr uint32_t round_up_to_power_of_2(uint32_t a) noexcept {
110110
return increment(or_equal(decrement(a), 1, 2, 4, 8, 16));
111111
}
112112

113-
constexpr uint64_t round_up_to_power_of_2(uint64_t a) noexcept {
113+
ATOMIC_QUEUE_INLINE static constexpr uint64_t round_up_to_power_of_2(uint64_t a) noexcept {
114114
return increment(or_equal(decrement(a), 1, 2, 4, 8, 16, 32));
115115
}
116116

@@ -125,11 +125,23 @@ constexpr T nil() noexcept {
125125
}
126126

127127
template<class T>
128-
inline void destroy_n(T* p, unsigned n) noexcept {
128+
ATOMIC_QUEUE_INLINE static void destroy_n(T* p, unsigned n) noexcept {
129129
for(auto q = p + n; p != q;)
130130
(p++)->~T();
131131
}
132132

133+
template<class T>
134+
ATOMIC_QUEUE_INLINE static void swap_relaxed(std::atomic<T>& a, std::atomic<T>& b) noexcept {
135+
auto a2 = a.load(X);
136+
a.store(b.load(X), X);
137+
b.store(a2, X);
138+
}
139+
140+
template<class T>
141+
ATOMIC_QUEUE_INLINE static void copy_relaxed(std::atomic<T>& a, std::atomic<T> const& b) noexcept {
142+
a.store(b.load(X), X);
143+
}
144+
133145
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
134146

135147
} // namespace details
@@ -152,18 +164,15 @@ class AtomicQueueCommon {
152164
, tail_(b.tail_.load(X)) {}
153165

154166
AtomicQueueCommon& operator=(AtomicQueueCommon const& b) noexcept {
155-
head_.store(b.head_.load(X), X);
156-
tail_.store(b.tail_.load(X), X);
167+
details::copy_relaxed(head_, b.head_);
168+
details::copy_relaxed(tail_, b.tail_);
157169
return *this;
158170
}
159171

172+
// Relatively semi-special swap is not thread-safe either.
160173
void swap(AtomicQueueCommon& b) noexcept {
161-
unsigned h = head_.load(X);
162-
unsigned t = tail_.load(X);
163-
head_.store(b.head_.load(X), X);
164-
tail_.store(b.tail_.load(X), X);
165-
b.head_.store(h, X);
166-
b.tail_.store(t, X);
174+
details::swap_relaxed(head_, b.head_);
175+
details::swap_relaxed(tail_, b.tail_);
167176
}
168177

169178
template<class T, T NIL>

include/atomic_queue/defs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,12 @@ namespace atomic_queue {
8484
#define ATOMIC_QUEUE_LIKELY(expr) __builtin_expect(static_cast<bool>(expr), 1)
8585
#define ATOMIC_QUEUE_UNLIKELY(expr) __builtin_expect(static_cast<bool>(expr), 0)
8686
#define ATOMIC_QUEUE_NOINLINE __attribute__((noinline))
87+
#define ATOMIC_QUEUE_INLINE inline __attribute__((always_inline))
8788
#else
8889
#define ATOMIC_QUEUE_LIKELY(expr) (expr)
8990
#define ATOMIC_QUEUE_UNLIKELY(expr) (expr)
9091
#define ATOMIC_QUEUE_NOINLINE
92+
#define ATOMIC_QUEUE_INLINE inline
9193
#endif
9294

9395
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)