mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-22 09:21:57 -05:00
AK: Make parts of Atomic constexpr
These new constexpr functions are for the most part identical to the same non-constexpr functions, except they drop the `volatile` qualifier on `this`. `fetch_add()`, `fetch_sub()`, `load()` have explicit `is_constant_evaluated()` branches that don't call (non-constexpr) atomic built-ins. Off the constexpr path, they forward to the volatile functions.
This commit is contained in:
parent
e3826bf791
commit
761320c4d2
1 changed files with 52 additions and 0 deletions
52
AK/Atomic.h
52
AK/Atomic.h
|
@ -247,11 +247,21 @@ public:
|
|||
return fetch_add(1) + 1;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE constexpr T operator++() noexcept
|
||||
{
|
||||
return fetch_add(1) + 1;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE T operator++(int) volatile noexcept
|
||||
{
|
||||
return fetch_add(1);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE constexpr T operator++(int) noexcept
|
||||
{
|
||||
return fetch_add(1);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE T operator+=(T val) volatile noexcept
|
||||
{
|
||||
return fetch_add(val) + val;
|
||||
|
@ -262,16 +272,36 @@ public:
|
|||
return __atomic_fetch_add(&m_value, val, order);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE constexpr T fetch_add(T val, MemoryOrder order = DefaultMemoryOrder) noexcept
|
||||
{
|
||||
if (is_constant_evaluated()) {
|
||||
T old_value = m_value;
|
||||
m_value += val;
|
||||
return old_value;
|
||||
}
|
||||
return static_cast<Atomic volatile*>(this)->fetch_add(val, order);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE T operator--() volatile noexcept
|
||||
{
|
||||
return fetch_sub(1) - 1;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE constexpr T operator--() noexcept
|
||||
{
|
||||
return fetch_sub(1) - 1;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE T operator--(int) volatile noexcept
|
||||
{
|
||||
return fetch_sub(1);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE constexpr T operator--(int) noexcept
|
||||
{
|
||||
return fetch_sub(1);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE T operator-=(T val) volatile noexcept
|
||||
{
|
||||
return fetch_sub(val) - val;
|
||||
|
@ -288,6 +318,16 @@ public:
|
|||
return __atomic_fetch_sub(ptr, val, order);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE constexpr T fetch_sub(T val, MemoryOrder order = DefaultMemoryOrder) noexcept
|
||||
{
|
||||
if (is_constant_evaluated()) {
|
||||
T old_value = m_value;
|
||||
m_value -= val;
|
||||
return old_value;
|
||||
}
|
||||
return static_cast<Atomic volatile*>(this)->fetch_sub(val, order);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE T operator&=(T val) volatile noexcept
|
||||
{
|
||||
return fetch_and(val) & val;
|
||||
|
@ -323,11 +363,23 @@ public:
|
|||
return load();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE constexpr operator T() const noexcept
|
||||
{
|
||||
return load();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE T load(MemoryOrder order = DefaultMemoryOrder) const volatile noexcept
|
||||
{
|
||||
return __atomic_load_n(&m_value, order);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE constexpr T load(MemoryOrder order = DefaultMemoryOrder) const noexcept
|
||||
{
|
||||
if (is_constant_evaluated())
|
||||
return m_value;
|
||||
return static_cast<Atomic const volatile*>(this)->load(order);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(misc-unconventional-assign-operator) We want operator= to exchange the value, so returning an object of type Atomic& here does not make sense
|
||||
ALWAYS_INLINE T operator=(T desired) volatile noexcept
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue