| [228] | 1 | #ifndef PREFCOUNT_H
 | 
|---|
 | 2 | #define PREFCOUNT_H
 | 
|---|
 | 3 | 
 | 
|---|
 | 4 | // Classe d'objet avec comptage de référence.
 | 
|---|
 | 5 | // Le nombre de référence est incrémenté lors de la création et lors d'un Attach
 | 
|---|
 | 6 | // (inutile d'appeler Attach si on crée l'objet).
 | 
|---|
 | 7 | // Si on cree l'objet avec isTmp = true, alors le possesseur est temporaire,
 | 
|---|
 | 8 | // et en tout cas, possede le PRefCount en lecture seule.
 | 
|---|
 | 9 | // Par exemple, une fonction qui retourne un objet de type PRefCounted le créera
 | 
|---|
 | 10 | // en mode temporaire. Un constructeur par copie appelé derrière ne dupliquera pas
 | 
|---|
 | 11 | // les données.
 | 
|---|
 | 12 | // HasTmpOnly retourne true si un objet n'est référencé que de façon temporaire.
 | 
|---|
 | 13 | 
 | 
|---|
 | 14 | #ifdef TRACE_REFCOUNT
 | 
|---|
 | 15 | #define DBG_DESTROY cerr << "PRefCounted destroyed" << endl;
 | 
|---|
 | 16 | #define DBG_ATTACH  cerr << "PRefCounted attached" << endl;
 | 
|---|
 | 17 | #define DBG_DETACH  cerr << "PRefCounted detached" << endl;
 | 
|---|
 | 18 | #else
 | 
|---|
 | 19 | #define DBG_DESTROY 
 | 
|---|
 | 20 | #define DBG_ATTACH
 | 
|---|
 | 21 | #define DBG_DETACH
 | 
|---|
 | 22 | #endif
 | 
|---|
 | 23 | 
 | 
|---|
 | 24 | 
 | 
|---|
 | 25 | class PRefCounted {
 | 
|---|
 | 26 | public:
 | 
|---|
 | 27 |                                PRefCounted(bool isTmp=false) 
 | 
|---|
 | 28 |                                                         :refcount(1), tmpcount(isTmp?1:0) {}
 | 
|---|
 | 29 |   virtual                      ~PRefCounted()           {DBG_DESTROY}
 | 
|---|
 | 30 |   
 | 
|---|
 | 31 |   void                         Attach(bool isTemp=false) 
 | 
|---|
 | 32 |                                                         {if (isTemp && HasTmpOnly()) tmpcount++;
 | 
|---|
 | 33 |                                                          DBG_ATTACH
 | 
|---|
 | 34 |                                                          refcount++;}
 | 
|---|
 | 35 |   void                         Detach()                 {refcount--;
 | 
|---|
 | 36 |                                                          DBG_DETACH
 | 
|---|
 | 37 |                                                          if (!refcount) delete this;}
 | 
|---|
 | 38 |   
 | 
|---|
 | 39 |   int                          RefCount() const         {return refcount;}
 | 
|---|
 | 40 |   bool                         HasTmpOnly() const       {return tmpcount == refcount;}
 | 
|---|
 | 41 |   
 | 
|---|
 | 42 | private:
 | 
|---|
 | 43 |   int refcount;
 | 
|---|
 | 44 |   int tmpcount;
 | 
|---|
 | 45 | };
 | 
|---|
 | 46 | 
 | 
|---|
 | 47 | // Macro pour les constructeurs par copie d'objets référençant des PRefCounted
 | 
|---|
 | 48 | // Il faut que le PRefCounted ait une méthode T* Clone(bool isTmp);
 | 
|---|
 | 49 | 
 | 
|---|
 | 50 | template <class refcount>
 | 
|---|
 | 51 | void PRefCountCopy(refcount*& dest, refcount const* src, bool isTmp=false) {
 | 
|---|
 | 52 |   if (dest) dest->Detach();
 | 
|---|
 | 53 |   if (!src) {
 | 
|---|
 | 54 |     dest=0;
 | 
|---|
 | 55 |   } else if (src->HasTmpOnly()) {
 | 
|---|
 | 56 |     dest = const_cast<refcount*>(src);
 | 
|---|
 | 57 |     dest->Attach(isTmp);
 | 
|---|
 | 58 |   } else {
 | 
|---|
 | 59 |     dest = src->Clone(isTmp);
 | 
|---|
 | 60 |   }
 | 
|---|
 | 61 | }
 | 
|---|
 | 62 | 
 | 
|---|
 | 63 | 
 | 
|---|
 | 64 | #endif
 | 
|---|
 | 65 | 
 | 
|---|