#ifndef ALTPTR_H
#define ALTPTR_H
/*--------------------------------------------------------------------------*

   Alternative Llibrary

  $Id: altPtr.h 644 2007-11-16 10:15:42Z nekosys $

  Copyright (C) 2007 NEKO SYSTEM
 
  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU Library General Public License for more details.
 
  You should have received a copy of the GNU Library General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *---------------------------------------------------------------------------*/
/**
 * \file    altPtr.h
 * \brief   Pointer template class
 * \date    2007
 * \author  NEKO SYSTEM
 */
/*----------------------------------------------------------------*
 * Include
 *----------------------------------------------------------------*/
#include <altBase/altBase.h>
#include <altBase/altBaseMem.h>
#include <altBase/altSyncThread.h>

#include <map>

/*----------------------------------------------------------------*
 * Type Definition
 *----------------------------------------------------------------*/

/*----------------------------------------------------------------*
 * Define
 *----------------------------------------------------------------*/

/*----------------------------------------------------------------*
 * Class Definition
 *----------------------------------------------------------------*/
///
/// \brief  Pointer Class
///
template <typename T>
class altPtr : public altBase
{
public:
  ///
  /// \brief  Constructor
  ///
  LIBALT_API altPtr()
  {
    m_pPtr = NULL;
    m_bInherited = false;
  };

  ///
  /// \brief  Constructor
  ///
  /// \param  pPtr  [I ] pointer
  ///
  LIBALT_API altPtr(T * pPtr)
  {
    oSync.BeginLock();
    m_pPtr = pPtr;
    oPtrMap[m_pPtr] = oPtrMap[m_pPtr] + 1;
    oSync.EndLock();
    m_bInherited = false;
  };

  ///
  /// \brief  Copy Constructor
  ///
  /// \param  oPtr  [I ] pointer object
  ///
  LIBALT_API altPtr(const altPtr<T> & oPtr)
  {
    oSync.BeginLock();
    m_pPtr = oPtr.m_pPtr;
    oPtrMap[m_pPtr] = oPtrMap[m_pPtr] + 1;
    oSync.EndLock();
    m_bInherited = false;
  };

  ///
  /// \brief  Destructor
  ///
  LIBALT_API virtual ~altPtr()
  {
    if (! m_bInherited) {
      oSync.BeginLock();
      oPtrMap[m_pPtr] = oPtrMap[m_pPtr] - 1;
      if (oPtrMap[m_pPtr] == 0) {
        delete m_pPtr;
        m_pPtr = NULL;
      }
      oSync.EndLock();
    }
  };

  ///
  /// \brief  operator = 
  ///
  /// \param  oPtr  [I ] object
  ///
  /// \return this object
  ///
  LIBALT_API altPtr & operator = (const altPtr<T> & oPtr)
  {
    (* this) = oPtr.m_pPtr;
    return (* this);
  }

  ///
  /// \brief  operator = 
  ///
  /// \param  pPtr  [I ] pointer
  ///
  LIBALT_API T * operator = (T * pPtr)
  {
    oSync.BeginLock();
    if (m_pPtr != NULL) {
      oPtrMap[m_pPtr] = oPtrMap[m_pPtr] - 1;
      if (oPtrMap[m_pPtr] == 0) {
        delete m_pPtr;
      }
    }
    m_pPtr = pPtr;
    if (pPtr != NULL) {
      oPtrMap[m_pPtr] = oPtrMap[m_pPtr] + 1;
    }
    oSync.EndLock();
    return (pPtr);
  }

  ///
  /// \brief  operator -> 
  ///
  /// \return pointer
  ///
  LIBALT_API  T * operator -> () const
  {
    return (m_pPtr);
  }

  ///
  /// \brief  operator *
  ///
  /// \return object
  ///
  LIBALT_API T & operator * () const
  {
    return (* m_pPtr);
  }

  ///
  /// \brief  operator ==
  ///
  /// \param  pPtr  [I ] pointer
  ///
  LIBALT_API altBool operator == (const T * pPtr) const
  {
    return (m_pPtr == pPtr);
  }

  ///
  /// \brief  operator ==
  ///
  /// \param  pPtr  [I ] pointer
  ///
  LIBALT_API altBool operator == (const altPtr<T> oPtr) const
  {
    return (m_pPtr == oPtr.m_pPtr);
  }

  ///
  /// \brief  operator !=
  ///
  /// \param  pPtr  [I ] pointer
  ///
  LIBALT_API altBool operator != (const T * pPtr) const
  {
    return (m_pPtr != pPtr);
  }

  ///
  /// \brief  operator !=
  ///
  /// \param  pPtr  [I ] pointer
  ///
  LIBALT_API altBool operator != (const altPtr<T> oPtr) const
  {
    return (m_pPtr != oPtr.m_pPtr);
  }

  ///
  /// \brief  operator <
  ///
  /// \param  pPtr  [I ] pointer
  ///
  LIBALT_API altBool operator < (const altPtr<T> oPtr) const
  {
    return (m_pPtr < oPtr.m_pPtr);
  }

  ///
  /// \brief  operator  []
  ///
  /// \param  nIndex  [i ] nIndex
  ///
  /// \return index element
  ///
  LIBALT_API T & operator [] (const altUInt nIndex) const
  {
    return (m_pPtr[nIndex]);
  }

  ///
  /// \brief  operator  []
  ///
  /// \param  nIndex  [i ] nIndex
  ///
  /// \return index element
  ///
  LIBALT_API T & operator [] (const altInt nIndex) const
  {
    return (m_pPtr[nIndex]);
  }

protected:
  static std::map<T *, altUInt> oPtrMap;      ///< pointer and reference count map
  static altSyncThread          oSync;        ///< thread syncronize object
  T *                           m_pPtr;       ///< pointer
  altBool                       m_bInherited; ///< inherited or not
};

template<typename T> std::map<T *, altUInt> altPtr<T>::oPtrMap; ///< pointer and reference count map
template<typename T> altSyncThread          altPtr<T>::oSync;   ///< thread syncronize object

#endif  // ALTPTR_H

