Medical Imaging Interaction Toolkit  2018.04.99-c3229764
Medical Imaging Interaction Toolkit
mitkWeakPointer.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 mitkWeakPointer_h
14 #define mitkWeakPointer_h
15 
16 #include <itkCommand.h>
17 #include <functional>
18 
19 namespace mitk
20 {
21  template <class T>
22  class WeakPointer final
23  {
24  public:
25  using DeleteEventCallbackType = std::function<void ()>;
26 
27  WeakPointer() noexcept
28  : m_RawPointer(nullptr)
29  {
30  }
31 
32  WeakPointer(T *rawPointer)
33  : m_RawPointer(rawPointer)
34  {
35  this->AddDeleteEventObserver();
36  }
37 
38  WeakPointer(const WeakPointer &other)
39  : m_RawPointer(other.m_RawPointer)
40  {
41  this->AddDeleteEventObserver();
42  }
43 
45  : m_RawPointer(other.m_RawPointer)
46  {
47  other.RemoveDeleteEventObserver();
48  other.m_RawPointer = nullptr;
49  this->AddDeleteEventObserver();
50  }
51 
52  ~WeakPointer() noexcept
53  {
54  try
55  {
56  this->RemoveDeleteEventObserver();
57  }
58  catch (...)
59  {
60  // Swallow. Otherwise, the application would terminate if another
61  // exception is already propagating.
62  }
63  }
64 
65  // Prefer classic implementation to copy-and-swap idiom. Swapping is
66  // non-trivial for this class as the observed object is keeping references
67  // to its observers.
69  {
70  if (this != &other)
71  {
72  this->RemoveDeleteEventObserver();
73  m_RawPointer = other.m_RawPointer;
74  this->AddDeleteEventObserver();
75  }
76 
77  return *this;
78  }
79 
81  {
82  // No check for self-assignment as it is allowed to assume that the
83  // parameter is a unique reference to this argument.
84 
85  this->RemoveDeleteEventObserver();
86  m_RawPointer = other.m_RawPointer;
87  other.m_RawPointer = nullptr;
88  this->AddDeleteEventObserver();
89 
90  return *this;
91  }
92 
93  WeakPointer & operator =(std::nullptr_t)
94  {
95  this->RemoveDeleteEventObserver();
96  m_RawPointer = nullptr;
97 
98  return *this;
99  }
100 
102  {
103  if (m_RawPointer != other)
104  {
105  this->RemoveDeleteEventObserver();
106  m_RawPointer = other;
107  this->AddDeleteEventObserver();
108  }
109 
110  return *this;
111  }
112 
113  explicit operator bool() const noexcept
114  {
115  return nullptr != m_RawPointer;
116  }
117 
118  bool IsExpired() const noexcept
119  {
120  return !*this;
121  }
122 
124  {
125  return m_RawPointer;
126  }
127 
129  {
130  m_DeleteEventCallback = callback;
131  }
132 
133  private:
134  void AddDeleteEventObserver()
135  {
136  if (nullptr != m_RawPointer)
137  {
138  auto command = itk::SimpleMemberCommand<WeakPointer>::New();
139  command->SetCallbackFunction(this, &WeakPointer::OnDeleteEvent);
140  m_ObserverTag = m_RawPointer->AddObserver(itk::DeleteEvent(), command);
141  }
142  }
143 
144  void RemoveDeleteEventObserver()
145  {
146  if (nullptr != m_RawPointer)
147  m_RawPointer->RemoveObserver(m_ObserverTag);
148  }
149 
150  void OnDeleteEvent() noexcept
151  {
152  // Don't remove any observers from the observed object as it is about to
153  // die and can't handle this operation anymore.
154 
155  m_RawPointer = nullptr;
156 
157  if (m_DeleteEventCallback)
158  m_DeleteEventCallback();
159  }
160 
161  // The following comparison operators need access to class internals.
162  // All remaining comparison operators are implemented as non-member
163  // non-friend functions that use logical combinations of these non-member
164  // friend functions.
165 
166  friend bool operator ==(const WeakPointer &left, const WeakPointer &right) noexcept
167  {
168  return left.m_RawPointer == right.m_RawPointer;
169  }
170 
171  // Also covers comparisons to T::Pointer and T::ConstPointer as
172  // itk::SmartPointer can be implicitly converted to a raw pointer.
173  friend bool operator ==(const WeakPointer &left, const T *right) noexcept
174  {
175  return left.m_RawPointer == right;
176  }
177 
178  friend bool operator <(const WeakPointer &left, const WeakPointer &right) noexcept
179  {
180  // The specialization of std::less for any pointer type yields a total
181  // order, even if the built-in operator < doesn't.
182  return std::less<T*>()(left.m_RawPointer, right.m_RawPointer);
183  }
184 
185  friend bool operator <(const WeakPointer &left, std::nullptr_t right) noexcept
186  {
187  return std::less<T*>()(left.m_RawPointer, right);
188  }
189 
190  friend bool operator <(std::nullptr_t left, const WeakPointer &right) noexcept
191  {
192  return std::less<T*>()(left, right.m_RawPointer);
193  }
194 
195  friend bool operator <(const WeakPointer &left, const T *right) noexcept
196  {
197  return std::less<T*>()(left.m_RawPointer, right);
198  }
199 
200  friend bool operator <(const T *left, const WeakPointer &right) noexcept
201  {
202  return std::less<T*>()(left, right.m_RawPointer);
203  }
204 
205  T *m_RawPointer;
206 
207  // m_ObserverTag is completely managed by the two methods
208  // AddDeleteEventObserver() and RemoveDeleteEventObserver(). There
209  // isn't any need to initialize or use it at all outside of these methods.
210  unsigned long m_ObserverTag;
211 
212  DeleteEventCallbackType m_DeleteEventCallback;
213  };
214 }
215 
216 template <class T>
217 bool operator !=(const mitk::WeakPointer<T> &left, const mitk::WeakPointer<T> &right) noexcept
218 {
219  return !(left == right);
220 }
221 
222 template <class T>
223 bool operator <=(const mitk::WeakPointer<T> &left, const mitk::WeakPointer<T> &right) noexcept
224 {
225  return !(right < left);
226 }
227 
228 template <class T>
229 bool operator >(const mitk::WeakPointer<T> &left, const mitk::WeakPointer<T> &right) noexcept
230 {
231  return right < left;
232 }
233 
234 template <class T>
235 bool operator >=(const mitk::WeakPointer<T> &left, const mitk::WeakPointer<T> &right) noexcept
236 {
237  return !(left < right);
238 }
239 
240 template <class T>
241 bool operator ==(const mitk::WeakPointer<T> &left, std::nullptr_t) noexcept
242 {
243  return !left;
244 }
245 
246 template <class T>
247 bool operator !=(const mitk::WeakPointer<T> &left, std::nullptr_t right) noexcept
248 {
249  return !(left == right);
250 }
251 
252 template <class T>
253 bool operator ==(std::nullptr_t, const mitk::WeakPointer<T> &right) noexcept
254 {
255  return !right;
256 }
257 
258 template <class T>
259 bool operator !=(std::nullptr_t left, const mitk::WeakPointer<T> &right) noexcept
260 {
261  return !(left == right);
262 }
263 
264 template <class T>
265 bool operator <=(const mitk::WeakPointer<T> &left, std::nullptr_t right) noexcept
266 {
267  return !(right < left);
268 }
269 
270 template <class T>
271 bool operator >(const mitk::WeakPointer<T> &left, std::nullptr_t right) noexcept
272 {
273  return right < left;
274 }
275 
276 template <class T>
277 bool operator >=(const mitk::WeakPointer<T> &left, std::nullptr_t right) noexcept
278 {
279  return !(left < right);
280 }
281 
282 template <class T>
283 bool operator <=(std::nullptr_t left, const mitk::WeakPointer<T> &right) noexcept
284 {
285  return !(right < left);
286 }
287 
288 template <class T>
289 bool operator >(std::nullptr_t left, const mitk::WeakPointer<T> &right) noexcept
290 {
291  return right < left;
292 }
293 
294 template <class T>
295 bool operator >=(std::nullptr_t left, const mitk::WeakPointer<T> &right) noexcept
296 {
297  return !(left < right);
298 }
299 
300 template <class T>
301 bool operator !=(const mitk::WeakPointer<T> &left, const T *right) noexcept
302 {
303  return !(left == right);
304 }
305 
306 template <class T>
307 bool operator <=(const mitk::WeakPointer<T> &left, const T *right) noexcept
308 {
309  return !(right < left);
310 }
311 
312 template <class T>
313 bool operator >(const mitk::WeakPointer<T> &left, const T *right) noexcept
314 {
315  return right < left;
316 }
317 
318 template <class T>
319 bool operator >=(const mitk::WeakPointer<T> &left, const T *right) noexcept
320 {
321  return !(left < right);
322 }
323 
324 template <class T>
325 bool operator ==(const T *left, const mitk::WeakPointer<T> &right) noexcept
326 {
327  return right == left;
328 }
329 
330 template <class T>
331 bool operator !=(const T *left, const mitk::WeakPointer<T> &right) noexcept
332 {
333  return !(right == left);
334 }
335 
336 template <class T>
337 bool operator <=(const T *left, const mitk::WeakPointer<T> &right) noexcept
338 {
339  return !(right < left);
340 }
341 
342 template <class T>
343 bool operator >(const T *left, const mitk::WeakPointer<T> &right) noexcept
344 {
345  return right < left;
346 }
347 
348 template <class T>
349 bool operator >=(const T *left, const mitk::WeakPointer<T> &right) noexcept
350 {
351  return !(left < right);
352 }
353 
354 template <class T>
355 bool operator !=(const mitk::WeakPointer<T> &left, itk::SmartPointer<T> right) noexcept
356 {
357  return !(left == right);
358 }
359 
360 template <class T>
361 bool operator <=(const mitk::WeakPointer<T> &left, itk::SmartPointer<T> right) noexcept
362 {
363  return !(right < left);
364 }
365 
366 template <class T>
367 bool operator >(const mitk::WeakPointer<T> &left, itk::SmartPointer<T> right) noexcept
368 {
369  return right < left;
370 }
371 
372 template <class T>
373 bool operator >=(const mitk::WeakPointer<T> &left, itk::SmartPointer<T> right) noexcept
374 {
375  return !(left < right);
376 }
377 
378 template <class T>
379 bool operator ==(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
380 {
381  return right == left;
382 }
383 
384 template <class T>
385 bool operator !=(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
386 {
387  return !(right == left);
388 }
389 
390 template <class T>
391 bool operator <=(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
392 {
393  return !(right < left);
394 }
395 
396 template <class T>
397 bool operator >(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
398 {
399  return right < left;
400 }
401 
402 template <class T>
403 bool operator >=(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
404 {
405  return !(left < right);
406 }
407 
408 #endif
bool operator>(const mitk::WeakPointer< T > &left, const mitk::WeakPointer< T > &right) noexcept
itk::SmartPointer< T > Lock() const
bool operator>=(const mitk::WeakPointer< T > &left, const mitk::WeakPointer< T > &right) noexcept
WeakPointer & operator=(const WeakPointer &other)
DataCollection - Class to facilitate loading/accessing structured data.
WeakPointer(T *rawPointer)
std::function< void()> DeleteEventCallbackType
WeakPointer() noexcept
WeakPointer(WeakPointer &&other)
MITKCORE_EXPORT bool operator!=(const InteractionEvent &a, const InteractionEvent &b)
friend bool operator==(const WeakPointer &left, const WeakPointer &right) noexcept
bool IsExpired() const noexcept
~WeakPointer() noexcept
void SetDeleteEventCallback(const DeleteEventCallbackType &callback)
friend bool operator<(const WeakPointer &left, const WeakPointer &right) noexcept
WeakPointer(const WeakPointer &other)