Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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