|
|
|
|
@ -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;
|
|
|
|
|
|