2. Use increment and decrement API If possible, and use cas do same thing with 64 bits value.
3. I think we do not need operator "+=" and "-=" with it.
4. "InterlockedCompareExchange64" cannot be located with kernal32.dll on XP SP3, so I use "_InterlockedCompareExchange64" to replace it.
5. I think use c++ 0x11 std::atomic if possible and use boost::atomic for others is better.
Code: Select all
// atomic.cpp : Defines the entry point for the console application.
//
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
#endif
#if !defined(NOMINMAX) && defined(_MSC_VER)
# define NOMINMAX // required to stop windows.h messing up std::min
#endif
/*
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0502
#endif
#ifndef WINVER
#define WINVER 0x0502
#endif
*/
#include <windows.h>
#include <intrin.h>
#include <tchar.h>
template<class T> class AtomicScalar
{
public:
AtomicScalar (const T &initial)
: mField(initial)
{
}
AtomicScalar (const AtomicScalar<T> &cousin)
: mField(cousin.mField)
{
}
AtomicScalar ()
{
}
void operator = (const AtomicScalar<T> &cousin)
{
mField = cousin.mField;
}
T get (void) const
{
return mField;
}
void set (const T &v)
{
mField = v;
}
// cas
template <int = sizeof(T)>
struct cas_traits
{
bool operator () (T volatile &x, const T &old, const T &nu) { throw "exception!"; }
};
template <>
struct cas_traits<2>
{
__forceinline bool operator () (T volatile &x, const T &old, const T &nu)
{
return _InterlockedCompareExchange16((SHORT*)&x, static_cast<SHORT>(nu), static_cast<SHORT>(old)) == static_cast<SHORT>(old);
}
};
template <>
struct cas_traits<4>
{
__forceinline bool operator () (T volatile &x, const T &old, const T &nu)
{
return _InterlockedCompareExchange((LONG*)&x, static_cast<LONG>(nu), static_cast<LONG>(old)) == static_cast<LONG>(old);
}
};
template <>
struct cas_traits<8>
{
__forceinline bool operator () (T volatile &x, const T &old, const T &nu)
{
return _InterlockedCompareExchange64((LONGLONG*)&x, static_cast<LONGLONG>(nu), static_cast<LONGLONG>(old)) == static_cast<LONGLONG>(old);
}
};
bool cas (const T &old, const T &nu)
{
return cas_traits<>()(mField, old, nu);
}
// increment
template <int = sizeof(T)>
struct increment_traits
{
bool operator () (T volatile &x) { throw "exception!"; }
};
template <>
struct increment_traits<2>
{
__forceinline T operator () (T volatile &x)
{
return _InterlockedIncrement16((SHORT*)&x);
}
};
template <>
struct increment_traits<4>
{
__forceinline T operator () (T volatile &x)
{
return InterlockedIncrement((LONG*)&x);
}
};
template <>
struct increment_traits<8>
{
__forceinline T operator () (T volatile &x)
{
return _InterlockedCompareExchange64((LONGLONG*)&x, static_cast<LONGLONG>(x + 1), static_cast<LONGLONG>(x));
}
};
// decrement
template <int = sizeof(T)>
struct decrement_traits
{
bool operator () (T volatile &x) { throw "exception!"; }
};
template <>
struct decrement_traits<2>
{
__forceinline T operator () (T volatile &x)
{
return _InterlockedDecrement16((SHORT*)&x);
}
};
template <>
struct decrement_traits<4>
{
__forceinline T operator () (T volatile &x)
{
return InterlockedDecrement((LONG*)&x);
}
};
template <>
struct decrement_traits<8>
{
__forceinline T operator () (T volatile &x)
{
return _InterlockedCompareExchange64((LONGLONG*)&x, static_cast<LONGLONG>(x - 1), static_cast<LONGLONG>(x));
}
};
T operator++ (void)
{
return increment_traits<>()(mField);
}
T operator-- (void)
{
return decrement_traits<>()(mField);
}
T operator++ (int)
{
return increment_traits<>()(mField) - 1;
}
T operator-- (int)
{
return decrement_traits<>()(mField) + 1;
}
T operator+=(const T &add)
{
//The function InterlockedExchangeAdd is not available for 64 and 16 bit version
//We will use the cas operation instead.
T newVal;
do {
//Create a value of the current field plus the added value
newVal = mField + add;
//Replace the current field value with the new value. Ensure that the value
//of the field hasn't changed in the mean time by comparing it to the new value
//minus the added value.
} while (!cas(newVal - add, newVal)); //repeat until successful
return newVal;
}
T operator-=(const T &sub)
{
//The function InterlockedExchangeAdd is not available for 64 and 16 bit version
//We will use the cas operation instead.
T newVal;
do {
//Create a value of the current field plus the added value
newVal = mField - sub;
//Replace the current field value with the new value. Ensure that the value
//of the field hasn't changed in the mean time by comparing it to the new value
//minus the added value.
} while (!cas(newVal + sub, newVal)); //repeat until successful
return newVal;
}
volatile T mField;
};
int _tmain(int argc, _TCHAR* argv[])
{
typedef unsigned char ResourceHandle8;
typedef unsigned short ResourceHandle16;
typedef unsigned long int ResourceHandle32;
typedef unsigned long long int ResourceHandle64;
AtomicScalar<ResourceHandle64> mField(0);
++mField;
--mField;
mField++;
mField--;
mField += 2;
mField -= 2;
return 0;
}
