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