1 /*
2   Copyright (C) 2009 Facundo Domínguez
3 
4   This file is part of Spacejunk.
5 
6   Spacejunk is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10 
11   Foobar is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 /*
21  * This file defines counted references and
22  * */
23 
24 #ifndef REFERENCE_H
25 #define REFERENCE_H
26 #include <stdlib.h>
27 
28 template <class PointedType>
del(PointedType * p)29 inline void del(PointedType*p) {
30     delete p;
31 }
32 template <class PointedType>
delarray(PointedType * p)33 inline void delarray(PointedType*p) {
34     delete [] p;
35 }
36 
37 /** Reference-counted smart pointer implementation. */
38 template <class PointedType,void FreeRoutine(PointedType*) = del<PointedType> >
39 class Ref {
40 protected:
41     PointedType * p;
42     int * refCounter;
43 public:
Ref()44     Ref(): p(NULL), refCounter(NULL) {};
Ref(PointedType * p)45     explicit Ref(PointedType * p) : p(p), refCounter() {
46         refCounter=p?new int(1):NULL;
47     };
Ref(const Ref<PointedType,FreeRoutine> & r)48     Ref(const Ref<PointedType,FreeRoutine> & r) : p(r.p), refCounter(r.refCounter) {
49         if (refCounter) ++*refCounter;
50     };
51 
clear()52     void clear() {
53         if (p && !--*refCounter) {
54             FreeRoutine(p);
55             delete refCounter;
56         }
57     };
58 
59     Ref<PointedType,FreeRoutine> & operator=(const Ref<PointedType,FreeRoutine> & r) {
60         if (this!=&r) {
61             clear();
62             refCounter=r.refCounter;
63             if (refCounter) ++*refCounter;
64             p=r.p;
65         }
66         return *this;
67     };
68 
~Ref()69     virtual ~Ref() {
70         clear();
71     };
72 
73     PointedType * operator ->() const {
74         return p;
75     }
76     PointedType & operator *() const {
77         return *p;
78     }
79     bool operator == (const Ref<PointedType,FreeRoutine> & r) const {
80         return p==r.p;
81     }
82     bool operator != (const Ref<PointedType,FreeRoutine> & r) const {
83         return *this!=r;
84     }
85     bool operator < (const Ref<PointedType,FreeRoutine> & r) const {
86         return p<r.p;
87     }
88 };
89 
90 template <class PointedType>
clone(PointedType * p)91 inline PointedType* clone(PointedType*p) {
92     return p?new PointedType(*p):NULL;
93 }
94 
95 /** Deep copy smart pointer implementation. */
96 template <class PointedType,
97           PointedType* CloneRoutine(PointedType*)=clone<PointedType>,
98           void FreeRoutine(PointedType*) = del<PointedType>  >
99 class OwnRef {
100 protected:
101     PointedType * p;
102 public:
OwnRef()103     OwnRef(): p(NULL) {};
OwnRef(PointedType * p)104     OwnRef(PointedType * p) : p(p) {};
OwnRef(const OwnRef<PointedType,CloneRoutine,FreeRoutine> & r)105     OwnRef(const OwnRef<PointedType,CloneRoutine,FreeRoutine> & r) {
106         p=CloneRoutine(r.p);
107     };
108 
109     OwnRef<PointedType,CloneRoutine,FreeRoutine> & operator=(const OwnRef<PointedType,CloneRoutine,FreeRoutine> & r) {
110         if (this!=&r) {
111             if (p) FreeRoutine(p);
112             p=CloneRoutine(r.p);
113         }
114         return *this;
115     };
116 
117     OwnRef<PointedType,CloneRoutine,FreeRoutine> & operator=(PointedType * p) {
118         if (this->p!=p) {
119             if (this->p) FreeRoutine(this->p);
120             this->p=CloneRoutine(p);
121         }
122         return *this;
123     };
124 
~OwnRef()125     virtual ~OwnRef() {
126         if (p) FreeRoutine(p);/*cout<<rc<<"\n";*/
127     };
128 
129     PointedType * operator ->() const {
130         return p;
131     }
132     PointedType & operator *() const {
133         return *p;
134     }
135 };
136 
137 #endif // REFERENCE_H
138