Fix for architectures w/o atomic built-in functions

sayer/1.4-spce2.6
Peter Lemenkov 16 years ago committed by Raphael Coeffic
parent 08f6326ac2
commit df9524d8e0

@ -1,31 +1,49 @@
#ifndef _atomic_types_h_
#define _atomic_types_h_
#if defined(__GNUC__)
# if defined(__GNUC_PATCHLEVEL__)
# define __GNUC_VERSION__ (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
# else
# define __GNUC_VERSION__ (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100)
# endif
#if (__GNUC__ > 4) || \
(__GNUC__ == 4 && __GNUC_MINOR__ >= 1) && \
( \
(defined(__APPLE__) && \
( \
defined(__ppc__) || \
defined(__i386__) || \
defined(__x86_64__) \
) \
) || \
(defined(__linux__) && \
( \
(defined(__i386__) && (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8))) || \
defined(__ia64__) || \
defined(__x86_64__) || \
(defined(__powerpc__) && !defined(__powerpc64__)) || \
defined(__alpha) \
) \
) \
)
#define HAVE_ATOMIC_CAS 1
#else
#error Unsupported compiler
#endif
#if __GNUC_VERSION__ < 40101
#error GCC version >= 4.1.1 is required for proper atomic operations
#warning Compare and Swap is not supported on this architecture
#define HAVE_ATOMIC_CAS 0
#endif
#include <assert.h>
#include "log.h"
#if !HAVE_ATOMIC_CAS
#include "AmThread.h"
#endif
// 32 bit unsigned integer
class atomic_int
#if !HAVE_ATOMIC_CAS
: protected AmMutex
#endif
{
volatile unsigned int i;
public:
atomic_int() : i(0) {}
@ -37,6 +55,7 @@ public:
return i;
}
#if HAVE_ATOMIC_CAS
// ++i;
unsigned int inc() {
return __sync_add_and_fetch(&i,1);
@ -46,6 +65,25 @@ public:
unsigned int dec() {
return __sync_sub_and_fetch(&i,1);
}
#else // if HAVE_ATOMIC_CAS
// ++i;
unsigned int inc() {
unsigned int res;
lock();
res = ++i;
unlock();
return res;
}
// --i;
unsigned int dec() {
unsigned int res;
lock();
res = --i;
unlock();
return res;
}
#endif
// return --ll != 0;
bool dec_and_test() {
@ -55,10 +93,14 @@ public:
// 64 bit unsigned integer
class atomic_int64
#if !HAVE_ATOMIC_CAS
: protected AmMutex
#endif
{
volatile unsigned long long ll;
public:
#if HAVE_ATOMIC_CAS
void set(unsigned long long val) {
#if !defined(__LP64__) || !__LP64__
unsigned long long tmp_ll;
@ -95,6 +137,49 @@ public:
return __sync_sub_and_fetch(&ll,1);
}
#else // if HAVE_ATOMIC_CAS
void set(unsigned long long val) {
#if !defined(__LP64__) || !__LP64__
this->lock();
ll = val;
unlock();
#else
ll = val;
#endif
}
unsigned long long get() {
#if !defined(__LP64__) || !__LP64__
unsigned long long tmp_ll;
lock();
tmp_ll = ll;
unlock();
return tmp_ll;
#else
return ll;
#endif
}
// returns ++ll;
unsigned long long inc() {
unsigned long long res;
lock();
res = ++ll;
unlock();
return res;
}
// returns --ll;
unsigned long long dec() {
unsigned long long res;
lock();
res = --ll;
unlock();
return res;
}
#endif
// return --ll == 0;
bool dec_and_test() {
return dec() == 0;

Loading…
Cancel
Save