#ifndef PREFCOUNT_H
#define PREFCOUNT_H

// Classe d'objet avec comptage de référence.
// Le nombre de référence est incrémenté lors de la création et lors d'un Attach
// (inutile d'appeler Attach si on crée l'objet).
// Si on cree l'objet avec isTmp = true, alors le possesseur est temporaire,
// et en tout cas, possede le PRefCount en lecture seule.
// Par exemple, une fonction qui retourne un objet de type PRefCounted le créera
// en mode temporaire. Un constructeur par copie appelé derrière ne dupliquera pas
// les données.
// HasTmpOnly retourne true si un objet n'est référencé que de façon temporaire.

#ifdef TRACE_REFCOUNT
#define DBG_DESTROY cerr << "PRefCounted destroyed" << endl;
#define DBG_ATTACH  cerr << "PRefCounted attached" << endl;
#define DBG_DETACH  cerr << "PRefCounted detached" << endl;
#else
#define DBG_DESTROY 
#define DBG_ATTACH
#define DBG_DETACH
#endif


class PRefCounted {
public:
                               PRefCounted(bool isTmp=false) 
                                                        :refcount(1), tmpcount(isTmp?1:0) {}
  virtual                      ~PRefCounted()           {DBG_DESTROY}
  
  void                         Attach(bool isTemp=false) 
                                                        {if (isTemp && HasTmpOnly()) tmpcount++;
                                                         DBG_ATTACH
                                                         refcount++;}
  void                         Detach()                 {refcount--;
                                                         DBG_DETACH
                                                         if (!refcount) delete this;}
  
  int                          RefCount() const         {return refcount;}
  bool                         HasTmpOnly() const       {return tmpcount == refcount;}
  
private:
  int refcount;
  int tmpcount;
};

// Macro pour les constructeurs par copie d'objets référençant des PRefCounted
// Il faut que le PRefCounted ait une méthode T* Clone(bool isTmp);

template <class refcount>
void PRefCountCopy(refcount*& dest, refcount const* src, bool isTmp=false) {
  if (dest) dest->Detach();
  if (!src) {
    dest=0;
  } else if (src->HasTmpOnly()) {
    dest = const_cast<refcount*>(src);
    dest->Attach(isTmp);
  } else {
    dest = src->Clone(isTmp);
  }
}


#endif

