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")]]
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
307#if LASS_TAGGED_PTR_64_PACKED
310 typedef num::Tuint16 TTag;
311 TaggedPtr() =
default;
312 TaggedPtr(T * ptr, TTag tag): bits_((
reinterpret_cast<num::Tint64
>(ptr) << 16) | (tag & 0xffff)) {}
315# if defined(LASS_HAVE_INLINE_ASSEMBLY_GCC) && defined(LASS_PROCESSOR_ARCHITECTURE_x86)
317 __asm__ (
"sarq $16, %0;" :
"=q"(ptr) :
"0"(bits_) :
"cc");
319# elif LASS_COMPILER_TYPE == LASS_COMPILER_TYPE_MSVC
320 return reinterpret_cast<T*
>(__ll_rshift(bits_, 16));
322 return ((bits_ & 0xa000000000000000) == 0) ?
323 reinterpret_cast<T*
>(bits_ >> 16) :
324 reinterpret_cast<T*
>((bits_ >> 16) | 0xffff000000000000);
327 TTag tag()
const {
return static_cast<TTag
>(bits_ & 0xffff); }
328 TTag nextTag()
const {
return static_cast<TTag
>(
static_cast<size_t>(tag() + 1) & 0xffff); }
329 bool operator==(
const TaggedPtr& other)
const {
return bits_ == other.bits_; }
331 num::Tint64 bits_ = 0;
336 typedef num::TuintPtr TTag;
337 TaggedPtr() =
default;
338 TaggedPtr(T* ptr, TTag tag) : ptr_(ptr), tag_(tag) {}
339 T* get()
const {
return ptr_; }
340 TTag tag()
const {
return tag_; }
341 TTag nextTag()
const {
return tag_ + 1; }
342 bool operator==(
const TaggedPtr& other)
const {
return ptr_ == other.ptr_ && tag_ == other.tag_; }
350 T* operator->()
const { LASS_ASSERT(get());
return get(); }
351 bool operator!()
const {
return get() ==
nullptr; }
352 explicit operator bool()
const {
return get() !=
nullptr; }
353 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.