Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TATOMICVAR_H
Toshihiro Shimizu 890ddd
#define TATOMICVAR_H
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#undef DVAPI
Toshihiro Shimizu 890ddd
#undef DVVAR
Toshihiro Shimizu 890ddd
#ifdef TNZCORE_EXPORTS
Toshihiro Shimizu 890ddd
#define DVAPI DV_EXPORT_API
Toshihiro Shimizu 890ddd
#define DVVAR DV_EXPORT_VAR
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
#define DVAPI DV_IMPORT_API
Toshihiro Shimizu 890ddd
#define DVVAR DV_IMPORT_VAR
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
#include <windows.h></windows.h>
Toshihiro Shimizu 890ddd
#elif defined(__sgi)
Toshihiro Shimizu 890ddd
#include <sys atomic_ops.h=""></sys>
Toshihiro Shimizu 890ddd
#elif defined(LINUX)
Toshihiro Shimizu 890ddd
// #include <asm atomic.h=""></asm>
Toshihiro Shimizu 890ddd
// it's broken, either include the kernel header
Toshihiro Shimizu 890ddd
//   /usr/src/linux/include/asm/atomic.h
Toshihiro Shimizu 890ddd
// or copy it here
Toshihiro Shimizu 890ddd
#include "/usr/src/linux-2.4/include/asm/atomic.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#elif defined(powerpc)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// from linux-2.4.20-20.9/include/linux/asm-ppc
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef struct {
Toshihiro Shimizu 890ddd
	volatile int counter;
Toshihiro Shimizu 890ddd
} atomic_t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define ATOMIC_INIT(i) \
Toshihiro Shimizu 890ddd
	{                  \
Toshihiro Shimizu 890ddd
		(i)            \
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define atomic_read(v) ((v)->counter)
Toshihiro Shimizu 890ddd
#define atomic_set(v, i) (((v)->counter) = (i))
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
Toshihiro Shimizu 890ddd
extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// we define it as we want to run on SMP dual processors...
Toshihiro Shimizu 890ddd
#define CONFIG_SMP
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef CONFIG_SMP
Toshihiro Shimizu 890ddd
#define SMP_ISYNC "\n\tisync"
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
#define SMP_ISYNC
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ void atomic_add(int a, atomic_t *v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	__asm__ __volatile__(
Toshihiro Shimizu 890ddd
		"1:	lwarx	%0,0,%3		\n\
Toshihiro Shimizu 890ddd
	add	%0,%2,%0\n\
Toshihiro Shimizu 890ddd
	stwcx.	%0,0,%3\n\
Toshihiro Shimizu 890ddd
	bne-	1b"
Toshihiro Shimizu 890ddd
		: "=&r"(t), "=m"(v->counter)
Toshihiro Shimizu 890ddd
		: "r"(a), "r"(&v->counter), "m"(v->counter)
Toshihiro Shimizu 890ddd
		: "cc");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ int atomic_add_return(int a, atomic_t *v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	__asm__ __volatile__(
Toshihiro Shimizu 890ddd
		"1:	lwarx	%0,0,%2		\n\
Toshihiro Shimizu 890ddd
	add	%0,%1,%0\n\
Toshihiro Shimizu 890ddd
	stwcx.	%0,0,%2\n\
Toshihiro Shimizu 890ddd
	bne-	1b" SMP_ISYNC
Toshihiro Shimizu 890ddd
		: "=&r"(t)
Toshihiro Shimizu 890ddd
		: "r"(a), "r"(&v->counter)
Toshihiro Shimizu 890ddd
		: "cc", "memory");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return t;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ void atomic_sub(int a, atomic_t *v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	__asm__ __volatile__(
Toshihiro Shimizu 890ddd
		"1:	lwarx	%0,0,%3		\n\
Toshihiro Shimizu 890ddd
	subf	%0,%2,%0\n\
Toshihiro Shimizu 890ddd
	stwcx.	%0,0,%3\n\
Toshihiro Shimizu 890ddd
	bne-	1b"
Toshihiro Shimizu 890ddd
		: "=&r"(t), "=m"(v->counter)
Toshihiro Shimizu 890ddd
		: "r"(a), "r"(&v->counter), "m"(v->counter)
Toshihiro Shimizu 890ddd
		: "cc");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ int atomic_sub_return(int a, atomic_t *v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	__asm__ __volatile__(
Toshihiro Shimizu 890ddd
		"1:	lwarx	%0,0,%2		\n\
Toshihiro Shimizu 890ddd
	subf	%0,%1,%0\n\
Toshihiro Shimizu 890ddd
	stwcx.	%0,0,%2\n\
Toshihiro Shimizu 890ddd
	bne-	1b" SMP_ISYNC
Toshihiro Shimizu 890ddd
		: "=&r"(t)
Toshihiro Shimizu 890ddd
		: "r"(a), "r"(&v->counter)
Toshihiro Shimizu 890ddd
		: "cc", "memory");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return t;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ void atomic_inc(atomic_t *v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	__asm__ __volatile__(
Toshihiro Shimizu 890ddd
		"1:	lwarx	%0,0,%2		\n\
Toshihiro Shimizu 890ddd
	addic	%0,%0,1\n\
Toshihiro Shimizu 890ddd
	stwcx.	%0,0,%2\n\
Toshihiro Shimizu 890ddd
	bne-	1b"
Toshihiro Shimizu 890ddd
		: "=&r"(t), "=m"(v->counter)
Toshihiro Shimizu 890ddd
		: "r"(&v->counter), "m"(v->counter)
Toshihiro Shimizu 890ddd
		: "cc");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ int atomic_inc_return(atomic_t *v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	__asm__ __volatile__(
Toshihiro Shimizu 890ddd
		"1:	lwarx	%0,0,%1		\n\
Toshihiro Shimizu 890ddd
	addic	%0,%0,1\n\
Toshihiro Shimizu 890ddd
	stwcx.	%0,0,%1\n\
Toshihiro Shimizu 890ddd
	bne-	1b" SMP_ISYNC
Toshihiro Shimizu 890ddd
		: "=&r"(t)
Toshihiro Shimizu 890ddd
		: "r"(&v->counter)
Toshihiro Shimizu 890ddd
		: "cc", "memory");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return t;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ void atomic_dec(atomic_t *v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	__asm__ __volatile__(
Toshihiro Shimizu 890ddd
		"1:	lwarx	%0,0,%2		\n\
Toshihiro Shimizu 890ddd
	addic	%0,%0,-1\n\
Toshihiro Shimizu 890ddd
	stwcx.	%0,0,%2\n\
Toshihiro Shimizu 890ddd
	bne-	1b"
Toshihiro Shimizu 890ddd
		: "=&r"(t), "=m"(v->counter)
Toshihiro Shimizu 890ddd
		: "r"(&v->counter), "m"(v->counter)
Toshihiro Shimizu 890ddd
		: "cc");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ int atomic_dec_return(atomic_t *v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int t;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	__asm__ __volatile__(
Toshihiro Shimizu 890ddd
		"1:	lwarx	%0,0,%1		\n\
Toshihiro Shimizu 890ddd
	addic	%0,%0,-1\n\
Toshihiro Shimizu 890ddd
	stwcx.	%0,0,%1\n\
Toshihiro Shimizu 890ddd
	bne-	1b" SMP_ISYNC
Toshihiro Shimizu 890ddd
		: "=&r"(t)
Toshihiro Shimizu 890ddd
		: "r"(&v->counter)
Toshihiro Shimizu 890ddd
		: "cc", "memory");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return t;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#elif defined(i386)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <atomic></atomic>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef std::atomic<int> atomic_t;</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ void atomic_set(atomic_t *v, const int value)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	v->store(value);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ int atomic_inc_return(atomic_t *v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return v->fetch_add(1) + 1; // post increment atomic
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ int atomic_dec_return(atomic_t *v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return v->fetch_sub(1) - 1; // post decriment atomic
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ int atomic_read(const atomic_t *v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return v->load();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
static __inline__ int atomic_add(int num, const atomic_t *v)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return const_cast<atomic_t *="">(v)->fetch_add(num) + num; /* なんで const つけた? */</atomic_t>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
@ @PLATFORM NOT SUPPORTED !@ @
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! Platform specific 
Toshihiro Shimizu 890ddd
    Provides class with increment & decrement absolutely done in interlocked way 
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class DVAPI TAtomicVar
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
#if defined(LINUX) || defined(MACOSX)
Toshihiro Shimizu 890ddd
	TAtomicVar()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		atomic_set(&m_var, 0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
	TAtomicVar() : m_var(0)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	long operator++()
Toshihiro Shimizu 890ddd
	{
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
		return InterlockedIncrement(&m_var);
Toshihiro Shimizu 890ddd
#elif defined(__sgi)
Toshihiro Shimizu 890ddd
		return ++m_var;
Toshihiro Shimizu 890ddd
#elif defined(LINUX)
Toshihiro Shimizu 890ddd
		// atomic_inc(&m_var);
Toshihiro Shimizu 890ddd
		// return atomic_read(&m_var);
Toshihiro Shimizu 890ddd
		//  this is broken as it can return a value != from ++m_var
Toshihiro Shimizu 890ddd
		atomic_inc(&m_var);
Toshihiro Shimizu 890ddd
		return atomic_read(&m_var);
Toshihiro Shimizu 890ddd
#elif defined(MACOSX)
Toshihiro Shimizu 890ddd
		return atomic_inc_return(&m_var);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	long operator+=(long value)
Toshihiro Shimizu 890ddd
	{
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
		InterlockedExchangeAdd(&m_var, value);
Toshihiro Shimizu 890ddd
		return m_var;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#elif defined(__sgi)
Toshihiro Shimizu 890ddd
		m_var += value;
Toshihiro Shimizu 890ddd
		return m_var;
Toshihiro Shimizu 890ddd
#elif defined(LINUX)
Toshihiro Shimizu 890ddd
		// atomic_inc(&m_var);
Toshihiro Shimizu 890ddd
		// return atomic_read(&m_var);
Toshihiro Shimizu 890ddd
		//  this is broken as it can return a value != from ++m_var
Toshihiro Shimizu 890ddd
		assert(false);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return m_var;
Toshihiro Shimizu 890ddd
#elif defined(MACOSX)
Toshihiro Shimizu 890ddd
		atomic_add(value, &m_var);
Toshihiro Shimizu 890ddd
		return atomic_read(&m_var);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	long operator--()
Toshihiro Shimizu 890ddd
	{
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
		return InterlockedDecrement(&m_var);
Toshihiro Shimizu 890ddd
#elif defined(__sgi)
Toshihiro Shimizu 890ddd
		return --m_var;
Toshihiro Shimizu 890ddd
#elif defined(LINUX)
Toshihiro Shimizu 890ddd
		// atomic_dec(&m_var);
Toshihiro Shimizu 890ddd
		// return atomic_read(&m_var);
Toshihiro Shimizu 890ddd
		// broken as above...
Toshihiro Shimizu 890ddd
		atomic_dec(&m_var);
Toshihiro Shimizu 890ddd
		return atomic_read(&m_var);
Toshihiro Shimizu 890ddd
#elif defined(MACOSX)
Toshihiro Shimizu 890ddd
		// atomic_dec(&m_var);
Toshihiro Shimizu 890ddd
		// return atomic_read(&m_var);
Toshihiro Shimizu 890ddd
		// broken as above...
Toshihiro Shimizu 890ddd
		return atomic_dec_return(&m_var);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bool operator<=(const long &rhs)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
#if defined(LINUX) || defined(MACOSX)
Toshihiro Shimizu 890ddd
		return atomic_read(&m_var) <= rhs;
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
		return m_var <= rhs;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
	operator long() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
#if defined(LINUX) || defined(MACOSX)
Toshihiro Shimizu 890ddd
		return atomic_read(&m_var);
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
		return m_var;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Toshihiro Shimizu 890ddd
	long m_var;
Toshihiro Shimizu 890ddd
#elif defined(__sgi)
Toshihiro Shimizu 890ddd
	long m_var;
Toshihiro Shimizu 890ddd
#elif defined(LINUX) || defined(MACOSX)
Toshihiro Shimizu 890ddd
	atomic_t m_var;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if !defined(LINUX) || defined(LINUX) && (__GNUC__ == 3) && (__GNUC_MINOR__ > 1)
Toshihiro Shimizu 890ddd
private: // to avoid well known bug in gcc3 ... fixed in later versions..
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	TAtomicVar &operator=(const TAtomicVar &); //not implemented
Toshihiro Shimizu 890ddd
	TAtomicVar(const TAtomicVar &v);		   //not implemented
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif