Merged with trunk r37717.
[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 class AUD_ReferenceHandler
37 {
38 private:
39         static std::map<void*, int> m_references;
40
41 public:
42         static inline void incref(void* reference)
43         {
44                 std::map<void*, int>::iterator result = m_references.find(reference);
45                 if(result != m_references.end())
46                 {
47                         m_references[reference]++;
48                 }
49                 else
50                 {
51                         m_references[reference] = 1;
52                 }
53         }
54
55         static inline bool decref(void* reference)
56         {
57                 if(!--m_references[reference])
58                 {
59                         m_references.erase(reference);
60                         return true;
61                 }
62                 return false;
63         }
64 };
65
66 template <class T>
67 /**
68  * This class provides reference counting functionality.
69  */
70 class AUD_Reference
71 {
72 private:
73         /// The reference.
74         T* m_reference;
75         void* m_original;
76 public:
77         /**
78          * Creates a new reference counter.
79          * \param reference The reference.
80          */
81         AUD_Reference(T* reference = 0)
82         {
83                 m_original = m_reference = reference;
84                 AUD_ReferenceHandler::incref(reference);
85         }
86
87         /**
88          * Copies an AUD_Reference object.
89          * \param ref The AUD_Reference object to copy.
90          */
91         AUD_Reference(const AUD_Reference& ref)
92         {
93                 m_original = m_reference = ref.m_reference;
94                 AUD_ReferenceHandler::incref(m_reference);
95         }
96
97         template <class U>
98         explicit AUD_Reference(const AUD_Reference<U>& ref)
99         {
100                 m_original = ref.get();
101                 m_reference = dynamic_cast<T*>(ref.get());
102                 AUD_ReferenceHandler::incref(m_original);
103         }
104
105         /**
106          * Destroys a AUD_Reference object, if there's no furthere reference on the
107          * reference, it is destroyed as well.
108          */
109         ~AUD_Reference()
110         {
111                 if(AUD_ReferenceHandler::decref(m_original))
112                         delete m_reference;
113         }
114
115         /**
116          * Assigns an AUD_Reference to this object.
117          * \param ref The AUD_Reference object to assign.
118          */
119         AUD_Reference& operator=(const AUD_Reference& ref)
120         {
121                 if(&ref == this)
122                         return *this;
123
124                 if(AUD_ReferenceHandler::decref(m_original))
125                         delete m_reference;
126
127                 m_original = ref.m_original;
128                 m_reference = ref.m_reference;
129                 AUD_ReferenceHandler::incref(m_original);
130
131                 return *this;
132         }
133
134         /**
135          * Returns whether the reference is NULL.
136          */
137         inline bool isNull() const
138         {
139                 return m_reference == 0;
140         }
141
142         /**
143          * Returns the reference.
144          */
145         inline T* get() const
146         {
147                 return m_reference;
148         }
149
150         inline void* getOriginal() const
151         {
152                 return m_original;
153         }
154
155         /**
156          * Returns the reference.
157          */
158         inline T& operator*() const
159         {
160                 return *m_reference;
161         }
162
163         /**
164          * Returns the reference.
165          */
166         inline T* operator->() const
167         {
168                 return m_reference;
169         }
170 };
171
172 template<class T, class U>
173 inline bool operator==(const AUD_Reference<T>& a, const AUD_Reference<U>& b)
174 {
175         return a.getOriginal() == b.getOriginal();
176 }
177
178 template<class T, class U>
179 inline bool operator!=(const AUD_Reference<T>& a, const AUD_Reference<U>& b)
180 {
181         return a.getOriginal() != b.getOriginal();
182 }
183
184 #endif // AUD_REFERENCE