Issue 163
[zxing.git] / cpp / core / src / 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
26 #include <iostream>
27 #ifdef DEBUG_COUNTING
28 #include <typeinfo>
29 #endif
30
31 using namespace std;
32
33 namespace common {
34   /* base class for reference-counted objects */
35   class Counted {
36   private:
37     unsigned int count_;
38   public:
39     Counted() : count_(0) { 
40 #ifdef DEBUG_COUNTING
41       cout << "instantiating " << typeid(*this).name() << " " << this <<
42         " @ " << count_ << "\n";
43 #endif
44     }
45     virtual ~Counted() { }
46     virtual Counted *retain() { 
47 #ifdef DEBUG_COUNTING
48       cout << "retaining " << typeid(*this).name() << " " << this <<
49         " @ " << count_;
50 #endif
51       count_++;
52 #ifdef DEBUG_COUNTING
53       cout << "->" << count_ << "\n";
54 #endif
55       return this; 
56     }
57     virtual void release() { 
58 #ifdef DEBUG_COUNTING
59       cout << "releasing " << typeid(*this).name() << " " << this <<
60         " @ " << count_;
61 #endif
62       if (count_ == 0 || count_ == 54321) {
63 #ifdef DEBUG_COUNTING
64         cout << "\nOverreleasing already-deleted object " << this << "!!!\n";
65 #endif
66         throw 4711;
67       }
68       count_--; 
69 #ifdef DEBUG_COUNTING
70       cout << "->" << count_ << "\n";
71 #endif
72       if (count_ == 0) { 
73 #ifdef DEBUG_COUNTING
74         cout << "deleting " << typeid(*this).name() << " " << this << "\n";
75 #endif
76         count_ = 0xDEADF001;
77         delete this; 
78       } 
79     }
80     
81     /* return the current count for denugging purposes or similar */
82     int count() const { return count_; }
83   };
84   
85   /* counting reference to reference-counted objects */
86   template<typename T> class Ref {
87   private:
88   public:
89     T *object_;
90     explicit Ref(T *o = 0) : object_(0) { 
91 #ifdef DEBUG_COUNTING
92       cout << "instantiating Ref " << this << " from pointer\n";
93 #endif
94       reset(o);
95     }
96     
97     explicit Ref(const T &o) : object_(0) {
98 #ifdef DEBUG_COUNTING
99       cout << "instantiating Ref " << this << " from reference\n";
100 #endif
101       reset(const_cast<T *>(&o));
102     }
103     
104     Ref(const Ref &other) : object_(0) {
105 #ifdef DEBUG_COUNTING
106       cout << "instantiating Ref " << this << " from Ref " << &other << "\n";
107 #endif
108       reset(other.object_);
109     }
110     
111     template<class Y>
112     Ref(const Ref<Y> &other) : object_(0) {
113 #ifdef DEBUG_COUNTING
114       cout << "instantiating Ref " << this << " from reference\n";
115 #endif
116       reset(other.object_);
117     }
118     
119     
120     ~Ref() { 
121 #ifdef DEBUG_COUNTING
122       cout << "destroying Ref " << this << " with " <<
123         (object_ ? typeid(*object_).name() : "NULL") << " " << object_ << "\n";
124 #endif
125       if (object_) { 
126         object_->release(); 
127       } 
128     }
129     
130     void reset(T *o) {
131 #ifdef DEBUG_COUNTING
132       cout << "resetting Ref " << this << " from " <<
133         (object_ ? typeid(*object_).name() : "NULL") << " " << object_ <<
134         " to "  << (o ? typeid(*o).name() : "NULL") << " " << o << "\n";
135 #endif
136       if (o) { o->retain(); }
137       if (object_) { object_->release(); }
138       object_ = o;
139     }
140     Ref& operator=(const Ref &other) {
141       reset(other.object_);
142       return *this;
143     }
144     template<class Y>
145     Ref& operator=(const Ref<Y> &other) {
146       reset(other.object_);
147       return *this;
148     }
149     Ref& operator=(T* o) {
150       reset(o);
151       return *this;
152     }
153     template<class Y>
154     Ref& operator=(Y* o) {
155       reset(o);
156       return *this;
157     }
158     
159     T& operator*() { return *object_; }
160     T* operator->() { return object_; }
161     operator T*() { return object_; }
162     
163     bool operator==(const int x) { return x == 0 ? object_ == 0 : false; }
164     bool operator==(const Ref &other) const { 
165       return object_ == other.object_ || *object_ == *(other.object_);
166     }
167     template<class Y>
168     bool operator==(const Ref<Y> &other) const { 
169       return object_ == other.object_ || *object_ == *(other.object_);
170     }
171     
172     bool operator!=(const int x) { return x == 0 ? object_ != 0 : true; }
173     
174     template<class Y>
175     friend ostream& operator<<(ostream &out, Ref<Y>& ref);
176   };
177 }
178
179 #endif // __COUNTED_H__