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