43#ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_ATOMIC_H
44#define LASS_GUARDIAN_OF_INCLUSION_UTIL_ATOMIC_H
47#if !defined(LASS_PROCESSOR_ARCHITECTURE_ARM64)
53#ifdef LASS_PROCESSOR_ARCHITECTURE_x86
54# if LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
56# define LASS_SPIN_PAUSE _mm_pause()
58# define LASS_SPIN_PAUSE __builtin_ia32_pause()
61# define LASS_SPIN_PAUSE
64#ifdef __cpp_lib_hardware_interference_size
65#define LASS_LOCK_FREE_ALIGNMENT std::hardware_destructive_interference_size
67#define LASS_LOCK_FREE_ALIGNMENT 64
79#if !defined(LASS_PROCESSOR_ARCHITECTURE_ARM64)
93[[deprecated(
"Use std::atomic")]]
96 return impl::AtomicOperations<
sizeof(T) >::compareAndSwap(dest, expectedValue, newValue);
115template <
typename T1,
typename T2>
116[[deprecated(
"Use std::atomic")]]
119 static_assert(
sizeof(T1) ==
sizeof(T2),
"T1 and T2 must be of same size");
120 return impl::AtomicOperations<
sizeof(T1) >::compareAndSwap(
121 dest1, expected1, expected2, new1, new2);
136[[deprecated(
"Use std::atomic")]]
139 impl::AtomicOperations<
sizeof(T) >::increment(value);
154[[deprecated(
"Use std::atomic")]]
157 impl::AtomicOperations<
sizeof(T) >::decrement(value);
167[[deprecated(
"Use std::atomic")]]
185[[deprecated(
"Use std::atomic")]]
208[[deprecated(
"Use std::atomic")]]
226 T current = semaphore.load(std::memory_order_acquire);
232 current = semaphore.load(std::memory_order_relaxed);
234 LASS_ASSERT(current >= 0);
236 while (!semaphore.compare_exchange_weak(current, current - 1,
237 std::memory_order_release, std::memory_order_relaxed));
251 T current = semaphore.load(std::memory_order_acquire);
254 LASS_ASSERT(current >= 0);
260 while (!semaphore.compare_exchange_weak(current, current - 1,
261 std::memory_order_release, std::memory_order_relaxed));
272 semaphore.fetch_add(1, std::memory_order_acq_rel);
276#if LASS_ADDRESS_SIZE == 64
277# if LASS_HAVE_STD_ATOMIC_DWCAS_LOCK_FREE
281# define LASS_TAGGED_PTR_ALIGN alignas(16)
282# elif LASS_ACTUAL_ADDRESS_SIZE == 48
290# define LASS_TAGGED_PTR_64_PACKED 1
291# define LASS_TAGGED_PTR_ALIGN alignas(8)
293# error not implemented yet
296# define LASS_TAGGED_PTR_ALIGN alignas(8)
305class LASS_TAGGED_PTR_ALIGN TaggedPtr
311#if LASS_TAGGED_PTR_64_PACKED
313 typedef num::Tuint16 TTag;
314 TaggedPtr() =
default;
315 TaggedPtr(T * ptr, TTag tag): bits_((
reinterpret_cast<num::Tint64
>(ptr) << 16) | (tag & 0xffff)) {}
318# if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC) && defined(LASS_PROCESSOR_ARCHITECTURE_x86)
320 __asm__ (
"sarq $16, %0;" :
"=q"(ptr) :
"0"(bits_) :
"cc");
322# elif LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
323 return reinterpret_cast<TPointer
>(__ll_rshift(bits_, 16));
325 return ((bits_ & 0xa000000000000000) == 0) ?
326 reinterpret_cast<TPointer
>(bits_ >> 16) :
327 reinterpret_cast<TPointer
>((bits_ >> 16) | 0xffff000000000000);
330 TTag tag()
const {
return static_cast<TTag
>(bits_ & 0xffff); }
331 TTag nextTag()
const {
return static_cast<TTag
>(
static_cast<size_t>(tag() + 1) & 0xffff); }
332 bool operator==(
const TaggedPtr& other)
const {
return bits_ == other.bits_; }
334 num::Tint64 bits_ = 0;
338 typedef num::TuintPtr TTag;
339 TaggedPtr() =
default;
340 TaggedPtr(TPointer ptr, TTag tag) : ptr_(ptr), tag_(tag) {}
341 TPointer get()
const {
return ptr_; }
342 TTag tag()
const {
return tag_; }
343 TTag nextTag()
const {
return tag_ + 1; }
344 bool operator==(
const TaggedPtr& other)
const {
return ptr_ == other.ptr_ && tag_ == other.tag_; }
346 TPointer ptr_ =
nullptr;
352 TPointer operator->()
const { LASS_ASSERT(get());
return get(); }
353 bool operator!()
const {
return get() ==
nullptr; }
354 explicit operator bool()
const {
return get() !=
nullptr; }
355 bool operator!=(
const TaggedPtr& other)
const {
return !(*
this == other); }
void atomicLock(volatile T &semaphore)
bool atomicCompareAndSwap(volatile T &dest, T expectedValue, T newValue)
Performs the following pseudocode in an atomic way (no other threads can intervene):
void atomicIncrement(volatile T &value)
Performs the following pseudocode in an atomic way (no other threads can intervene):
bool atomicTryLock(volatile T &semaphore)
void atomicUnlock(volatile T &semaphore)
void atomicDecrement(volatile T &value)
Performs the following pseudocode in an atomic way (no other threads can intervene):
general utility, debug facilities, ...
Library for Assembled Shared Sources.