SmartPtr.h
1 /*
2  * Copyright (C) 2006 by Tommi Maekitalo
3  * Copyright (C) 2006 by Marc Boris Duerner
4  * Copyright (C) 2006 by Stefan Bueder
5  * Copyright (C) 2010-2010 by Aloysius Indrayanto
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * As a special exception, you may use this file as part of a free
13  * software library without restriction. Specifically, if other files
14  * instantiate templates or use macros or inline functions from this
15  * file, or you compile this file and link it with other files to
16  * produce an executable, this file does not by itself cause the
17  * resulting executable to be covered by the GNU General Public
18  * License. This exception does not however invalidate any other
19  * reasons why the executable file might be covered by the GNU Library
20  * General Public License.
21  *
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25  * Lesser General Public License for more details.
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31 
32 #ifndef PT_SMARTPTR_H
33 #define PT_SMARTPTR_H
34 
35 #include <Pt/Api.h>
36 #include <Pt/Atomicity.h>
37 #include <Pt/SerializationInfo.h>
38 
39 namespace Pt {
40 
49 template <typename T>
50 class RefLinked
51 {
52  private:
53  mutable const RefLinked* prev;
54  mutable const RefLinked* next;
55 
56  protected:
59  : prev(0),
60  next(0)
61  { }
62 
64  bool unlink(T* object)
65  {
66  bool ret = false;
67  if (object)
68  {
69  if (next == this)
70  {
71  ret = true;
72  }
73  else
74  {
75  next->prev = prev;
76  prev->next = next;
77  }
78  next = prev = this;
79  }
80  return ret;
81  }
82 
84  void link(const RefLinked& ptr, T* object)
85  {
86  if (object)
87  {
88  prev = &ptr;
89  next = ptr.next;
90  prev->next = this;
91  next->prev = this;
92  }
93  }
94 };
95 
106 template <typename T>
107 class InternalRefCounted
108 {
109  protected:
111  bool unlink(T* object)
112  {
113  if (object)
114  object->release();
115  return false;
116  }
117 
119  void link(const InternalRefCounted& ptr, T* object)
120  {
121  if (object)
122  object->addRef();
123  }
124 };
125 
126 
134 template <typename T>
136 {
137  public:
139  int refs() const
140  { return _count ? *_count : 0; }
141 
142  protected:
145  : _count(0)
146  { }
147 
149  bool unlink(T* object)
150  {
151  if ( _count && --*_count <= 0)
152  {
153  delete _count;
154  // no need to set _count to 0 since the pointer is either
155  // destroyed or another object is linked in
156  return true;
157  }
158  else
159  return false;
160  }
161 
163  void link(const ExternalRefCounted& ptr, T* object)
164  {
165  if(object)
166  {
167  if(ptr._count == 0) {
168  _count = new unsigned(1);
169  }
170  else
171  {
172  _count = ptr._count;
173  ++*_count;
174  }
175  }
176  else
177  _count = 0;
178  }
179 
180  private:
181  unsigned* _count;
182 };
183 
184 
185 template <typename T>
186 class ExternalAtomicRefCounted
187 {
188  public:
189  int refs() const
190  { return rc ? atomicGet(*rc) : 0; }
191 
192  protected:
193  ExternalAtomicRefCounted()
194  : rc(0)
195  { }
196 
197  bool unlink(T* object)
198  {
199  if (object && atomicDecrement(*rc) <= 0)
200  {
201  delete rc;
202  // no need to set rc to 0 since the pointer is either
203  // destroyed or another object is linked in
204  return true;
205  }
206  else
207  return false;
208  }
209 
210  void link(const ExternalAtomicRefCounted& ptr, T* object)
211  {
212  if (object)
213  {
214  if (ptr.rc == 0)
215  rc = new atomic_t(1);
216  else
217  {
218  rc = ptr.rc;
219  atomicIncrement(*rc);
220  }
221  }
222  else
223  rc = 0;
224  }
225 
226  private:
227  volatile atomic_t* rc;
228 };
229 
239 template <typename T>
241 {
242  protected:
243  static void destroy(T* ptr)
244  { delete ptr; }
245 };
246 
247 
248 template <typename T>
249 class FreeDestroyPolicy
250 {
251  protected:
252  void destroy(T* ptr)
253  { free(ptr); }
254 };
255 
256 
257 template <typename ObjectType>
258 class ArrayDestroyPolicy
259 {
260  protected:
261  static void destroy(ObjectType* ptr)
262  { delete[] ptr; }
263 };
264 
265 
266 template<typename T>
267 struct AutoPtrRef
268 {
269  T* ptr;
270 
271  explicit AutoPtrRef(T* rhs)
272  : ptr(rhs)
273  { }
274 };
275 
276 
288 template<typename T,
289  typename Destroy = DeletePolicy<T> >
290 class AutoPtr : public Destroy
291 {
292  public:
293  typedef T element_type;
294 
295  public:
297  explicit AutoPtr(T* ptr = 0)
298  : ap(ptr)
299  { }
300 
302  AutoPtr(AutoPtrRef<T> rhs)
303  : ap(rhs.ptr) {
304  }
305 
307  AutoPtr& operator= (AutoPtrRef<T> rhs)
308  {
309  reset(rhs.ptr);
310  return *this;
311  }
312 
315  { this->destroy(ap); }
316 
318  template<class Y>
319  operator AutoPtrRef<Y>()
320  {
321  return AutoPtrRef<Y>( release() );
322  }
323 
325  T* get() const {
326  return ap;
327  }
328 
330  T& operator*() const {
331  return *ap;
332  }
333 
335  T* operator->() const
336  {
337  return ap;
338  }
339 
341  bool operator!() const
342  {
343  return ap == 0;
344  }
345 
353  operator bool () const
354  { return ap != 0; }
355 
357  T* release()
358  {
359  T* tmp(ap);
360  ap = 0;
361  return tmp;
362  }
363 
365  void reset(T* ptr = 0)
366  {
367  if (ap != ptr)
368  {
369  this->destroy(ap);
370  ap = ptr;
371  }
372  }
373 
374  private:
375  AutoPtr(AutoPtr &p);
376 
378 
379  private:
380  T* ap;
381 };
382 
383 template <typename T>
384 AutoPtr<T> move(AutoPtr<T>& p)
385 {
386  return AutoPtr<T>( AutoPtrRef<T>(p) );
387 }
388 
393 template <typename T, typename D, typename T2, typename D2>
394 bool operator==(const AutoPtr<T, D>& a, const AutoPtr<T2, D2>& b)
395 { return a.get() == b.get(); }
396 
401 template <typename T, typename D, typename T2>
402 bool operator==(const AutoPtr<T, D>& a, const T2* b)
403 { return a.get() == b; }
404 
405 
410 template <typename T, typename D, typename T2, typename D2>
411 bool operator!=(const AutoPtr<T, D>& a, const AutoPtr<T2, D2>& b)
412 { return a.get() != b.get(); }
413 
418 template <typename T, typename D, typename T2>
419 bool operator!=(const AutoPtr<T, D>& a, const T2* b)
420 { return a.get() != b; }
421 
422 
427 template <typename T, typename D, typename T2, typename D2>
428 bool operator<(const AutoPtr<T, D>& a, const AutoPtr<T2, D2>& b)
429 { return a.v() < b.get(); }
430 
435 template <typename T, typename D, typename T2>
436 bool operator<(const AutoPtr<T, D>& a, const T2* b)
437 { return a.get() < b; }
438 
439 
457 template <typename T,
458  typename OwnershipPolicy = ExternalRefCounted<T>,
459  typename DestroyPolicy = DeletePolicy<T> >
460 class SmartPtr : public OwnershipPolicy,
461  public DestroyPolicy
462 {
463  private:
465  T* object;
466 
467  public:
473  : object(0)
474  {}
475 
478  explicit SmartPtr(T* ptr)
479  : object(ptr)
480  { this->link(*this, ptr); }
481 
484  SmartPtr(const SmartPtr& ptr)
485  : object(ptr.object)
486  { this->link(ptr, ptr.object); }
487 
491  {
492  if (this->unlink(object))
493  this->destroy(object);
494  }
495 
499  {
500  if(object == ptr.object)
501  return *this;
502 
503  if( this->unlink(object) )
504  this->destroy(object);
505 
506  object = ptr.object;
507 
508  this->link(ptr, object);
509 
510  return *this;
511  }
512 
513  void reset(T* ptr = 0)
514  {
515  if(object == ptr)
516  return;
517 
518  if( this->unlink(object) )
519  this->destroy(object);
520 
521  object = ptr;
522 
523  this->link(*this, object);
524  }
525 
528  T* operator->() const
529  { return object; }
530 
533  T& operator*() const
534  { return *object; }
535 
538  bool operator! () const
539  { return object == 0; }
540 
543  operator bool () const
544  { return object != 0; }
545 
548  T* get()
549  { return object; }
550 
553  const T* get() const
554  { return object; }
555 };
556 
557 
562 template <typename T, class O, typename D, typename T2, typename O2, typename D2>
564 { return a.get() == b.get(); }
565 
570 template <typename T, typename O, typename D, typename T2>
571 bool operator==(const SmartPtr<T, O, D>& a, const T2* b)
572 { return a.get() == b; }
573 
574 
579 template <typename T, typename O, typename D, typename T2, typename O2, typename D2>
581 { return a.get() != b.get(); }
582 
587 template <typename T, typename O, typename D, typename T2>
588 bool operator!=(const SmartPtr<T, O, D>& a, const T2* b)
589 { return a.get() != b; }
590 
591 
596 template <typename T, typename O, typename D, typename T2, typename O2, typename D2>
597 bool operator<(const SmartPtr<T, O, D>& a, const SmartPtr<T2, O2, D2>& b)
598 { return a.get() < b.get(); }
599 
604 template <typename T, typename O, typename D, typename T2>
605 bool operator<(const SmartPtr<T, O, D>& a, const T2* b)
606 { return a.get() < b; }
607 
608 
613 template <typename T, typename M, typename D >
614 void fixup(const Pt::FixupInfo& fixup, SmartPtr<T, M, D>& fixme)
615 {
616  if( fixup.isNull() )
617  {
618  fixme = SmartPtr<T,M, D>();
619  }
620  else
621  {
622  const SmartPtr<T,M, D>* to = fixup.getTarget< SmartPtr<T, M, D> >();
623  fixme = *to;
624  }
625 }
626 
631 template <typename T, typename M, typename D >
632 void load(const LoadInfo& li, SmartPtr<T, M, D>& sp)
633 {
634  if( li.in().isReference() )
635  {
636  li.in().loadReference(sp);
637  }
638  else
639  {
640  li.load(sp);
641  }
642 }
643 
648 template <typename T, typename M>
649 void operator >>=(const Pt::SerializationInfo& si, SmartPtr<T, M>& sp)
650 {
651  sp.reset( new T() );
652  si >>= *sp;
653 }
654 
659 template <typename T, typename M, typename D >
660 void save(Pt::SaveInfo& si, const SmartPtr<T, M, D>& sp)
661 {
662  if( ! sp.get() || ! si.save( *sp ) )
663  {
664  si.out() <<= sp.get();
665  }
666 }
667 
672 template <typename T, typename M, typename D >
673 void operator <<=(Pt::SerializationInfo& si, const SmartPtr<T, M, D>& sp)
674 {
675  if( sp.getPointer() )
676  {
677  si <<= *sp;
678  }
679  else
680  {
681  si <<= sp.getPointer();
682  }
683 }
684 
685 } // namespace Pt
686 
687 #endif // PT_SMARTPTR_H
ExternalRefCounted()
Default constructor.
Definition: SmartPtr.h:144
Policy based smart pointer.
Definition: SmartPtr.h:460
bool operator!=(const SmartPtr< T, O, D > &a, const T2 *b)
Equality comparison operator.
Definition: SmartPtr.h:588
T * get() const
Access value.
Definition: SmartPtr.h:325
SerializationInfo & out() const
Returns the SerializationInfo to save to.
Definition: SerializationInfo.h:848
Loads referencable types.
Definition: SerializationInfo.h:911
SmartPtr(T *ptr)
Constructs from a pointer to manage.
Definition: SmartPtr.h:478
T * operator->() const
Access value.
Definition: SmartPtr.h:335
T * getTarget() const
Returns a pointer to the refernced type.
Definition: FixupInfo.h:81
Non-intrusive reference counting for SmartPtr.
Definition: SmartPtr.h:135
Fixup of references during serialization.
Definition: FixupInfo.h:42
bool isReference() const
Returns true if reference.
Definition: SerializationInfo.h:168
RefLinked()
Default constructor.
Definition: SmartPtr.h:58
bool operator==(const AutoPtr< T, D > &a, const AutoPtr< T2, D2 > &b)
Equality comparison operator.
Definition: SmartPtr.h:394
bool operator!() const
Returns true if the raw pointer is null.
Definition: SmartPtr.h:538
const SerializationInfo & in() const
Returns the SerializationInfo to load from.
Definition: SerializationInfo.h:921
bool operator!=(const AutoPtr< T, D > &a, const T2 *b)
Equality comparison operator.
Definition: SmartPtr.h:419
void save(Pt::SaveInfo &si, const SmartPtr< T, M, D > &sp)
Custom saving for serialization.
Definition: SmartPtr.h:660
void reset(T *ptr=0)
Reset value.
Definition: SmartPtr.h:365
T * get()
Get non-owning pointer.
Definition: SmartPtr.h:548
SmartPtr(const SmartPtr &ptr)
Copy constructor.
Definition: SmartPtr.h:484
T & operator*() const
Access value.
Definition: SmartPtr.h:330
SmartPtr & operator=(const SmartPtr &ptr)
Assign from another SmartPtr.
Definition: SmartPtr.h:498
AutoPtr(T *ptr=0)
Default constructor.
Definition: SmartPtr.h:297
bool operator==(const SmartPtr< T, O, D > &a, const T2 *b)
Equality comparison operator.
Definition: SmartPtr.h:571
~SmartPtr()
Destructor.
Definition: SmartPtr.h:490
T * operator->() const
Access value.
Definition: SmartPtr.h:528
T * release()
Release ownership.
Definition: SmartPtr.h:357
bool operator!=(const SmartPtr< T, O, D > &a, const SmartPtr< T2, O2, D2 > &b)
Equality comparison operator.
Definition: SmartPtr.h:580
bool save(const T &type)
Returns true if type was saved, false if type was already saved.
Definition: SerializationInfo.h:854
bool unlink(T *object)
unlink a smart pointer from a managed object
Definition: SmartPtr.h:149
Saves referencable types.
Definition: SerializationInfo.h:838
void fixup(const Pt::FixupInfo &fixup, SmartPtr< T, M, D > &fixme)
Custom fixup for deserialization.
Definition: SmartPtr.h:614
void load(const LoadInfo &li, SmartPtr< T, M, D > &sp)
Custom loading for deserialization.
Definition: SmartPtr.h:632
bool operator==(const SmartPtr< T, O, D > &a, const SmartPtr< T2, O2, D2 > &b)
Equality comparison operator.
Definition: SmartPtr.h:563
void link(const ExternalRefCounted &ptr, T *object)
link a smart pointer to a managed object
Definition: SmartPtr.h:163
~AutoPtr()
Destructor.
Definition: SmartPtr.h:314
AutoPtr & operator=(AutoPtrRef< T > rhs)
Assignment operator.
Definition: SmartPtr.h:307
bool isNull() const
Returns true if null.
Definition: FixupInfo.h:76
void load(T &type) const
Loads the type.
Definition: SerializationInfo.h:927
bool unlink(T *object)
Unlink a smart pointer from a managed object.
Definition: SmartPtr.h:64
SmartPtr()
Default Constructor.
Definition: SmartPtr.h:472
bool operator!() const
Returns true if nullptr.
Definition: SmartPtr.h:341
Represents arbitrary types during serialization.
Definition: SerializationInfo.h:58
void loadReference(T &fixme, unsigned mid=0) const
Load a reference during deserialization.
Definition: SerializationInfo.h:575
bool operator!=(const AutoPtr< T, D > &a, const AutoPtr< T2, D2 > &b)
Equality comparison operator.
Definition: SmartPtr.h:411
int refs() const
Returns the refcount.
Definition: SmartPtr.h:139
bool operator==(const AutoPtr< T, D > &a, const T2 *b)
Equality comparison operator.
Definition: SmartPtr.h:402
Reference linking policy for SmartPtr.
Definition: SmartPtr.h:50
Policy based Auto pointer.
Definition: SmartPtr.h:290
Deleter policy for SmartPtr.
Definition: SmartPtr.h:240
AutoPtr(AutoPtrRef< T > rhs)
Copy constructor.
Definition: SmartPtr.h:302
void link(const RefLinked &ptr, T *object)
Link a smart pointer to a managed object.
Definition: SmartPtr.h:84
T & operator*() const
Access value.
Definition: SmartPtr.h:533