3D Audio GSoC:
[blender.git] / intern / audaspace / intern / AUD_Reference.h
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * Copyright 2009-2011 Jörg Hermann Müller
7  *
8  * This file is part of AudaSpace.
9  *
10  * Audaspace is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * AudaSpace is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Audaspace; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file audaspace/intern/AUD_Reference.h
28  *  \ingroup audaspaceintern
29  */
30
31 #ifndef AUD_REFERENCE
32 #define AUD_REFERENCE
33
34 #include <map>
35
36 #ifdef MEM_DEBUG
37 #include <iostream>
38 #include <typeinfo>
39 #endif
40
41 class AUD_ReferenceHandler
42 {
43 private:
44         static std::map<void*, int> m_references;
45
46 public:
47         static inline void incref(void* reference)
48         {
49                 if(!reference)
50                         return;
51
52                 std::map<void*, int>::iterator result = m_references.find(reference);
53                 if(result != m_references.end())
54                 {
55                         m_references[reference]++;
56                 }
57                 else
58                 {
59                         m_references[reference] = 1;
60                 }
61         }
62
63         static inline bool decref(void* reference)
64         {
65                 if(!reference)
66                         return false;
67
68                 if(!--m_references[reference])
69                 {
70                         m_references.erase(reference);
71                         return true;
72                 }
73                 return false;
74         }
75 };
76
77 template <class T>
78 /**
79  * This class provides reference counting functionality.
80  */
81 class AUD_Reference
82 {
83 private:
84         /// The reference.
85         T* m_reference;
86         void* m_original;
87 public:
88         /**
89          * Creates a new reference counter.
90          * \param reference The reference.
91          */
92         AUD_Reference(T* reference = 0)
93         {
94                 m_original = m_reference = reference;
95                 AUD_ReferenceHandler::incref(reference);
96 #ifdef MEM_DEBUG
97                 if(m_reference != 0)
98                         std::cerr << "+" << typeid(*m_reference).name() << std::endl;
99 #endif
100         }
101
102         /**
103          * Copies an AUD_Reference object.
104          * \param ref The AUD_Reference object to copy.
105          */
106         AUD_Reference(const AUD_Reference& ref)
107         {
108                 m_original = m_reference = ref.m_reference;
109                 AUD_ReferenceHandler::incref(m_reference);
110 #ifdef MEM_DEBUG
111                 if(m_reference != 0)
112                         std::cerr << "+" << typeid(*m_reference).name() << std::endl;
113 #endif
114         }
115
116         template <class U>
117         explicit AUD_Reference(const AUD_Reference<U>& ref)
118         {
119                 m_original = ref.get();
120                 m_reference = dynamic_cast<T*>(ref.get());
121                 AUD_ReferenceHandler::incref(m_original);
122 #ifdef MEM_DEBUG
123                 if(m_reference != 0)
124                         std::cerr << "+" << typeid(*m_reference).name() << std::endl;
125 #endif
126         }
127
128         /**
129          * Destroys a AUD_Reference object, if there's no furthere reference on the
130          * reference, it is destroyed as well.
131          */
132         ~AUD_Reference()
133         {
134 #ifdef MEM_DEBUG
135                 if(m_reference != 0)
136                         std::cerr << "-" << typeid(*m_reference).name() << std::endl;
137 #endif
138                 if(AUD_ReferenceHandler::decref(m_original))
139                         delete m_reference;
140         }
141
142         /**
143          * Assigns an AUD_Reference to this object.
144          * \param ref The AUD_Reference object to assign.
145          */
146         AUD_Reference& operator=(const AUD_Reference& ref)
147         {
148                 if(&ref == this)
149                         return *this;
150
151 #ifdef MEM_DEBUG
152                 if(m_reference != 0)
153                         std::cerr << "-" << typeid(*m_reference).name() << std::endl;
154 #endif
155                 if(AUD_ReferenceHandler::decref(m_original))
156                         delete m_reference;
157
158                 m_original = ref.m_original;
159                 m_reference = ref.m_reference;
160                 AUD_ReferenceHandler::incref(m_original);
161 #ifdef MEM_DEBUG
162                 if(m_reference != 0)
163                         std::cerr << "+" << typeid(*m_reference).name() << std::endl;
164 #endif
165
166                 return *this;
167         }
168
169         /**
170          * Returns whether the reference is NULL.
171          */
172         inline bool isNull() const
173         {
174                 return m_reference == 0;
175         }
176
177         /**
178          * Returns the reference.
179          */
180         inline T* get() const
181         {
182                 return m_reference;
183         }
184
185         inline void* getOriginal() const
186         {
187                 return m_original;
188         }
189
190         /**
191          * Returns the reference.
192          */
193         inline T& operator*() const
194         {
195                 return *m_reference;
196         }
197
198         /**
199          * Returns the reference.
200          */
201         inline T* operator->() const
202         {
203                 return m_reference;
204         }
205 };
206
207 template<class T, class U>
208 inline bool operator==(const AUD_Reference<T>& a, const AUD_Reference<U>& b)
209 {
210         return a.getOriginal() == b.getOriginal();
211 }
212
213 template<class T, class U>
214 inline bool operator!=(const AUD_Reference<T>& a, const AUD_Reference<U>& b)
215 {
216         return a.getOriginal() != b.getOriginal();
217 }
218
219 #endif // AUD_REFERENCE