blob: 7d6a3c6075b8043f34490dc6960f578ef5f98eed [file] [edit]
/*
* Copyright 2026 Rive
*/
#pragma once
#include "rive/async/threading.hpp"
#include "rive/rive_types.hpp"
#include <atomic>
#include <type_traits>
namespace rive
{
/// Same as std::atomic's compare exchanges.
#if defined(__wasm__) && !defined(__wasm_atomics__)
// Without wasm atomics no other thread shares memory, and at -Oz std's
// exchange stays out of line with a branch for every memory order.
#if defined(__EMSCRIPTEN__) && !RIVE_ONE_THREAD()
#error "a shared heap needs wasm atomics"
#endif
template <typename T, typename... Orders>
RIVE_ALWAYS_INLINE bool compareExchangeStrong(
std::atomic<T>& word,
T& expected,
typename std::atomic<T>::value_type desired,
Orders...)
{
static_assert(std::has_unique_object_representations<T>::value, "");
T current = word.load(std::memory_order_relaxed);
if (current != expected)
{
expected = current;
return false;
}
word.store(desired, std::memory_order_relaxed);
return true;
}
template <typename T, typename... Orders>
RIVE_ALWAYS_INLINE bool compareExchangeWeak(
std::atomic<T>& word,
T& expected,
typename std::atomic<T>::value_type desired,
Orders... orders)
{
return compareExchangeStrong(word, expected, desired, orders...);
}
#else
template <typename T, typename... Orders>
RIVE_ALWAYS_INLINE bool compareExchangeStrong(
std::atomic<T>& word,
T& expected,
typename std::atomic<T>::value_type desired,
Orders... orders)
{
return word.compare_exchange_strong(expected, desired, orders...);
}
template <typename T, typename... Orders>
RIVE_ALWAYS_INLINE bool compareExchangeWeak(
std::atomic<T>& word,
T& expected,
typename std::atomic<T>::value_type desired,
Orders... orders)
{
return word.compare_exchange_weak(expected, desired, orders...);
}
#endif
} // namespace rive