f79b5d8653c273c7a71f2acad86770c3b579f802
[zxing.git] / cpp / core / src / zxing / common / Counted.h
1 #ifndef __COUNTED_H__
2 #define __COUNTED_H__
3
4 /*
5  *  Counted.h
6  *  zxing
7  *
8  *  Copyright 2010 ZXing authors All rights reserved.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22
23 //#define DEBUG_COUNTING
24 //using namespace std;
25
26 #include <iostream>
27
28 #ifdef DEBUG_COUNTING
29 #include <typeinfo>
30 #endif
31
32 namespace zxing {
33
34 /* base class for reference-counted objects */
35 class Counted {
36 private:
37   unsigned int count_;
38 public:
39   Counted() :
40       count_(0) {
41 #ifdef DEBUG_COUNTING
42     cout << "instantiating " << typeid(*this).name() << " " << this <<
43          " @ " << count_ << "\n";
44 #endif
45   }
46   virtual ~Counted() {
47   }
48   virtual Counted *retain() {
49 #ifdef DEBUG_COUNTING
50     cout << "retaining " << typeid(*this).name() << " " << this <<
51          " @ " << count_;
52 #endif
53     count_++;
54 #ifdef DEBUG_COUNTING
55     cout << "->" << count_ << "\n";
56 #endif
57     return this;
58   }
59   virtual void release() {
60 #ifdef DEBUG_COUNTING
61     cout << "releasing " << typeid(*this).name() << " " << this <<
62          " @ " << count_;
63 #endif
64     if (count_ == 0 || count_ == 54321) {
65 #ifdef DEBUG_COUNTING
66       cout << "\nOverreleasing already-deleted object " << this << "!!!\n";
67 #endif
68       throw 4711;
69     }
70     count_--;
71 #ifdef DEBUG_COUNTING
72     cout << "->" << count_ << "\n";
73 #endif
74     if (count_ == 0) {
75 #ifdef DEBUG_COUNTING
76       cout << "deleting " << typeid(*this).name() << " " << this << "\n";
77 #endif
78       count_ = 0xDEADF001;
79       delete this;
80     }
81   }
82
83
84   /* return the current count for denugging purposes or similar */
85   int count() const {
86     return count_;
87   }
88 };
89
90 /* counting reference to reference-counted objects */
91 template<typename T> class Ref {
92 private:
93 public:
94   T *object_;
95   explicit Ref(T *o = 0) :
96       object_(0) {
97 #ifdef DEBUG_COUNTING
98     cout << "instantiating Ref " << this << " from pointer" << o << "\n";
99 #endif
100     reset(o);
101   }
102
103   explicit Ref(const T &o) :
104       object_(0) {
105 #ifdef DEBUG_COUNTING
106     cout << "instantiating Ref " << this << " from reference\n";
107 #endif
108     reset(const_cast<T *>(&o));
109   }
110
111   Ref(const Ref &other) :
112       object_(0) {
113 #ifdef DEBUG_COUNTING
114     cout << "instantiating Ref " << this << " from Ref " << &other << "\n";
115 #endif
116     reset(other.object_);
117   }
118
119   template<class Y>
120   Ref(const Ref<Y> &other) :
121       object_(0) {
122 #ifdef DEBUG_COUNTING
123     cout << "instantiating Ref " << this << " from reference\n";
124 #endif
125     reset(other.object_);
126   }
127
128   ~Ref() {
129 #ifdef DEBUG_COUNTING
130     cout << "destroying Ref " << this << " with " <<
131          (object_ ? typeid(*object_).name() : "NULL") << " " << object_ << "\n";
132 #endif
133     if (object_) {
134       object_->release();
135     }
136   }
137
138   void reset(T *o) {
139 #ifdef DEBUG_COUNTING
140     cout << "resetting Ref " << this << " from " <<
141          (object_ ? typeid(*object_).name() : "NULL") << " " << object_ <<
142          " to " << (o ? typeid(*o).name() : "NULL") << " " << o << "\n";
143 #endif
144     if (o) {
145       o->retain();
146     }
147     if (object_ != 0) {
148       object_->release();
149     }
150     object_ = o;
151   }
152   Ref& operator=(const Ref &other) {
153     reset(other.object_);
154     return *this;
155   }
156   template<class Y>
157   Ref& operator=(const Ref<Y> &other) {
158     reset(other.object_);
159     return *this;
160   }
161   Ref& operator=(T* o) {
162     reset(o);
163     return *this;
164   }
165   template<class Y>
166   Ref& operator=(Y* o) {
167     reset(o);
168     return *this;
169   }
170
171   T& operator*() {
172     return *object_;
173   }
174   T* operator->() const {
175     return object_;
176   }
177   operator T*() const {
178     return object_;
179   }
180
181   bool operator==(const int x) {
182     return x == 0 ? object_ == 0 : false;
183   }
184   bool operator==(const Ref &other) const {
185     return object_ == other.object_ || *object_ == *(other.object_);
186   }
187   template<class Y>
188   bool operator==(const Ref<Y> &other) const {
189     return object_ == other.object_ || *object_ == *(other.object_);
190   }
191
192   bool operator!=(const int x) {
193     return x == 0 ? object_ != 0 : true;
194   }
195
196   template<class Y>
197   friend std::ostream& operator<<(std::ostream &out, Ref<Y>& ref);
198 };
199 }
200
201 #endif // __COUNTED_H__