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