Shinya Kitaoka 810553
#pragma once
Shinya Kitaoka 810553
Toshihiro Shimizu 890ddd
#ifndef TSMARTPOINTER_INCLUDED
Toshihiro Shimizu 890ddd
#define TSMARTPOINTER_INCLUDED
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tutil.h"
Toshihiro Shimizu 890ddd
#include "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
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef NDEBUG
Toshihiro Shimizu 890ddd
#define INSTANCE_COUNT_ENABLED
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class DVAPI TSmartObject {
Shinya Kitaoka 120a6e
  TAtomicVar m_refCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef INSTANCE_COUNT_ENABLED
Shinya Kitaoka 120a6e
  const TINT32 m_classCodeRef;
Shinya Kitaoka 120a6e
  static const TINT32 m_unknownClassCode;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  typedef short ClassCode;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TSmartObject(ClassCode
Toshihiro Shimizu 890ddd
#ifdef INSTANCE_COUNT_ENABLED
Shinya Kitaoka 120a6e
                   classCode
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
               )
Shinya Kitaoka 120a6e
      : m_refCount()
Toshihiro Shimizu 890ddd
#ifdef INSTANCE_COUNT_ENABLED
Shinya Kitaoka 120a6e
      , m_classCodeRef(classCode)
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  {
Toshihiro Shimizu 890ddd
#ifdef INSTANCE_COUNT_ENABLED
Shinya Kitaoka 120a6e
    incrementInstanceCount();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TSmartObject()
Shinya Kitaoka 120a6e
      : m_refCount()
Toshihiro Shimizu 890ddd
#ifdef INSTANCE_COUNT_ENABLED
Shinya Kitaoka 120a6e
      , m_classCodeRef(m_unknownClassCode)
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  {
Toshihiro Shimizu 890ddd
#ifdef INSTANCE_COUNT_ENABLED
Shinya Kitaoka 120a6e
    incrementInstanceCount();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  virtual ~TSmartObject() {
Shinya Kitaoka 120a6e
    assert(m_refCount == 0);
Toshihiro Shimizu 890ddd
#ifdef INSTANCE_COUNT_ENABLED
Shinya Kitaoka 120a6e
    decrementInstanceCount();
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  inline void addRef() { ++m_refCount; }
Shinya Kitaoka 120a6e
  inline void release() {
Shinya Kitaoka 120a6e
    if ((--m_refCount) <= 0) delete this;
Shinya Kitaoka 120a6e
  };
Shinya Kitaoka 120a6e
  inline TINT32 getRefCount() const { return m_refCount; }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  static TINT32 getInstanceCount(ClassCode code);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  void incrementInstanceCount();
Shinya Kitaoka 120a6e
  void decrementInstanceCount();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  // not implemented
Shinya Kitaoka 120a6e
  TSmartObject(const TSmartObject &);
Shinya Kitaoka 120a6e
  TSmartObject &operator=(const TSmartObject &);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define DECLARE_CLASS_CODE                                                     \
shun-iwasawa 5b7b9f
  \
Shinya Kitaoka 120a6e
private:                                                                       \
Shinya Kitaoka 120a6e
  static const TSmartObject::ClassCode m_classCode;                            \
shun-iwasawa 5b7b9f
  \
Shinya Kitaoka 120a6e
public:                                                                        \
Shinya Kitaoka 120a6e
  inline static TINT32 getInstanceCount() {                                    \
Shinya Kitaoka 120a6e
    return TSmartObject::getInstanceCount(m_classCode);                        \
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#define DEFINE_CLASS_CODE(T, ID)                                               \
Shinya Kitaoka 120a6e
  const TSmartObject::ClassCode T::m_classCode = ID;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class t=""></class>
5f084d
class TSmartHolderT {
29623f
public:
29623f
  typedef T Type;
5f084d
Toshihiro Shimizu 890ddd
protected:
Shinya Kitaoka 120a6e
  T *m_pointer;
29623f
  T& reference() const
29623f
    { assert(m_pointer); return *m_pointer; }
5f084d
5f084d
public:
5f084d
  TSmartHolderT() : m_pointer(0) {}
5f084d
  TSmartHolderT(const TSmartHolderT &src) : m_pointer(src.m_pointer)
29623f
    { if (m_pointer) m_pointer->addRef(); }
5f084d
  explicit TSmartHolderT(T *pointer) : m_pointer(pointer)
29623f
    { if (m_pointer) m_pointer->addRef(); }
5f084d
  virtual ~TSmartHolderT()
29623f
    { if (m_pointer) { m_pointer->release(); m_pointer = 0; } }
29623f
5f084d
  TSmartHolderT& operator=(const TSmartHolderT &src) { set(src); return *this; }
5f084d
29623f
  void set(T *pointer) {
29623f
    if (m_pointer != pointer) {
29623f
      // call 'addRef' before 'release'
29623f
      if (pointer) pointer->addRef();
29623f
      if (m_pointer) m_pointer->release();
29623f
      m_pointer = pointer;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
5f084d
  void set(const TSmartHolderT &src)
29623f
    { set(src.m_pointer); }
e65e8f
  void reset()
e65e8f
    { set(0); }
29623f
  bool operator!() const
29623f
    { return m_pointer == 0; }
29623f
  operator bool() const
29623f
    { return m_pointer != 0; }
e65e8f
5f084d
  bool operator==(const T *p) const { return m_pointer == p; }
5f084d
  bool operator!=(const T *p) const { return m_pointer != p; }
5f084d
  bool operator< (const T *p) const { return m_pointer <  p; }
5f084d
  bool operator> (const T *p) const { return m_pointer >  p; }
5f084d
  bool operator<=(const T *p) const { return m_pointer <= p; }
5f084d
  bool operator>=(const T *p) const { return m_pointer >= p; }
5f084d
5f084d
  template<class tt=""></class>
2d2bcd
  bool equal(const TT *p) const { return m_pointer == p; }
5f084d
  template<class tt=""></class>
2d2bcd
  bool less(const TT *p) const { return m_pointer < p; }
1906ae
  template<class tt=""></class>
2d2bcd
  bool greater(const TT *p) const { return m_pointer > p; }
2d2bcd
2d2bcd
  template<class tt=""></class>
2d2bcd
  bool operator==(const TSmartHolderT<tt> &p) const { return p.equal(m_pointer); }</tt>
2d2bcd
  template<class tt=""></class>
2d2bcd
  bool operator!=(const TSmartHolderT<tt> &p) const { return !p.equal(m_pointer); }</tt>
2d2bcd
  template<class tt=""></class>
2d2bcd
  bool operator< (const TSmartHolderT<tt> &p) const { return p.greater(m_pointer); }</tt>
1906ae
  template<class tt=""></class>
2d2bcd
  bool operator> (const TSmartHolderT<tt> &p) const { return p.less(m_pointer); }</tt>
1906ae
  template<class tt=""></class>
2d2bcd
  bool operator<=(const TSmartHolderT<tt> &p) const { return !p.less(m_pointer); }</tt>
1906ae
  template<class tt=""></class>
2d2bcd
  bool operator>=(const TSmartHolderT<tt> &p) const { return !p.greater(m_pointer); }</tt>
29623f
};
Shinya Kitaoka 120a6e
29623f
//=========================================================
Shinya Kitaoka 120a6e
29623f
template <class t=""></class>
5f084d
class TSmartPointerConstT: public TSmartHolderT<t> {</t>
29623f
public:
5f084d
  typedef TSmartHolderT<t> Holder;</t>
5f084d
  TSmartPointerConstT() {}
5f084d
  TSmartPointerConstT(const TSmartPointerConstT &src): Holder(src) {}
5f084d
  explicit TSmartPointerConstT(T *pointer): Holder(pointer) {}
5f084d
  TSmartPointerConstT& operator=(const TSmartPointerConstT &src) { Holder::set(src); return *this; }
5f084d
  const T* getConstPointer() const { return Holder::m_pointer; }
5f084d
  const T* operator->() const { return &Holder::reference(); }
5f084d
  const T& operator*() const { return Holder::reference(); }
5f084d
  const T* getPointer() const { return Holder::m_pointer; }
29623f
};
Shinya Kitaoka 120a6e
29623f
//=========================================================
Shinya Kitaoka 120a6e
29623f
template <class t=""></class>
5f084d
class TSmartPointerT: public TSmartPointerConstT<t> {</t>
29623f
public:
5f084d
  typedef TSmartPointerConstT<t> Const;</t>
5f084d
  TSmartPointerT() {}
5f084d
  TSmartPointerT(const TSmartPointerT &src): Const(src) {}
5f084d
  TSmartPointerT(T *pointer): Const(pointer) {}
5f084d
  TSmartPointerT& operator=(const TSmartPointerT &src) { Const::set(src); return *this; }
5f084d
  T* operator->() const { return &Const::reference(); }
5f084d
  T& operator*() const { return Const::reference(); }
5f084d
  T* getPointer() const { return Const::m_pointer; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <class base="" class="" derived,=""></class>
e280ae
class TDerivedSmartPointerT : public TSmartPointerT<derived> {</derived>
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  typedef TDerivedSmartPointerT<derived, base=""> DerivedSmartPointer;</derived,>
Toshihiro Shimizu 890ddd
1906ae
  TDerivedSmartPointerT() { };
1906ae
  TDerivedSmartPointerT(DERIVED *pointer):
1906ae
    TSmartPointerT<derived>(pointer) { }</derived>
1906ae
  TDerivedSmartPointerT(const TSmartPointerT<base> &p):
1906ae
    TSmartPointerT<derived>(dynamic_cast<derived*>(p.getPointer())) { }</derived*></derived>
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
71b43d
//=========================================================
71b43d
71b43d
typedef TSmartPointerT<tsmartobject> TSmartObjectP;</tsmartobject>
71b43d
Toshihiro Shimizu 890ddd
#endif