Files
fennec/include/fennec/threading/detail/_atomic.h
2025-12-17 01:11:28 -05:00

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