Shinya Kitaoka 810553
#pragma once
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
Shinya Kitaoka 120a6e
typedef struct { volatile int counter; } atomic_t;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define ATOMIC_INIT(i)                                                         \
Shinya Kitaoka 120a6e
  { (i) }
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
Shinya Kitaoka 120a6e
static __inline__ void atomic_add(int a, atomic_t *v) {
Shinya Kitaoka 120a6e
  int t;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  __asm__ __volatile__(
Shinya Kitaoka 120a6e
      "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"
Shinya Kitaoka 120a6e
      : "=&r"(t), "=m"(v->counter)
Shinya Kitaoka 120a6e
      : "r"(a), "r"(&v->counter), "m"(v->counter)
Shinya Kitaoka 120a6e
      : "cc");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static __inline__ int atomic_add_return(int a, atomic_t *v) {
Shinya Kitaoka 120a6e
  int t;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  __asm__ __volatile__(
Shinya Kitaoka 120a6e
      "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
Shinya Kitaoka 120a6e
      : "=&r"(t)
Shinya Kitaoka 120a6e
      : "r"(a), "r"(&v->counter)
Shinya Kitaoka 120a6e
      : "cc", "memory");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return t;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static __inline__ void atomic_sub(int a, atomic_t *v) {
Shinya Kitaoka 120a6e
  int t;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  __asm__ __volatile__(
Shinya Kitaoka 120a6e
      "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"
Shinya Kitaoka 120a6e
      : "=&r"(t), "=m"(v->counter)
Shinya Kitaoka 120a6e
      : "r"(a), "r"(&v->counter), "m"(v->counter)
Shinya Kitaoka 120a6e
      : "cc");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static __inline__ int atomic_sub_return(int a, atomic_t *v) {
Shinya Kitaoka 120a6e
  int t;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  __asm__ __volatile__(
Shinya Kitaoka 120a6e
      "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
Shinya Kitaoka 120a6e
      : "=&r"(t)
Shinya Kitaoka 120a6e
      : "r"(a), "r"(&v->counter)
Shinya Kitaoka 120a6e
      : "cc", "memory");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return t;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static __inline__ void atomic_inc(atomic_t *v) {
Shinya Kitaoka 120a6e
  int t;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  __asm__ __volatile__(
Shinya Kitaoka 120a6e
      "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"
Shinya Kitaoka 120a6e
      : "=&r"(t), "=m"(v->counter)
Shinya Kitaoka 120a6e
      : "r"(&v->counter), "m"(v->counter)
Shinya Kitaoka 120a6e
      : "cc");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static __inline__ int atomic_inc_return(atomic_t *v) {
Shinya Kitaoka 120a6e
  int t;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  __asm__ __volatile__(
Shinya Kitaoka 120a6e
      "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
Shinya Kitaoka 120a6e
      : "=&r"(t)
Shinya Kitaoka 120a6e
      : "r"(&v->counter)
Shinya Kitaoka 120a6e
      : "cc", "memory");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return t;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static __inline__ void atomic_dec(atomic_t *v) {
Shinya Kitaoka 120a6e
  int t;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  __asm__ __volatile__(
Shinya Kitaoka 120a6e
      "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"
Shinya Kitaoka 120a6e
      : "=&r"(t), "=m"(v->counter)
Shinya Kitaoka 120a6e
      : "r"(&v->counter), "m"(v->counter)
Shinya Kitaoka 120a6e
      : "cc");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static __inline__ int atomic_dec_return(atomic_t *v) {
Shinya Kitaoka 120a6e
  int t;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  __asm__ __volatile__(
Shinya Kitaoka 120a6e
      "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
Shinya Kitaoka 120a6e
      : "=&r"(t)
Shinya Kitaoka 120a6e
      : "r"(&v->counter)
Shinya Kitaoka 120a6e
      : "cc", "memory");
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  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
Shinya Kitaoka 120a6e
static __inline__ void atomic_set(atomic_t *v, const int value) {
Shinya Kitaoka 120a6e
  v->store(value);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static __inline__ int atomic_inc_return(atomic_t *v) {
Shinya Kitaoka 120a6e
  return v->fetch_add(1) + 1;  // post increment atomic
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static __inline__ int atomic_dec_return(atomic_t *v) {
Shinya Kitaoka 120a6e
  return v->fetch_sub(1) - 1;  // post decriment atomic
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static __inline__ int atomic_read(const atomic_t *v) { return v->load(); }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
static __inline__ int atomic_add(int num, const atomic_t *v) {
Shinya Kitaoka 120a6e
  return const_cast<atomic_t *="">(v)->fetch_add(num) +</atomic_t>
Shinya Kitaoka 120a6e
         num; /* なんで const つけた? */
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
@ @PLATFORM NOT SUPPORTED !@ @
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
/*! Platform specific
Shinya Kitaoka 120a6e
    Provides class with increment & decrement absolutely done in interlocked way
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class DVAPI TAtomicVar {
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
#if defined(LINUX) || defined(MACOSX)
Shinya Kitaoka 120a6e
  TAtomicVar() { atomic_set(&m_var, 0); }
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
  TAtomicVar() : m_var(0) {}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  long operator++() {
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Shinya Kitaoka 120a6e
    return InterlockedIncrement(&m_var);
Toshihiro Shimizu 890ddd
#elif defined(__sgi)
Shinya Kitaoka 120a6e
    return ++m_var;
Toshihiro Shimizu 890ddd
#elif defined(LINUX)
Shinya Kitaoka 120a6e
    // atomic_inc(&m_var);
Shinya Kitaoka 120a6e
    // return atomic_read(&m_var);
Shinya Kitaoka 120a6e
    //  this is broken as it can return a value != from ++m_var
Shinya Kitaoka 120a6e
    atomic_inc(&m_var);
Shinya Kitaoka 120a6e
    return atomic_read(&m_var);
Toshihiro Shimizu 890ddd
#elif defined(MACOSX)
Shinya Kitaoka 120a6e
    return atomic_inc_return(&m_var);
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  long operator+=(long value) {
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Shinya Kitaoka 120a6e
    InterlockedExchangeAdd(&m_var, value);
Shinya Kitaoka 120a6e
    return m_var;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#elif defined(__sgi)
Shinya Kitaoka 120a6e
    m_var += value;
Shinya Kitaoka 120a6e
    return m_var;
Toshihiro Shimizu 890ddd
#elif defined(LINUX)
Shinya Kitaoka 120a6e
    // atomic_inc(&m_var);
Shinya Kitaoka 120a6e
    // return atomic_read(&m_var);
Shinya Kitaoka 120a6e
    //  this is broken as it can return a value != from ++m_var
Shinya Kitaoka 120a6e
    assert(false);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    return m_var;
Toshihiro Shimizu 890ddd
#elif defined(MACOSX)
Shinya Kitaoka 120a6e
    atomic_add(value, &m_var);
Shinya Kitaoka 120a6e
    return atomic_read(&m_var);
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  long operator--() {
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Shinya Kitaoka 120a6e
    return InterlockedDecrement(&m_var);
Toshihiro Shimizu 890ddd
#elif defined(__sgi)
Shinya Kitaoka 120a6e
    return --m_var;
Toshihiro Shimizu 890ddd
#elif defined(LINUX)
Shinya Kitaoka 120a6e
    // atomic_dec(&m_var);
Shinya Kitaoka 120a6e
    // return atomic_read(&m_var);
Shinya Kitaoka 120a6e
    // broken as above...
Shinya Kitaoka 120a6e
    atomic_dec(&m_var);
Shinya Kitaoka 120a6e
    return atomic_read(&m_var);
Toshihiro Shimizu 890ddd
#elif defined(MACOSX)
Shinya Kitaoka 120a6e
    // atomic_dec(&m_var);
Shinya Kitaoka 120a6e
    // return atomic_read(&m_var);
Shinya Kitaoka 120a6e
    // broken as above...
Shinya Kitaoka 120a6e
    return atomic_dec_return(&m_var);
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  bool operator<=(const long &rhs) {
Toshihiro Shimizu 890ddd
#if defined(LINUX) || defined(MACOSX)
Shinya Kitaoka 120a6e
    return atomic_read(&m_var) <= rhs;
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
    return m_var <= rhs;
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  };
Shinya Kitaoka 120a6e
  operator long() const {
Toshihiro Shimizu 890ddd
#if defined(LINUX) || defined(MACOSX)
Shinya Kitaoka 120a6e
    return atomic_read(&m_var);
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
    return m_var;
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  };
Toshihiro Shimizu 890ddd
Shinya Kitaoka 9f5a1b
#ifdef _WIN32
Shinya Kitaoka 120a6e
  long m_var;
Toshihiro Shimizu 890ddd
#elif defined(__sgi)
Shinya Kitaoka 120a6e
  long m_var;
Toshihiro Shimizu 890ddd
#elif defined(LINUX) || defined(MACOSX)
Shinya Kitaoka 120a6e
  atomic_t m_var;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#if !defined(LINUX) || defined(LINUX) && (__GNUC__ == 3) && (__GNUC_MINOR__ > 1)
Shinya Kitaoka 120a6e
private:  // to avoid well known bug in gcc3 ... fixed in later versions..
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  TAtomicVar &operator=(const TAtomicVar &);  // not implemented
Shinya Kitaoka 120a6e
  TAtomicVar(const TAtomicVar &v);            // not implemented
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif