blob: 6fb2a96da760a3ed6e5eb75398dac7c12303546d [file] [log] [blame]
#include "THAtomic.h"
/*
Note: I thank Leon Bottou for his useful comments.
Ronan.
*/
#if defined(USE_C11_ATOMICS)
#include <stdatomic.h>
#endif
#if defined(USE_MSC_ATOMICS)
#include <intrin.h>
#endif
#if !defined(USE_MSC_ATOMICS) && !defined(USE_GCC_ATOMICS) && defined(USE_PTHREAD_ATOMICS)
#include <pthread.h>
static pthread_mutex_t ptm = PTHREAD_MUTEX_INITIALIZER;
#endif
void THAtomicSet(int volatile *a, int newvalue)
{
#if defined(USE_C11_ATOMICS)
atomic_store(a, newvalue);
#elif defined(USE_MSC_ATOMICS)
_InterlockedExchange((long*)a, newvalue);
#elif defined(USE_GCC_ATOMICS)
__sync_lock_test_and_set(a, newvalue);
#else
int oldvalue;
do {
oldvalue = *a;
} while (!THAtomicCompareAndSwap(a, oldvalue, newvalue));
#endif
}
int THAtomicGet(int volatile *a)
{
#if defined(USE_C11_ATOMICS)
return atomic_load(a);
#else
int value;
do {
value = *a;
} while (!THAtomicCompareAndSwap(a, value, value));
return value;
#endif
}
int THAtomicAdd(int volatile *a, int value)
{
#if defined(USE_C11_ATOMICS)
return atomic_fetch_add(a, value);
#elif defined(USE_MSC_ATOMICS)
return _InterlockedExchangeAdd((long*)a, value);
#elif defined(USE_GCC_ATOMICS)
return __sync_fetch_and_add(a, value);
#else
int oldvalue;
do {
oldvalue = *a;
} while (!THAtomicCompareAndSwap(a, oldvalue, (oldvalue + value)));
return oldvalue;
#endif
}
void THAtomicIncrementRef(int volatile *a)
{
THAtomicAdd(a, 1);
}
int THAtomicDecrementRef(int volatile *a)
{
return (THAtomicAdd(a, -1) == 1);
}
int THAtomicCompareAndSwap(int volatile *a, int oldvalue, int newvalue)
{
#if defined(USE_C11_ATOMICS)
return atomic_compare_exchange_strong(a, &oldvalue, newvalue);
#elif defined(USE_MSC_ATOMICS)
return (_InterlockedCompareExchange((long*)a, (long)newvalue, (long)oldvalue) == (long)oldvalue);
#elif defined(USE_GCC_ATOMICS)
return __sync_bool_compare_and_swap(a, oldvalue, newvalue);
#elif defined(USE_PTHREAD_ATOMICS)
int ret = 0;
pthread_mutex_lock(&ptm);
if(*a == oldvalue) {
*a = newvalue;
ret = 1;
}
pthread_mutex_unlock(&ptm);
return ret;
#else
#warning THAtomic is not thread safe
if(*a == oldvalue) {
*a = newvalue;
return 1;
}
else
return 0;
#endif
}