#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 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(src); dest->Attach(isTmp); } else { dest = src->Clone(isTmp); } } #endif