wxArt2D
smrtptr.h
Go to the documentation of this file.
1 /*! \file wx/general/smrtptr.h
2  \brief smart pointer class and list.
3 
4  Smart pointers are used all over wxDocview, and the a2dObject from which most classes are derived
5  (in)directly is for that reason reference counted.
6 
7  \author Michael Sögtrop / Klaas Holwerda
8  \date Created 10/29/2003
9 
10  Copyright: 2003-2004 (c) Michael Sögtrop / Klaas Holwerda
11 
12  Licence: wxWidgets Licence
13 
14  RCS-ID: $Id: smrtptr.h,v 1.21 2008/09/05 19:01:13 titato Exp $
15 */
16 
17 #ifndef __SMRTPTR_H__
18 #define __SMRTPTR_H__
19 
20 #include <string.h>
21 #include <wx/general/a2dlist.h>
22 
23 // Enable smart pointer / reference counter debugging
24 //#define SMART_POINTER_DEBUG
25 #define __A2DONLYFILE__(fname) (strchr(fname,'\\') ? strrchr(fname,'\\')+1 : fname)
26 #define __A2DFILE__ __A2DONLYFILE__(__FILE__)
27 
28 
29 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
30 // This is used as a hint which object a smart pointer might be a member of
31 // All objects that contain smart pointer as members should set this in the
32 // constructor of their base class (In the constructor itself it would be
33 // to late, because the smart pointer constructor for members is called before
34 // the constructor body is executed.
35 // You can of course also set m_owner and m_ownertype directly in the constructor
36 // after constructing the smart pointer object.
37 A2DGENERALDLLEXP_DATA ( extern wxObject* ) CurrentSmartPointerOwner;
38 
39 struct A2DGENERALDLLEXP a2dInitCurrentSmartPointerOwner
40 {
41 public:
42  a2dInitCurrentSmartPointerOwner( wxObject* object )
43  {
44  CurrentSmartPointerOwner = object;
45  }
46 };
47 #endif
48 
49 //! A trivial base class for a2dSmrtPtr. Non-template class, so that it can
50 /*! be made a friend class of a2dObject and avoid noncompliance problems with
51  friend templates.
52 
53  \ingroup general
54 */
55 class A2DGENERALDLLEXP a2dSmrtPtrBase
56 {
57 protected:
58  a2dSmrtPtrBase() {}
59 private:
60  a2dSmrtPtrBase( const a2dSmrtPtrBase& ); // Noncopyable; do not implement.
61  a2dSmrtPtrBase& operator=( const a2dSmrtPtrBase& ); // Noncopyable; do not implement.
62 protected:
63  template<class T> static void OwnRef( T* pRefObject ) { if( pRefObject ) pRefObject->SmrtPtrOwn(); }
64  template<class T> static void ReleaseRef( T* pRefObject ) { if( pRefObject ) pRefObject->SmrtPtrRelease(); }
65 };
66 
67 
68 //! A pointer class, that automatically calls SmrtPtrOwn/SmrtPtrRelease
69 /*! a2dSmrtPtr is a template class, that performs automatic reference counting.
70  It can be used like a usual C++ pointer.
71  It can be used for any class, that has SmrtPtrOwn and SmrtPtrRelease functions, like this:
72 
73 <code>
74  class XXX
75  private:
76 
77  // how many references to this object do exist
78  int m_refcount;
79 
80  // Call to have a new owner for this object
81  // This function should only be called by a2dSmrtPtr
82  //
83  // \remark owning mean that the object calling this member needs to call Release at some time,
84  // in order to actually release/delete the object.
85  //
86  // \return The return value is the object itself, which is now owned on time extra.
87  //
88  // increment refcount by 1 ( use when adding a reference to this object)
89  //
90  a2dLineSegment* SmrtPtrOwn() { m_refcount++; return this; }
91 
92  // To release the object, it is not longer owned by the calling object.
93  // This function should only be called by a2dSmrtPtr
94  bool SmrtPtrRelease()
95  {
96  m_refcount--;
97  wxASSERT_MSG( m_refcount >= 0, wxT("XXX object Own/Release not matched (extra Release calls)") );
98  if ( m_refcount <= 0 )
99  {
100  delete this;
101  return true;
102  }
103  return false;
104  }
105 
106  private:
107  friend class a2dSmrtPtrBase;
108 </code>
109 
110  \ingroup general
111 
112 */
113 template<class Clss>
114 class a2dSmrtPtr : private a2dSmrtPtrBase
115 {
116 public:
117  typedef Clss TType;
118 
119  a2dSmrtPtr()
120  {
121  m_ptr = NULL;
122  PointerListInit();
123  }
124 
125  a2dSmrtPtr( Clss* objc )
126  {
127  PointerListInit();
128  m_ptr = objc;
129  AddToPointerList();
130  OwnRef( m_ptr );
131  }
132 
133  a2dSmrtPtr( const a2dSmrtPtr& objc )
134  {
135  PointerListInit();
136  m_ptr = &*objc;
137  AddToPointerList();
138  OwnRef( m_ptr );
139  }
140 
141  ~a2dSmrtPtr()
142  {
143  // It is required to set m_ptr to 0 in case the destructor of the target
144  // object tries to set the pointer in this object to
145  Clss* old = m_ptr;
146  RmvFromPointerList();
147  m_ptr = 0;
148  ReleaseRef( old );
149  }
150 
151  void operator=( const a2dSmrtPtr& objc )
152  {
153  Clss* ptrold = m_ptr;
154  RmvFromPointerList();
155  m_ptr = &*objc;
156  AddToPointerList();
157  OwnRef( m_ptr );
158  ReleaseRef( ptrold );
159  }
160 
161  void operator=( Clss* objc )
162  {
163  Clss* ptrold = m_ptr;
164  RmvFromPointerList();
165  m_ptr = objc;
166  AddToPointerList();
167  OwnRef( m_ptr );
168  ReleaseRef( ptrold );
169  }
170 
171  friend inline bool operator==( const a2dSmrtPtr& a, const a2dSmrtPtr& b )
172  {
173  return a.m_ptr == b.m_ptr;
174  }
175 
176  friend inline bool operator!=( const a2dSmrtPtr& a, const a2dSmrtPtr& b )
177  {
178  return a.m_ptr != b.m_ptr;
179  }
180 
181  // This is needed, because otherwise the compiler doesnt know if he
182  // should use (Clss*)a == b or a==wxSmtrPtr<Clss>(b)
183  friend inline bool operator==( const a2dSmrtPtr& a, const Clss* b )
184  {
185  return a.m_ptr == b;
186  }
187 
188  friend inline bool operator!=( const a2dSmrtPtr& a, const Clss* b )
189  {
190  return a.m_ptr != b;
191  }
192 
193  friend inline bool operator==( const Clss* a, const a2dSmrtPtr& b )
194  {
195  return a == b.m_ptr;
196  }
197 
198  friend inline bool operator!=( const Clss* a, const a2dSmrtPtr& b )
199  {
200  return a != b.m_ptr;
201  }
202 
203  friend inline bool operator==( const a2dSmrtPtr& a, Clss* b )
204  {
205  return a.m_ptr == b;
206  }
207 
208  friend inline bool operator!=( const a2dSmrtPtr& a, Clss* b )
209  {
210  return a.m_ptr != b;
211  }
212 
213  friend inline bool operator==( Clss* a, const a2dSmrtPtr& b )
214  {
215  return a == b.m_ptr;
216  }
217 
218  friend inline bool operator!=( Clss* a, const a2dSmrtPtr& b )
219  {
220  return a != b.m_ptr;
221  }
222 
223  inline operator Clss* () const { return m_ptr; }
224 
225  inline Clss* Get() const
226  {
227  return m_ptr;
228  }
229 
230  inline Clss* operator->() const { /* !!!!! a throw on 0 should go here */ return m_ptr; }
231 
232  inline Clss& operator*() const { /* !!!!! a throw on 0 should go here */ return *m_ptr; }
233 
234 private:
235  Clss* m_ptr;
236 
237 public:
238 
239 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
240  a2dSmrtPtr( const wxChar* filename, int linenum )
241  {
242  m_ptr = NULL;
243  PointerListInit();
244  m_filename = filename;
245  m_linenum = linenum;
246  }
247  a2dSmrtPtr( const wxChar* filename, int linenum, Clss* objc )
248  {
249  PointerListInit();
250  m_filename = filename;
251  m_linenum = linenum;
252  m_ptr = objc;
253  AddToPointerList();
254  OwnRef( m_ptr );
255  }
256  a2dSmrtPtr( const wxChar* filename, int linenum, const a2dSmrtPtr& objc )
257  {
258  PointerListInit();
259  m_filename = filename;
260  m_linenum = linenum;
261  m_ptr = &*objc;
262  AddToPointerList();
263  OwnRef( m_ptr );
264  }
265 
266  //! This is a double linkes list of all pointers to an object
267  /*! This is only used for debugging */
268  a2dSmrtPtr<Clss> *m_next;
269  a2dSmrtPtr<Clss> *m_prvs;
270  wxObject* m_owner;
271  const wxChar* m_filename;
272  int m_linenum;
273  enum
274  {
275  owner_none,
276  owner_wxobject,
277  owner_smartpointerlist
278  } m_ownertype;
279 
280  void PointerListInit()
281  {
282  // see CurrentSmartPointerOwner comment
283 
284  m_next = 0;
285  m_prvs = 0;
286  m_filename = 0;
287  m_linenum = 0;
288  // objects tend to be smaller than 1k
289  if( ( char* )this - ( char* )CurrentSmartPointerOwner < 1024 )
290  {
291  m_owner = CurrentSmartPointerOwner;
292  m_ownertype = owner_wxobject;
293  }
294  else
295  {
296  m_owner = 0;
297  m_ownertype = owner_none;
298  }
299  }
300 
301  void AddToPointerList()
302  {
303  if( !m_ptr ) return;
304  m_next = ( a2dSmrtPtr<Clss>* ) m_ptr->m_ownerlist;
305  if( m_next )
306  m_next->m_prvs = this;
307  m_prvs = 0;
308  m_ptr->m_ownerlist = ( typename Clss::TOwnerListClass* ) this;
309  }
310 
311  void RmvFromPointerList()
312  {
313  if( !m_ptr ) return;
314  if( m_prvs )
315  m_prvs->m_next = m_next;
316  else
317  m_ptr->m_ownerlist = ( typename Clss::TOwnerListClass* ) m_next;
318  if( m_next )
319  m_next->m_prvs = m_prvs;
320  }
321 #else
322  void PointerListInit() {}
323  void AddToPointerList() {}
324  void RmvFromPointerList() {}
325 #endif
326 };
327 
328 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
329 #define a2dDECLARE_GLOBAL_VAR(type, var) type var(__FILE__,__LINE__)
330 #define a2dDECLARE_GLOBAL_ITEM(type, var, item) type var(__FILE__,__LINE__,item)
331 #define a2dDECLARE_LOCAL_ITEM(type, var, item) CurrentSmartPointerOwner = this;\
332  type var(__FILE__,__LINE__,item)
333 #else
334 #define a2dDECLARE_GLOBAL_VAR(type, var) type var
335 #define a2dDECLARE_GLOBAL_ITEM(type, var, item) type var(item)
336 #define a2dDECLARE_LOCAL_ITEM(type, var, item) type var(item)
337 #endif
338 
339 //! A pointer class, that is automatically set to 0 if the target is deleted
340 /*! The target keeps a list of all auto zero smart pointers pointing to it.
341 
342  For e.g. a2dObject, this list is implemented as a property.
343 
344  \ingroup general
345 */
346 template<class Clss>
348 {
349 public:
350  typedef Clss TType;
351 
353  {
354  m_ptr = NULL;
355  PointerListInit();
356  }
357 
358  a2dAutoZeroPtr( Clss* objc )
359  {
360  PointerListInit();
361  m_ptr = objc;
362  AddToPointerList();
363  }
364 
365  a2dAutoZeroPtr( const a2dAutoZeroPtr& objc )
366  {
367  PointerListInit();
368  m_ptr = &*objc;
369  AddToPointerList();
370  }
371 
372  ~a2dAutoZeroPtr()
373  {
374  RmvFromPointerList();
375  }
376 
377  //! This is called from the targets destructor
378  /*! It is safe to call this function with a zero this pointer */
380  {
381  a2dAutoZeroPtr<Clss> *next, *crnt;
382  for( crnt = this; crnt; crnt = next )
383  {
384  next = crnt->m_next;
385  crnt->m_ptr = 0;
386  crnt->m_next = 0;
387  crnt->m_prvs = 0;
388  }
389  }
390 
391  void operator=( const a2dAutoZeroPtr& objc )
392  {
393  RmvFromPointerList();
394  m_ptr = &*objc;
395  AddToPointerList();
396  }
397 
398  void operator=( Clss* objc )
399  {
400  RmvFromPointerList();
401  m_ptr = objc;
402  AddToPointerList();
403  }
404 
405  friend inline bool operator==( const a2dAutoZeroPtr& a, const a2dAutoZeroPtr& b )
406  {
407  return a.m_ptr == b.m_ptr;
408  }
409 
410  friend inline bool operator!=( const a2dAutoZeroPtr& a, const a2dAutoZeroPtr& b )
411  {
412  return a.m_ptr != b.m_ptr;
413  }
414 
415  // This is needed, because otherwise the compiler doesnt know if he
416  // should use (Clss*)a == b or a==wxSmtrPtr<Clss>(b)
417  friend inline bool operator==( const a2dAutoZeroPtr& a, const Clss* b )
418  {
419  return a.m_ptr == b;
420  }
421 
422  friend inline bool operator!=( const a2dAutoZeroPtr& a, const Clss* b )
423  {
424  return a.m_ptr != b;
425  }
426 
427  friend inline bool operator==( const Clss* a, const a2dAutoZeroPtr& b )
428  {
429  return a == b.m_ptr;
430  }
431 
432  friend inline bool operator!=( const Clss* a, const a2dAutoZeroPtr& b )
433  {
434  return a != b.m_ptr;
435  }
436 
437  friend inline bool operator==( const a2dAutoZeroPtr& a, Clss* b )
438  {
439  return a.m_ptr == b;
440  }
441 
442  friend inline bool operator!=( const a2dAutoZeroPtr& a, Clss* b )
443  {
444  return a.m_ptr != b;
445  }
446 
447  friend inline bool operator==( Clss* a, const a2dAutoZeroPtr& b )
448  {
449  return a == b.m_ptr;
450  }
451 
452  friend inline bool operator!=( Clss* a, const a2dAutoZeroPtr& b )
453  {
454  return a != b.m_ptr;
455  }
456 
457  inline operator Clss* () const { return m_ptr; }
458 
459  inline Clss* Get() const
460  {
461  return m_ptr;
462  }
463 
464  inline Clss* operator->() const { /* !!!!! a throw on 0 should go here */ return m_ptr; }
465 
466  inline Clss& operator*() const { /* !!!!! a throw on 0 should go here */ return *m_ptr; }
467 
468 private:
469  //! Initialize the pointer list pointers
470  void PointerListInit()
471  {
472  m_next = 0;
473  m_prvs = 0;
474  // objects tend to be smaller than 1k
475  }
476  //! Add this pointer to the pointer list of the target
477  void AddToPointerList()
478  {
479  if( !m_ptr ) return;
480  a2dAutoZeroPtr<Clss> **ownerlist = ( a2dAutoZeroPtr<Clss>** ) m_ptr->GetAutoZeroPtrList();
481  m_next = *ownerlist;
482  if( m_next )
483  m_next->m_prvs = this;
484  m_prvs = 0;
485  *ownerlist = ( a2dAutoZeroPtr<Clss>* ) this;
486  }
487  //! Remove this pointer from the pointer list of the target
488  void RmvFromPointerList()
489  {
490  if( !m_ptr ) return;
491  if( m_prvs )
492  {
493  m_prvs->m_next = m_next;
494  }
495  else
496  {
497  a2dAutoZeroPtr<Clss> **ownerlist = ( a2dAutoZeroPtr<Clss>** ) m_ptr->GetAutoZeroPtrList();
498  *ownerlist = ( a2dAutoZeroPtr<Clss>* ) m_next;
499  }
500  if( m_next )
501  m_next->m_prvs = m_prvs;
502  }
503 
504 private:
505  Clss* m_ptr;
506 
507  //! This is a double linked list of all pointers to an object
508  /*! This is only used for debugging */
509  a2dAutoZeroPtr<Clss> *m_next;
510  a2dAutoZeroPtr<Clss> *m_prvs;
511 };
512 
513 //! A pointer class, that does not call SmrtPtrOwn/SmrtPtrRelease, but initializes to 0
514 /*!
515  \ingroup general
516 */
517 template<class Clss>
519 {
520 public:
521  typedef Clss TType;
522 
523  a2dDumbPtr()
524  {
525  m_ptr = NULL;
526  }
527 
528  a2dDumbPtr( Clss* objc )
529  {
530  m_ptr = objc;
531  }
532 
533  a2dDumbPtr( const a2dDumbPtr& objc )
534  {
535  m_ptr = &*objc;
536  }
537 
538  void operator=( const a2dDumbPtr& objc )
539  {
540  m_ptr = &*objc;
541  }
542 
543  friend inline bool operator==( const a2dDumbPtr& a, const a2dDumbPtr& b )
544  {
545  return a.m_ptr == b.m_ptr;
546  }
547 
548  friend inline bool operator!=( const a2dDumbPtr& a, const a2dDumbPtr& b )
549  {
550  return a.m_ptr != b.m_ptr;
551  }
552 
553  // This is needed, because otherwise the compiler doesnt know if he
554  // should use (Clss*)a == b or a==wxSmtrPtr<Clss>(b)
555  friend inline bool operator==( const a2dDumbPtr& a, const Clss* b )
556  {
557  return a.m_ptr == b;
558  }
559 
560  friend inline bool operator!=( const a2dDumbPtr& a, const Clss* b )
561  {
562  return a.m_ptr != b;
563  }
564 
565  friend inline bool operator==( const Clss* a, const a2dDumbPtr& b )
566  {
567  return a == b.m_ptr;
568  }
569 
570  friend inline bool operator!=( const Clss* a, const a2dDumbPtr& b )
571  {
572  return a != b.m_ptr;
573  }
574 
575  friend inline bool operator==( const a2dDumbPtr& a, Clss* b )
576  {
577  return a.m_ptr == b;
578  }
579 
580  friend inline bool operator!=( const a2dDumbPtr& a, Clss* b )
581  {
582  return a.m_ptr != b;
583  }
584 
585  friend inline bool operator==( Clss* a, const a2dDumbPtr& b )
586  {
587  return a == b.m_ptr;
588  }
589 
590  friend inline bool operator!=( Clss* a, const a2dDumbPtr& b )
591  {
592  return a != b.m_ptr;
593  }
594 
595  inline operator Clss* () const { return m_ptr; }
596 
597  ~a2dDumbPtr()
598  {
599  }
600 
601  inline Clss* Get() const
602  {
603  return m_ptr;
604  }
605 
606  inline Clss* operator->() const { /* !!!!! a throw on 0 should go here */ return m_ptr; }
607 
608  inline Clss& operator*() const { /* !!!!! a throw on 0 should go here */ return *m_ptr; }
609 
610 private:
611  Clss* m_ptr;
612 };
613 
614 
615 
616 //! A list class for reference counted objects
617 /*! The list uses a2dSmrtPtr for reference counting,
618  and therefore objects which reach refcount zero will be deleted automatically.
619 
620  \ingroup general
621 */
622 template<class T>
623 class a2dDumbPtrList: public a2dlist< a2dDumbPtr< T > >
624 {
625 
626 public:
627 
628  typedef typename a2dlist< a2dDumbPtr< T > >::iterator itSmart;
629  typedef typename a2dlist< a2dDumbPtr< T > >::const_iterator const_itSmart;
630 
631  //! Find a specific object
632  itSmart Find( T* object );
633 
634  //! Find a specific object
635  const_itSmart Find( T* object ) const;
636 
637  //! Find the index of a specific object
638  int IndexOf( T* object ) const;
639 
640  //! release a certain object from the list
641  bool RemoveObject( T* object );
642 
643 };
644 
645 
646 //! A list class for reference counted objects
647 /*! The list uses a2dSmrtPtr for reference counting,
648  and therefore objects which reach refcount zero will be deleted automatically.
649 
650  \ingroup general
651 */
652 template<class T>
653 class a2dSmrtPtrList: public a2dlist< a2dSmrtPtr< T > >
654 {
655 
656 public:
657 
658  typedef typename a2dlist< a2dSmrtPtr< T > >::iterator itSmart;
659  typedef typename a2dlist< a2dSmrtPtr< T > >::const_iterator const_itSmart;
660 
661  //! Find a specific object
662  itSmart Find( T* object );
663 
664  //! Find a specific object
665  const_itSmart Find( T* object ) const;
666 
667  //! Find the index of a specific object
668  int IndexOf( T* object ) const;
669 
670  //! release a certain object from the list
671  bool ReleaseObject( T* object );
672 
673 };
674 
675 #if defined(WXDOCVIEW_USINGDLL)
676 #include "wx/general/smrtptr.inl"
677 #endif
678 
679 #endif // __SMRTPTR_H__
A trivial base class for a2dSmrtPtr. Non-template class, so that it can.
Definition: smrtptr.h:55
see wx/general/smrtptr.h
int IndexOf(T *object) const
Find the index of a specific object.
Definition: smrtptr.inl:46
std list compatible list
Definition: a2dlist.h:42
itSmart Find(T *object)
Find a specific object.
Definition: smrtptr.inl:19
A pointer class, that is automatically set to 0 if the target is deleted.
Definition: smrtptr.h:347
A list class for reference counted objects.
Definition: smrtptr.h:623
basic list class based on STL containers.
bool RemoveObject(T *object)
release a certain object from the list
Definition: smrtptr.inl:61
bool ReleaseObject(T *object)
release a certain object from the list
Definition: smrtptr.inl:118
void TargetDestructing()
This is called from the targets destructor.
Definition: smrtptr.h:379
A pointer class, that does not call SmrtPtrOwn/SmrtPtrRelease, but initializes to 0...
Definition: smrtptr.h:518
A list class for reference counted objects.
Definition: smrtptr.h:653
itSmart Find(T *object)
Find a specific object.
Definition: smrtptr.inl:76
A pointer class, that automatically calls SmrtPtrOwn/SmrtPtrRelease.
Definition: a2dlist.h:20
int IndexOf(T *object) const
Find the index of a specific object.
Definition: smrtptr.inl:103
smrtptr.h Source File -- Sun Oct 12 2014 17:04:23 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation