223 lines
7.1 KiB
C++
223 lines
7.1 KiB
C++
// =====================================================================================================================
|
|
// fennec, a free and open source game engine
|
|
// Copyright © 2025 Medusa Slockbower
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
// =====================================================================================================================
|
|
|
|
#ifndef FENNEC_LANG_DETAIL_ATOMIC_H
|
|
#define FENNEC_LANG_DETAIL_ATOMIC_H
|
|
|
|
// Define _Atomic as volatile
|
|
#ifdef _Atomic
|
|
#undef _Atomic
|
|
#endif
|
|
#define _Atomic volatile
|
|
|
|
#if FENNEC_COMPILER_GCC
|
|
|
|
// memory_order ========================================================================================================
|
|
|
|
enum memory_order {
|
|
memory_order_relaxed = __ATOMIC_RELAXED,
|
|
memory_order_consume = __ATOMIC_CONSUME,
|
|
memory_order_acquire = __ATOMIC_ACQUIRE,
|
|
memory_order_release = __ATOMIC_RELEASE,
|
|
memory_order_acq_rel = __ATOMIC_ACQ_REL,
|
|
memory_order_seq_cst = __ATOMIC_SEQ_CST,
|
|
};
|
|
|
|
|
|
|
|
// atomic_init =========================================================================================================
|
|
|
|
template<typename T>
|
|
constexpr void atomic_init(_Atomic T* x, const T val) {
|
|
*x = val;
|
|
}
|
|
|
|
|
|
|
|
// atomic_flag =========================================================================================================
|
|
|
|
struct atomic_flag;
|
|
|
|
|
|
|
|
// atomic_flag_test_and_set ============================================================================================
|
|
|
|
constexpr bool atomic_flag_test_and_set(_Atomic atomic_flag* x) {
|
|
return ::__atomic_test_and_set(x, memory_order_seq_cst);
|
|
}
|
|
|
|
constexpr bool atomic_flag_test_and_set_explicit(_Atomic atomic_flag* x, memory_order memorder) {
|
|
return ::__atomic_test_and_set(x, memorder);
|
|
}
|
|
|
|
|
|
|
|
// atomic_flag_clear ===================================================================================================
|
|
|
|
constexpr void atomic_flag_clear(_Atomic atomic_flag* x) {
|
|
return ::__atomic_clear(x, memory_order_seq_cst);
|
|
}
|
|
|
|
constexpr void atomic_flag_clear_explicit(_Atomic atomic_flag* x, memory_order memorder) {
|
|
return ::__atomic_clear(x, memorder);
|
|
}
|
|
|
|
|
|
|
|
// atomic_load =========================================================================================================
|
|
|
|
template<typename T>
|
|
constexpr T atomic_load(_Atomic T* x) {
|
|
return ::__atomic_load_n(x, memory_order_seq_cst);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr T atomic_load_explicit(_Atomic T* x, memory_order memorder) {
|
|
return ::__atomic_load_n(x, memorder);
|
|
}
|
|
|
|
|
|
|
|
// atomic_store ========================================================================================================
|
|
|
|
template<typename T>
|
|
constexpr bool atomic_store(_Atomic T* x, const T val) {
|
|
return ::__atomic_store_n(x, val, memory_order_seq_cst);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr bool atomic_store_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
|
return ::__atomic_store_n(x, val, memorder);
|
|
}
|
|
|
|
|
|
|
|
// atomic_exchange =====================================================================================================
|
|
|
|
template<typename T>
|
|
constexpr bool atomic_exchange(_Atomic T* x, const T val) {
|
|
return ::__atomic_exchange_n(x, val, memory_order_seq_cst);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr bool atomic_exchange_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
|
return ::__atomic_exchange_n(x, val, memorder);
|
|
}
|
|
|
|
|
|
|
|
// atomic_compare_exchange_weak ========================================================================================
|
|
|
|
template<typename T>
|
|
constexpr bool atomic_compare_exchange_weak(_Atomic T* x, T* exp, const T des) {
|
|
return ::__atomic_compare_exchange_n(x, exp, des, true, memory_order_seq_cst, memory_order_seq_cst);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr bool atomic_compare_exchange_weak_explicit(_Atomic T* x, T* exp, const T des, memory_order succ, memory_order fail) {
|
|
return ::__atomic_compare_exchange_n(x, exp, des, true, succ, fail);
|
|
}
|
|
|
|
|
|
|
|
// atomic_compare_exchange_strong ======================================================================================
|
|
|
|
template<typename T>
|
|
constexpr bool atomic_compare_exchange_strong(_Atomic T* x, T* exp, const T des) {
|
|
return ::__atomic_compare_exchange_n(x, exp, des, false, memory_order_seq_cst, memory_order_seq_cst);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr bool atomic_compare_exchange_strong_explicit(_Atomic T* x, T* exp, const T des, memory_order succ, memory_order fail) {
|
|
return ::__atomic_compare_exchange_n(x, exp, des, false, succ, fail);
|
|
}
|
|
|
|
|
|
|
|
// atomic_fetch_add ====================================================================================================
|
|
|
|
template<typename T>
|
|
constexpr T atomic_fetch_add(_Atomic T* x, const T val) {
|
|
return ::__atomic_fetch_add(x, val, memory_order_seq_cst);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr T atomic_fetch_add_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
|
return ::__atomic_fetch_add(x, val, memorder);
|
|
}
|
|
|
|
|
|
|
|
// atomic_fetch_sub ====================================================================================================
|
|
|
|
template<typename T>
|
|
constexpr T atomic_fetch_sub(_Atomic T* x, const T val) {
|
|
return ::__atomic_fetch_sub(x, val, memory_order_seq_cst);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr T atomic_fetch_sub_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
|
return ::__atomic_fetch_sub(x, val, memorder);
|
|
}
|
|
|
|
|
|
|
|
// atomic_fetch_or ====================================================================================================
|
|
|
|
template<typename T>
|
|
constexpr T atomic_fetch_or(_Atomic T* x, const T val) {
|
|
return ::__atomic_fetch_or(x, val, memory_order_seq_cst);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr T atomic_fetch_or_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
|
return ::__atomic_fetch_or(x, val, memorder);
|
|
}
|
|
|
|
|
|
|
|
// atomic_fetch_xor ====================================================================================================
|
|
|
|
template<typename T>
|
|
constexpr T atomic_fetch_xor(_Atomic T* x, const T val) {
|
|
return ::__atomic_fetch_xor(x, val, memory_order_seq_cst);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr T atomic_fetch_xor_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
|
return ::__atomic_fetch_xor(x, val, memorder);
|
|
}
|
|
|
|
|
|
|
|
// atomic_fetch_and ====================================================================================================
|
|
|
|
template<typename T>
|
|
constexpr T atomic_fetch_and(_Atomic T* x, const T val) {
|
|
return ::__atomic_fetch_and(x, val, memory_order_seq_cst);
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr T atomic_fetch_and_explicit(_Atomic T* x, const T val, memory_order memorder) {
|
|
return ::__atomic_fetch_and(x, val, memorder);
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif // FENNEC_LANG_DETAIL_ATOMIC_H
|