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 
45 namespace BLOCXX_NAMESPACE
46 {
47 
53 template<class T>
55 {
56 public:
57  typedef T element_type;
58 
63  COWReference();
64 
69  explicit COWReference(T* ptr);
70 
77  COWReference(const COWReference<T>& arg);
78 
86  template <class U>
87  COWReference(const COWReference<U>& arg);
88 
94  ~COWReference();
95 
105 
115  COWReference<T>& operator= (T* newObj);
116 
117  void swap(COWReference<T>& arg);
118 
122  T* operator->();
123 
127  const T* operator->() const;
128 
132  T& operator*();
133 
137  const T& operator*() const;
138 
142  const T* getPtr() const;
143  bool isNull() const BLOCXX_DEPRECATED; // in 3.1.0
144 
145  BLOCXX_SAFE_BOOL_IMPL(COWReference, T* volatile, COWReference::m_pObj, m_pObj)
146 
147  template <class U>
148  COWReference<U> cast_to() const;
149 
150  template <class U>
151  void useRefCountOf(const COWReference<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;
156 private:
157 #endif
158  T* volatile m_pObj;
159  void decRef();
160  void getWriteLock();
161 };
163 template<class T>
165  : COWReferenceBase(), m_pObj(0)
166 {
167 }
169 template<class T>
171  : COWReferenceBase(), m_pObj(ptr)
172 {
173 }
175 template<class T>
177  : COWReferenceBase(arg), m_pObj(arg.m_pObj)
178 {
179 }
181 template<class T>
182 template<class U>
184  : COWReferenceBase(arg), m_pObj(arg.m_pObj)
185 {
186 }
188 template<class T>
190 {
191  try
192  {
193  decRef();
194  }
195  catch (...)
196  {
197  // don't let exceptions escape
198  }
199 }
201 template<class T>
203 {
204  typedef char type_must_be_complete[sizeof(T)];
206  {
207  delete m_pObj;
208  m_pObj = 0;
209  }
210 }
211 
213 template<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 }
233 template<class T>
235 {
236  COWReference<T>(arg).swap(*this);
237  return *this;
238 }
240 template<class T>
242 {
243  COWReference<T>(newObj).swap(*this);
244  return *this;
245 }
247 template <class T>
249 {
251  COWRefSwap(m_pObj, arg.m_pObj);
252 }
254 template<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 }
266 template<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 }
278 template<class T>
279 inline 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 }
289 template<class T>
290 inline 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 }
300 template<class T>
301 inline const T* COWReference<T>::getPtr() const
302 {
303  return m_pObj;
304 }
306 template<class T>
307 inline bool COWReference<T>::isNull() const
308 {
309  return (m_pObj == 0);
310 }
312 template <class T>
313 template <class U>
314 inline 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 }
326 template <class T>
327 template <class U>
328 inline void
330 {
332 }
334 // Comparisons
335 template <class T, class U>
336 inline bool operator==(const COWReference<T>& a, const COWReference<U>& b)
337 {
338  return a.getPtr() == b.getPtr();
339 }
341 template <class T, class U>
342 inline bool operator!=(const COWReference<T>& a, const COWReference<U>& b)
343 {
344  return a.getPtr() != b.getPtr();
345 }
347 template <class T, class U>
348 inline bool operator<(const COWReference<T>& a, const COWReference<U>& b)
349 {
350  return a.getPtr() < b.getPtr();
351 }
352 
354 template <class T>
355 inline 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_