Medical Imaging Interaction Toolkit  2018.4.99-b7f3afaa
Medical Imaging Interaction Toolkit
berrySmartPointer.h
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #ifndef BERRYSMARTPOINTER_H_
14 #define BERRYSMARTPOINTER_H_
15 
16 #include <iostream>
17 #include <stdexcept>
18 
20 
21 #include <berryConfig.h>
22 
23 #include <Poco/Bugcheck.h>
24 
25 #if defined(BLUEBERRY_DEBUG_SMARTPOINTER)
26 #include <QMutex>
27 #endif
28 
29 namespace berry
30 {
31 
32 template<class T> class WeakPointer;
33 
44 template<class TObjectType>
45 class SmartPointer
46 {
47 public:
48  typedef TObjectType ObjectType;
49  typedef SmartPointer Self;
50 
53  m_Pointer(nullptr)
54  {
55 #if defined(BLUEBERRY_DEBUG_SMARTPOINTER)
56  DebugInitSmartPointer();
57 #endif
58 
59  }
60 
62  explicit SmartPointer(ObjectType *p) :
63  m_Pointer(p)
64  {
65  if (m_Pointer)
66  this->Register();
67 
68 #if defined(BLUEBERRY_DEBUG_SMARTPOINTER)
69  DebugInitSmartPointer();
70 #endif
71  }
72 
75  m_Pointer(p.m_Pointer)
76  {
77  this->Register();
78 
79 #if defined(BLUEBERRY_DEBUG_SMARTPOINTER)
80  DebugInitSmartPointer();
81 #endif
82  }
83 
84  template<class Other>
86  m_Pointer(const_cast<Other*> (ptr.GetPointer()))
87  {
88  if (m_Pointer)
89  this->Register();
90 
91 #if defined(BLUEBERRY_DEBUG_SMARTPOINTER)
92  DebugInitSmartPointer();
93 #endif
94  }
95 
96  template<class Other>
97  explicit SmartPointer(const WeakPointer<Other>& wp);
98 
101  {
102 #if defined(BLUEBERRY_DEBUG_SMARTPOINTER)
103  if (m_Pointer) DebugRemoveSmartPointer();
104 #endif
105 
106  this->UnRegister();
107  m_Pointer = nullptr;
108  }
109 
110  template<class Other>
112  {
113  Other* pOther = dynamic_cast<Other*> (m_Pointer);
114  return SmartPointer<Other> (pOther);
115  }
116 
118  ObjectType *operator ->() const
119  {
120  return m_Pointer;
121  }
122 
123 // /** Return pointer to object. */
124 // operator ObjectType *() const
125 // {
126 // return m_Pointer;
127 // }
128 
129  ObjectType & operator*() const
130  {
131  poco_assert( m_Pointer != nullptr );
132  return *m_Pointer;
133  }
134 
136  bool IsNotNull() const
137  {
138  return m_Pointer != nullptr;
139  }
140  bool IsNull() const
141  {
142  return m_Pointer == nullptr;
143  }
144 
145  typedef ObjectType * Self::*unspecified_bool_type;
146 
147  operator unspecified_bool_type () const
148  {
149  return m_Pointer == nullptr ? nullptr: &Self::m_Pointer;
150  }
151 
153  template<typename R>
154  bool operator ==(const R* o) const
155  {
156  return (m_Pointer == nullptr ? o == nullptr : (o && m_Pointer->operator==(o)));
157  }
158 
159  template<typename R>
160  bool operator ==(const SmartPointer<R>& r) const
161  {
162  const R* o = r.GetPointer();
163  return (m_Pointer == nullptr ? o == nullptr : (o && m_Pointer->operator==(o)));
164  }
165 
166  bool operator ==(int r) const
167  {
168  if (r == 0)
169  return m_Pointer == nullptr;
170 
171  throw std::invalid_argument("Can only compare to 0");
172  }
173 
174  template<typename R>
175  bool operator !=(const R* r) const
176  {
177  return !(this->operator==(r));
178  }
179 
180  template<typename R>
181  bool operator !=(const SmartPointer<R>& r) const
182  {
183  return !(this->operator==(r));
184  }
185 
186  bool operator !=(int r) const
187  {
188  if (r == 0)
189  return m_Pointer != nullptr;
190 
191  throw std::invalid_argument("Can only compare to 0");
192  }
193 
194 // /** Template comparison operators using operator==. */
195 // template<typename R>
196 // bool CompareTo(const SmartPointer<R>& r) const
197 // {
198 // return m_Pointer == 0 ? r == 0 : r.GetPointer() && m_Pointer->operator==(r.GetPointer());
199 // }
200 
201 // template<typename R>
202 // bool CompareTo(R r) const
203 // {
204 // //const ObjectType* o = static_cast<const ObjectType*> (r);
205 // return m_Pointer == 0 ? r == 0 : (r && m_Pointer->operator==(r));
206 // }
207 
209  ObjectType *GetPointer() const
210  {
211  return m_Pointer;
212  }
213 
215  template<typename R>
216  bool operator <(const SmartPointer<R>& r) const
217  {
218  const R* o = r.GetPointer();
219  return m_Pointer == nullptr ? o == nullptr : o && m_Pointer->operator<(o);
220  }
221 
223  template<typename R>
224  bool operator>(const SmartPointer<R>& r) const
225  {
226  const R* o = r.GetPointer();
227  return m_Pointer == 0 ? o == 0 : o && m_Pointer->operator>(o);
228  }
229 
231  template<typename R>
232  bool operator <=(const SmartPointer<R>& r) const
233  {
234  return this->operator<(r) || this->operator==(r);
235  }
236 
238  template<typename R>
239  bool operator >=(const SmartPointer<R>& r) const
240  {
241  return this->operator>(r) || this->operator==(r);
242  }
243 
246  {
247  return this->operator =(r.GetPointer());
248  }
249 
251  template<typename R>
253  {
254  return this->operator =(r.GetPointer());
255  }
256 
258  SmartPointer &operator =(ObjectType *r)
259  {
260  if (m_Pointer != r)
261  {
262 #if defined(BLUEBERRY_DEBUG_SMARTPOINTER)
263  DebugAssignSmartPointer(r, m_Pointer);
264 #endif
265  ObjectType* tmp = m_Pointer; //avoid recursive unregisters by retaining temporarily
266  m_Pointer = r;
267  this->Register();
268  if (tmp)
269  {
270  tmp->UnRegister();
271  }
272  }
273  return *this;
274  }
275 
277  QDebug Print(QDebug os) const;
278 
279 private:
280 
282  ObjectType* m_Pointer;
283 
284  void Register()
285  {
286  if (m_Pointer)
287  {
288  m_Pointer->Register();
289  }
290  }
291 
292  void UnRegister()
293  {
294  if (m_Pointer)
295  {
296  m_Pointer->UnRegister();
297  }
298  }
299 
300 #if defined(BLUEBERRY_DEBUG_SMARTPOINTER)
301 
302  unsigned int m_Id;
303  QMutex m_Mutex;
304 
305  void DebugInitSmartPointer();
306 
307  void DebugRemoveSmartPointer();
308 
309  void DebugAssignSmartPointer(const ObjectType* newObject, const ObjectType* oldObject);
310 
311 public:
312 
313  int GetId();
314 
315 private:
316 #endif
317 };
318 
319 template<typename T>
320 std::ostream& operator<<(std::ostream& os, const SmartPointer<T>& p)
321 {
322  os << p->ToString().toStdString();
323  return os;
324 }
325 
326 } // namespace berry
327 
328 template<class T>
330 {
331  return sp->HashCode();
332 }
333 
334 template<class T>
336 {
337  berry::SmartPointer<T> sp(wp.Lock());
338  if (sp.IsNull())
339  {
340  return 0;
341  }
342  return sp->HashCode();
343 }
344 
345 #include "berryException.h"
346 #include <QDebug>
347 
348 namespace berry {
349 
350 template<class T>
351 template<class Other>
353 {
354  if (wp.m_Pointer)
355  {
356  this->m_Pointer = wp.m_Pointer;
357  this->Register();
358 
359  #if defined(BLUEBERRY_DEBUG_SMARTPOINTER)
360  DebugInitSmartPointer();
361  #endif
362  }
363  else
364  {
365  throw BadWeakPointerException("Weak pointer is nullptr");
366  }
367 }
368 
370 template<class T>
371 QDebug SmartPointer<T>::Print(QDebug os) const
372 {
373  // This prints the object pointed to by the pointer
374  (*m_Pointer).Print(os);
375  return os;
376 }
377 
378 }
379 
380 #if defined(BLUEBERRY_DEBUG_SMARTPOINTER)
381 
382 #include "berryDebugUtil.h"
383 
384 namespace berry {
385 
386 template<class T>
388 {
389  {
390  QMutexLocker lock(&m_Mutex);
391  if (m_Pointer)
392  {
393  unsigned int& counter = DebugUtil::GetSmartPointerCounter();
394  m_Id = ++counter;
395  DebugUtil::RegisterSmartPointer(m_Id, m_Pointer);
396  }
397  else m_Id = 0;
398  }
399 
400  //if (DebugUtil::GetSmartPointerCounter() == Platform::GetConfiguration().getInt(Platform::DEBUG_ARG_SMARTPOINTER_ID))
401  //throw 1;
402 }
403 
404 template<class T>
406 {
407  QMutexLocker lock(&m_Mutex);
408  DebugUtil::UnregisterSmartPointer(m_Id, m_Pointer);
409 }
410 
411 template<class T>
412 void SmartPointer<T>::DebugAssignSmartPointer(const ObjectType* newObject, const ObjectType* oldObject)
413 {
414  QMutexLocker lock(&m_Mutex);
415  if (oldObject)
416  DebugUtil::UnregisterSmartPointer(m_Id, oldObject);
417 
418  if (newObject)
419  {
420  if (m_Id < 1)
421  {
422  unsigned int& counter = DebugUtil::GetSmartPointerCounter();
423  m_Id = ++counter;
424  }
425  DebugUtil::RegisterSmartPointer(m_Id, newObject);
426  }
427 }
428 
429 template<class T>
431 {
432  return m_Id;
433 }
434 
435 }
436 
437 #endif
438 
439 #endif /*BERRYSMARTPOINTER_H_*/
ObjectType * operator->() const
static void UnregisterSmartPointer(unsigned int smartPointerId, const Object *objectPointer)
SmartPointer< Other > Cast() const
SmartPointer & operator=(const SmartPointer &r)
static unsigned int & GetSmartPointerCounter()
Implements transparent reference counting.
void Register() const
SmartPointer(const SmartPointer< ObjectType > &p)
void UnRegister(bool del=true) const
implements a WeakPointer class to deal with circular reference problems.
SmartPointer< ObjectType > Lock() const
ObjectType *Self::* unspecified_bool_type
SmartPointer(const SmartPointer< Other > &ptr)
bool operator!=(const R *r) const
bool operator>=(const SmartPointer< R > &r) const
uint qHash(const berry::SmartPointer< T > &sp)
static void RegisterSmartPointer(unsigned int smartPointerId, const Object *objectPointer, bool recordStack=false)
ObjectType & operator*() const
bool operator>(const SmartPointer< R > &r) const
bool operator<(const SmartPointer< R > &r) const
bool operator==(const R *o) const
unsigned int uint
SmartPointer(ObjectType *p)
QDebug Print(QDebug os) const
ObjectType * GetPointer() const