Add implementation of atomic based on mutex.
This commit is contained in:
1 parent
672c2d509d
commit
57ac0d8ae4
2 files changed
+112
-2
No files matched your search
@@ -90,7 +90,7 @@ Other headers offering other functionality are:
|
||||
* m-core.h: header for meta-programming with the C preprocessor.
|
||||
* m-mutex.h: header for providing a very thin layer across multiple implementation of mutex/threads.
|
||||
* m-algo.h: header for providing various generic algorithms to the previous containers.
|
||||
* m-atomic.h: header for ensuring compatibility between C's stdatmic.h and C++'s atomic header.
|
||||
* m-atomic.h: header for ensuring compatibility between C's stdatomic.h and C++'s atomic header. Provide also an implementation over mutex if neither are available.
|
||||
* m-mempool.h: header for creating specialized & fast memory allocator.
|
||||
|
||||
Each containers define their iterators.
|
||||
|
||||
+111
-1
@@ -86,10 +86,120 @@ using std::atomic_flag_test_and_set_explicit;
|
||||
using std::atomic_flag_clear;
|
||||
using std::atomic_flag_clear_explicit;
|
||||
|
||||
#else
|
||||
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \
|
||||
|| ( defined(__GNUC__) && !defined(__clang__) ) \
|
||||
|| (defined(__clang__) && __clang_major__ >= 4)
|
||||
|
||||
/* CLANG 3.5 has issues with GCC's stdatomic.h
|
||||
and doesn't provide its own stdatomic.h */
|
||||
#include <stdatomic.h>
|
||||
|
||||
#else
|
||||
|
||||
/* No atomic.h, nor stdatomic.h
|
||||
Write a compatible slin layer using mutex. */
|
||||
#include "m-mutex.h"
|
||||
|
||||
/* The structure is quite large... */
|
||||
#define _Atomic(T) \
|
||||
struct { \
|
||||
volatile T __val; \
|
||||
T __zero; \
|
||||
T __previous; \
|
||||
bool __cmp; \
|
||||
m_mutex_t __lock; \
|
||||
}
|
||||
|
||||
/* Even memory order is defined, only the strongest constraint exist */
|
||||
typedef enum {
|
||||
memory_order_relaxed,
|
||||
memory_order_consume,
|
||||
memory_order_acquire,
|
||||
memory_order_release,
|
||||
memory_order_acq_rel,
|
||||
memory_order_seq_cst
|
||||
} memory_order;
|
||||
|
||||
typedef _Atomic(bool) atomic_bool;
|
||||
typedef _Atomic(char) atomic_char;
|
||||
typedef _Atomic(short) atomic_short;
|
||||
typedef _Atomic(int) atomic_int;
|
||||
typedef _Atomic(long) atomic_long;
|
||||
typedef _Atomic(long long) atomic_llong;
|
||||
typedef _Atomic(unsigned char) atomic_uchar;
|
||||
typedef _Atomic(signed char) atomic_schar;
|
||||
typedef _Atomic(unsigned short) atomic_ushort;
|
||||
typedef _Atomic(unsigned int) atomic_uint;
|
||||
typedef _Atomic(unsigned long) atomic_ulong;
|
||||
typedef _Atomic(unsigned long long) atomic_ullong;
|
||||
typedef _Atomic(intptr_t) atomic_intptr_t;
|
||||
typedef _Atomic(uintptr_t) atomic_uintptr_t;
|
||||
typedef _Atomic(size_t) atomic_size_t;
|
||||
typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
|
||||
/* TODO: Test if stdint.h was included?
|
||||
typedef _Atomic(intmax_t) atomic_intmax_t;
|
||||
typedef _Atomic(uintmax_t) atomic_uintmax_t;*/
|
||||
|
||||
/* Unlock the mutex and return the given value */
|
||||
static inline long long atomic_fetch_unlock (m_mutex_t *lock, long long val)
|
||||
{
|
||||
m_mutex_unlock (*lock);
|
||||
return val;
|
||||
}
|
||||
|
||||
#define atomic_fetch_op(ptr, val, op) \
|
||||
(m_mutex_lock((ptr)->__lock), \
|
||||
(ptr)->__previous = (ptr)->__val, \
|
||||
(ptr)->__val op (val), \
|
||||
atomic_fetch_unlock(&(ptr)->__lock, (ptr)->__previous-(ptr)->__zero)+(ptr)->__zero)
|
||||
|
||||
#define atomic_fetch_add(ptr, val) atomic_fetch_op(ptr, val, +=)
|
||||
#define atomic_fetch_sub(ptr, val) atomic_fetch_op(ptr, val, -=)
|
||||
#define atomic_fetch_or(ptr, val) atomic_fetch_op(ptr, val, |=)
|
||||
#define atomic_fetch_xor(ptr, val) atomic_fetch_op(ptr, val, ^=)
|
||||
#define atomic_fetch_and(ptr, val) atomic_fetch_op(ptr, val, &=)
|
||||
#define atomic_exchange(ptr, val) atomic_fetch_op(ptr, val, =)
|
||||
|
||||
#define ATOMIC_VAR_INIT(val) { val, 0, 0, 0, M_MUTEXI_INIT_VALUE }
|
||||
|
||||
#define atomic_init(ptr, val) \
|
||||
(m_mutex_init((ptr)->__lock), (ptr)->__val = val, (ptr)->__zero = 0)
|
||||
|
||||
#define atomic_load(ptr) \
|
||||
(m_mutex_lock((ptr)->__lock), \
|
||||
(ptr)->__previous = (ptr)->__val, \
|
||||
atomic_fetch_unlock(&(ptr)->__lock, (ptr)->__previous-(ptr)->__zero)+(ptr)->__zero)
|
||||
|
||||
#define atomic_store(ptr, val) \
|
||||
(m_mutex_lock((ptr)->__lock), \
|
||||
(ptr)->__val = val, \
|
||||
m_mutex_unlock((ptr)->__lock))
|
||||
|
||||
#define atomic_compare_exchange_strong(ptr, exp, val) \
|
||||
(m_mutex_lock((ptr)->__lock), \
|
||||
(ptr)->__cmp = (ptr)->__val == *(exp), \
|
||||
((ptr)->__cmp != 0 && ((ptr)->__val = (val))), \
|
||||
((ptr)->__cmp == 0 && (*(exp) = (ptr)->__val)), \
|
||||
atomic_fetch_unlock(&(ptr)->__lock, (ptr)->__cmp))
|
||||
|
||||
#define atomic_fetch_add_explicit(ptr, val, mem) atomic_fetch_op(ptr, val, +=)
|
||||
#define atomic_fetch_sub_explicit(ptr, val, mem) atomic_fetch_op(ptr, val, -=)
|
||||
#define atomic_fetch_or_explicit(ptr, val, mem) atomic_fetch_op(ptr, val, |=)
|
||||
#define atomic_fetch_xor_explicit(ptr, val, mem) atomic_fetch_op(ptr, val, ^=)
|
||||
#define atomic_fetch_and_explicit(ptr, val, mem) atomic_fetch_op(ptr, val, &=)
|
||||
#define atomic_exchange_explicit(ptr, val, mem) atomic_fetch_op(ptr, val, =)
|
||||
#define atomic_load_explicit(ptr, mem) atomic_load(ptr)
|
||||
#define atomic_store_explicit(ptr, val, mem) atomic_store(ptr, val)
|
||||
#define kill_dependency(ptr) atomic_load(ptr)
|
||||
#define atomic_thread_fence(mem) (void) 0
|
||||
#define atomic_signal_fence(mem) (void) 0
|
||||
#define atomic_is_lock_free(ptr) false
|
||||
#define atomic_compare_exchange_strong_explicit(ptr, exp, val, mem) atomic_compare_exchange_strong(ptr, exp, val)
|
||||
#define atomic_compare_exchange_weak_explicit(ptr, exp, val, mem) atomic_compare_exchange_strong(ptr, exp, val)
|
||||
#define atomic_compare_exchange_weak(ptr, exp, val) atomic_compare_exchange_strong(ptr, exp, val)
|
||||
|
||||
/* TODO: Missing atomic_flag */
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user