00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #pragma once
00020
00021 #if defined(_WIN32)
00022 # include <windows.h>
00023 #endif
00024
00025 namespace mongo {
00026
00027 struct AtomicUInt {
00028 AtomicUInt() : x(0) {}
00029 AtomicUInt(unsigned z) : x(z) { }
00030
00031 operator unsigned() const { return x; }
00032 unsigned get() const { return x; }
00033
00034 inline AtomicUInt operator++();
00035 inline AtomicUInt operator++(int);
00036 inline AtomicUInt operator--();
00037 inline AtomicUInt operator--(int);
00038
00039 inline void zero();
00040
00041 volatile unsigned x;
00042 };
00043
00044 #if defined(_WIN32)
00045 void AtomicUInt::zero() {
00046 InterlockedExchange((volatile long*)&x, 0);
00047 }
00048 AtomicUInt AtomicUInt::operator++() {
00049 return InterlockedIncrement((volatile long*)&x);
00050 }
00051 AtomicUInt AtomicUInt::operator++(int) {
00052 return InterlockedIncrement((volatile long*)&x)-1;
00053 }
00054 AtomicUInt AtomicUInt::operator--() {
00055 return InterlockedDecrement((volatile long*)&x);
00056 }
00057 AtomicUInt AtomicUInt::operator--(int) {
00058 return InterlockedDecrement((volatile long*)&x)+1;
00059 }
00060 #elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
00061
00062 inline void AtomicUInt::zero() { x = 0; }
00063 AtomicUInt AtomicUInt::operator++() {
00064 return __sync_add_and_fetch(&x, 1);
00065 }
00066 AtomicUInt AtomicUInt::operator++(int) {
00067 return __sync_fetch_and_add(&x, 1);
00068 }
00069 AtomicUInt AtomicUInt::operator--() {
00070 return __sync_add_and_fetch(&x, -1);
00071 }
00072 AtomicUInt AtomicUInt::operator--(int) {
00073 return __sync_fetch_and_add(&x, -1);
00074 }
00075 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
00076 inline void AtomicUInt::zero() { x = 0; }
00077
00078 inline unsigned atomic_int_helper(volatile unsigned *x, int val) {
00079 int r;
00080 asm volatile
00081 (
00082 "lock\n\t"
00083 "xadd %1, %0":
00084 "+m"( *x ), "=r"( r ):
00085 "1"( val ):
00086 "memory", "cc"
00087 );
00088 return r;
00089 }
00090 AtomicUInt AtomicUInt::operator++() {
00091 return atomic_int_helper(&x, 1)+1;
00092 }
00093 AtomicUInt AtomicUInt::operator++(int) {
00094 return atomic_int_helper(&x, 1);
00095 }
00096 AtomicUInt AtomicUInt::operator--() {
00097 return atomic_int_helper(&x, -1)-1;
00098 }
00099 AtomicUInt AtomicUInt::operator--(int) {
00100 return atomic_int_helper(&x, -1);
00101 }
00102 #else
00103 # error "unsupported compiler or platform"
00104 #endif
00105
00106 }