blocxx
COWReference.hpp
Go to the documentation of this file.
1/*******************************************************************************
2* Copyright (C) 2005, Vintela, Inc. All rights reserved.
3* Copyright (C) 2006, Novell, Inc. All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7*
8* * Redistributions of source code must retain the above copyright notice,
9* this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of
14* Vintela, Inc.,
15* nor Novell, Inc.,
16* nor the names of its contributors or employees may be used to
17* endorse or promote products derived from this software without
18* specific prior written permission.
19*
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30* POSSIBILITY OF SUCH DAMAGE.
31*******************************************************************************/
32
33
38#ifndef BLOCXX_COWREFERENCE_HPP_INCLUDE_GUARD_
39#define BLOCXX_COWREFERENCE_HPP_INCLUDE_GUARD_
40#include "blocxx/BLOCXX_config.h"
43#include "blocxx/SafeBool.hpp"
44
45namespace BLOCXX_NAMESPACE
46{
47
53template<class T>
55{
56public:
57 typedef T element_type;
58
64
69 explicit COWReference(T* ptr);
70
78
86 template <class U>
88
95
105
116
118
123
127 const T* operator->() const;
128
133
137 const T& operator*() const;
138
142 const T* getPtr() const;
143 bool isNull() const BLOCXX_DEPRECATED; // in 3.1.0
144
146
147 template <class U>
149
150 template <class U>
152
153#if !defined(__GNUC__) || __GNUC__ > 2 // causes gcc 2.95 to ICE
154 /* This is so the templated constructor will work */
155 template <class U> friend class COWReference;
156private:
157#endif
158 T* volatile m_pObj;
159 void decRef();
161};
163template<class T>
165 : COWReferenceBase(), m_pObj(0)
166{
167}
169template<class T>
171 : COWReferenceBase(), m_pObj(ptr)
172{
173}
175template<class T>
177 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
178{
179}
181template<class T>
182template<class U>
184 : COWReferenceBase(arg), m_pObj(arg.m_pObj)
185{
186}
188template<class T>
190{
191 try
192 {
193 decRef();
194 }
195 catch (...)
196 {
197 // don't let exceptions escape
198 }
199}
201template<class T>
203{
204 typedef char type_must_be_complete[sizeof(T)];
206 {
207 delete m_pObj;
208 m_pObj = 0;
209 }
210}
211
213template<class T>
215{
217 {
218 // this needs to happen first to avoid a race condition between
219 // another thread deleting the object and this one making a copy.
220 T* tmp = COWReferenceClone(m_pObj);
221 // this will decrement the count and then make a new one if we're making a copy.
223 {
224 delete tmp;
225 }
226 else
227 {
228 m_pObj = tmp;
229 }
230 }
231}
233template<class T>
235{
236 COWReference<T>(arg).swap(*this);
237 return *this;
238}
240template<class T>
242{
243 COWReference<T>(newObj).swap(*this);
244 return *this;
245}
247template <class T>
249{
251 COWRefSwap(m_pObj, arg.m_pObj);
252}
254template<class T>
256{
257#ifdef BLOCXX_CHECK_NULL_REFERENCES
258 ReferenceHelpers::checkNull(this);
259 ReferenceHelpers::checkNull(m_pObj);
260#endif
261 getWriteLock();
262
263 return m_pObj;
264}
266template<class T>
268{
269#ifdef BLOCXX_CHECK_NULL_REFERENCES
270 ReferenceHelpers::checkNull(this);
271 ReferenceHelpers::checkNull(m_pObj);
272#endif
273 getWriteLock();
274
275 return *(m_pObj);
276}
278template<class T>
279inline const T* COWReference<T>::operator->() const
280{
281#ifdef BLOCXX_CHECK_NULL_REFERENCES
282 ReferenceHelpers::checkNull(this);
283 ReferenceHelpers::checkNull(m_pObj);
284#endif
285
286 return m_pObj;
287}
289template<class T>
290inline const T& COWReference<T>::operator*() const
291{
292#ifdef BLOCXX_CHECK_NULL_REFERENCES
293 ReferenceHelpers::checkNull(this);
294 ReferenceHelpers::checkNull(m_pObj);
295#endif
296
297 return *(m_pObj);
298}
300template<class T>
301inline const T* COWReference<T>::getPtr() const
302{
303 return m_pObj;
304}
306template<class T>
307inline bool COWReference<T>::isNull() const
308{
309 return (m_pObj == 0);
310}
312template <class T>
313template <class U>
314inline COWReference<U>
316{
317 COWReference<U> rval;
318 rval.m_pObj = dynamic_cast<U*>(m_pObj);
319 if (rval.m_pObj)
320 {
321 rval.useRefCountOf(*this);
322 }
323 return rval;
324}
326template <class T>
327template <class U>
328inline void
334// Comparisons
335template <class T, class U>
336inline bool operator==(const COWReference<T>& a, const COWReference<U>& b)
337{
338 return a.getPtr() == b.getPtr();
339}
341template <class T, class U>
342inline bool operator!=(const COWReference<T>& a, const COWReference<U>& b)
343{
344 return a.getPtr() != b.getPtr();
345}
347template <class T, class U>
348inline bool operator<(const COWReference<T>& a, const COWReference<U>& b)
349{
350 return a.getPtr() < b.getPtr();
351}
352
354template <class T>
355inline T* COWReferenceClone(T* obj)
356{
357 // default implementation. If a certain class doesn't have clone()
358 // (like std::vector), then they can overload this function
359 return obj->clone();
360}
361
362} // end namespace BLOCXX_NAMESPACE
363
364#endif // BLOCXX_COWREFERENCE_HPP_
#define BLOCXX_SAFE_BOOL_IMPL(classname, type, variable, test)
Definition SafeBool.hpp:58
void useRefCountOf(const COWReferenceBase &arg)
void swap(COWReferenceBase &arg)
COWReference A smart pointer that uses non-intrusive reference counting.
COWReference(const COWReference< U > &arg)
Copy constructor.
COWReference(T *ptr)
Construct a COWReference that will take ownership of a given pointer.
COWReference< U > cast_to() const
void useRefCountOf(const COWReference< U > &)
void swap(COWReference< T > &arg)
~COWReference()
Destroy this COWReference.
COWReference()
Default constructor The underlying object pointer will be NULL.
bool isNull() const BLOCXX_DEPRECATED
COWReference(const COWReference< T > &arg)
Copy constructor.
COWReference< T > & operator=(const COWReference< T > &arg)
Assignment operator.
Taken from RFC 1321.
T * COWReferenceClone(T *obj)
bool operator<(const Array< T > &x, const Array< T > &y)
bool operator==(const Array< T > &x, const Array< T > &y)
void COWRefSwap(T &x, T &y)
bool operator!=(const Array< T > &x, const Array< T > &y)
Determine two Arrays are not equal.
Definition Array.hpp:446