Medical Imaging Interaction Toolkit  2024.06.00
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 
141  using TWithoutConst = typename std::remove_const_t<T>;
142  //cast the pointer to non const before adding the observer. This is done to ensure that
143  //weak pointer also supports const pointers.
144  auto nonConstPointer = const_cast<TWithoutConst*>(m_RawPointer);
145  m_ObserverTag = nonConstPointer->AddObserver(itk::DeleteEvent(), command);
146  }
147  }
148 
149  void RemoveDeleteEventObserver()
150  {
151  if (nullptr != m_RawPointer)
152  {
153  using TWithoutConst = typename std::remove_const_t<T>;
154  //cast the pointer to non const before removing the observer. This is done to ensure that
155  //weak pointer also supports const pointers.
156  auto nonConstPointer = const_cast<TWithoutConst*>(m_RawPointer);
157  nonConstPointer->RemoveObserver(m_ObserverTag);
158  }
159  }
160 
161  void OnDeleteEvent() noexcept
162  {
163  // Don't remove any observers from the observed object as it is about to
164  // die and can't handle this operation anymore.
165 
166  m_RawPointer = nullptr;
167 
168  if (m_DeleteEventCallback)
169  m_DeleteEventCallback();
170  }
171 
172  // The following comparison operators need access to class internals.
173  // All remaining comparison operators are implemented as non-member
174  // non-friend functions that use logical combinations of these non-member
175  // friend functions.
176 
177  friend bool operator ==(const WeakPointer &left, const WeakPointer &right) noexcept
178  {
179  return left.m_RawPointer == right.m_RawPointer;
180  }
181 
182  // Also covers comparisons to T::Pointer and T::ConstPointer as
183  // itk::SmartPointer can be implicitly converted to a raw pointer.
184  friend bool operator ==(const WeakPointer &left, const T *right) noexcept
185  {
186  return left.m_RawPointer == right;
187  }
188 
189  friend bool operator <(const WeakPointer &left, const WeakPointer &right) noexcept
190  {
191  // The specialization of std::less for any pointer type yields a total
192  // order, even if the built-in operator < doesn't.
193  return std::less<T*>()(left.m_RawPointer, right.m_RawPointer);
194  }
195 
196  friend bool operator <(const WeakPointer &left, std::nullptr_t right) noexcept
197  {
198  return std::less<T*>()(left.m_RawPointer, right);
199  }
200 
201  friend bool operator <(std::nullptr_t left, const WeakPointer &right) noexcept
202  {
203  return std::less<T*>()(left, right.m_RawPointer);
204  }
205 
206  friend bool operator <(const WeakPointer &left, const T *right) noexcept
207  {
208  return std::less<T*>()(left.m_RawPointer, right);
209  }
210 
211  friend bool operator <(const T *left, const WeakPointer &right) noexcept
212  {
213  return std::less<T*>()(left, right.m_RawPointer);
214  }
215 
216  T *m_RawPointer;
217 
218  // m_ObserverTag is completely managed by the two methods
219  // AddDeleteEventObserver() and RemoveDeleteEventObserver(). There
220  // isn't any need to initialize or use it at all outside of these methods.
221  unsigned long m_ObserverTag;
222 
223  DeleteEventCallbackType m_DeleteEventCallback;
224  };
225 }
226 
227 template <class T>
228 bool operator !=(const mitk::WeakPointer<T> &left, const mitk::WeakPointer<T> &right) noexcept
229 {
230  return !(left == right);
231 }
232 
233 template <class T>
234 bool operator <=(const mitk::WeakPointer<T> &left, const mitk::WeakPointer<T> &right) noexcept
235 {
236  return !(right < left);
237 }
238 
239 template <class T>
240 bool operator >(const mitk::WeakPointer<T> &left, const mitk::WeakPointer<T> &right) noexcept
241 {
242  return right < left;
243 }
244 
245 template <class T>
246 bool operator >=(const mitk::WeakPointer<T> &left, const mitk::WeakPointer<T> &right) noexcept
247 {
248  return !(left < right);
249 }
250 
251 template <class T>
252 bool operator ==(const mitk::WeakPointer<T> &left, std::nullptr_t) noexcept
253 {
254  return !left;
255 }
256 
257 template <class T>
258 bool operator !=(const mitk::WeakPointer<T> &left, std::nullptr_t right) noexcept
259 {
260  return !(left == right);
261 }
262 
263 template <class T>
264 bool operator ==(std::nullptr_t, const mitk::WeakPointer<T> &right) noexcept
265 {
266  return !right;
267 }
268 
269 template <class T>
270 bool operator !=(std::nullptr_t left, const mitk::WeakPointer<T> &right) noexcept
271 {
272  return !(left == right);
273 }
274 
275 template <class T>
276 bool operator <=(const mitk::WeakPointer<T> &left, std::nullptr_t right) noexcept
277 {
278  return !(right < left);
279 }
280 
281 template <class T>
282 bool operator >(const mitk::WeakPointer<T> &left, std::nullptr_t right) noexcept
283 {
284  return right < left;
285 }
286 
287 template <class T>
288 bool operator >=(const mitk::WeakPointer<T> &left, std::nullptr_t right) noexcept
289 {
290  return !(left < right);
291 }
292 
293 template <class T>
294 bool operator <=(std::nullptr_t left, const mitk::WeakPointer<T> &right) noexcept
295 {
296  return !(right < left);
297 }
298 
299 template <class T>
300 bool operator >(std::nullptr_t left, const mitk::WeakPointer<T> &right) noexcept
301 {
302  return right < left;
303 }
304 
305 template <class T>
306 bool operator >=(std::nullptr_t left, const mitk::WeakPointer<T> &right) noexcept
307 {
308  return !(left < right);
309 }
310 
311 template <class T>
312 bool operator !=(const mitk::WeakPointer<T> &left, const T *right) noexcept
313 {
314  return !(left == right);
315 }
316 
317 template <class T>
318 bool operator <=(const mitk::WeakPointer<T> &left, const T *right) noexcept
319 {
320  return !(right < left);
321 }
322 
323 template <class T>
324 bool operator >(const mitk::WeakPointer<T> &left, const T *right) noexcept
325 {
326  return right < left;
327 }
328 
329 template <class T>
330 bool operator >=(const mitk::WeakPointer<T> &left, const T *right) noexcept
331 {
332  return !(left < right);
333 }
334 
335 template <class T>
336 bool operator ==(const T *left, const mitk::WeakPointer<T> &right) noexcept
337 {
338  return right == left;
339 }
340 
341 template <class T>
342 bool operator !=(const T *left, const mitk::WeakPointer<T> &right) noexcept
343 {
344  return !(right == left);
345 }
346 
347 template <class T>
348 bool operator <=(const T *left, const mitk::WeakPointer<T> &right) noexcept
349 {
350  return !(right < left);
351 }
352 
353 template <class T>
354 bool operator >(const T *left, const mitk::WeakPointer<T> &right) noexcept
355 {
356  return right < left;
357 }
358 
359 template <class T>
360 bool operator >=(const T *left, const mitk::WeakPointer<T> &right) noexcept
361 {
362  return !(left < right);
363 }
364 
365 template <class T>
366 bool operator !=(const mitk::WeakPointer<T> &left, itk::SmartPointer<T> right) noexcept
367 {
368  return !(left == right);
369 }
370 
371 template <class T>
372 bool operator <=(const mitk::WeakPointer<T> &left, itk::SmartPointer<T> right) noexcept
373 {
374  return !(right < left);
375 }
376 
377 template <class T>
378 bool operator >(const mitk::WeakPointer<T> &left, itk::SmartPointer<T> right) noexcept
379 {
380  return right < left;
381 }
382 
383 template <class T>
384 bool operator >=(const mitk::WeakPointer<T> &left, itk::SmartPointer<T> right) noexcept
385 {
386  return !(left < right);
387 }
388 
389 template <class T>
390 bool operator ==(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
391 {
392  return right == left;
393 }
394 
395 template <class T>
396 bool operator !=(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
397 {
398  return !(right == left);
399 }
400 
401 template <class T>
402 bool operator <=(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
403 {
404  return !(right < left);
405 }
406 
407 template <class T>
408 bool operator >(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
409 {
410  return right < left;
411 }
412 
413 template <class T>
414 bool operator >=(itk::SmartPointer<T> left, const mitk::WeakPointer<T> &right) noexcept
415 {
416  return !(left < right);
417 }
418 
419 #endif
mitk::WeakPointer::WeakPointer
WeakPointer(WeakPointer &&other)
Definition: mitkWeakPointer.h:44
mitk::WeakPointer::~WeakPointer
~WeakPointer() noexcept
Definition: mitkWeakPointer.h:52
operator==
bool operator==(const mitk::WeakPointer< T > &left, std::nullptr_t) noexcept
Definition: mitkWeakPointer.h:252
mitk::WeakPointer::WeakPointer
WeakPointer(T *rawPointer)
Definition: mitkWeakPointer.h:32
itk::SmartPointer
Definition: mitkIFileReader.h:30
mitk::WeakPointer::WeakPointer
WeakPointer() noexcept
Definition: mitkWeakPointer.h:27
mitk::WeakPointer::IsExpired
bool IsExpired() const noexcept
Definition: mitkWeakPointer.h:118
mitk::WeakPointer< mitk::DataInteractor >::DeleteEventCallbackType
std::function< void()> DeleteEventCallbackType
Definition: mitkWeakPointer.h:25
mitk
Find image slices visible on a given plane.
Definition: RenderingTests.dox:1
mitk::WeakPointer::Lock
itk::SmartPointer< T > Lock() const
Definition: mitkWeakPointer.h:123
operator!=
bool operator!=(const mitk::WeakPointer< T > &left, const mitk::WeakPointer< T > &right) noexcept
Definition: mitkWeakPointer.h:228
mitk::WeakPointer::operator<
friend bool operator<(const WeakPointer &left, const WeakPointer &right) noexcept
Definition: mitkWeakPointer.h:189
mitk::WeakPointer::WeakPointer
WeakPointer(const WeakPointer &other)
Definition: mitkWeakPointer.h:38
operator>=
bool operator>=(const mitk::WeakPointer< T > &left, const mitk::WeakPointer< T > &right) noexcept
Definition: mitkWeakPointer.h:246
operator>
bool operator>(const mitk::WeakPointer< T > &left, const mitk::WeakPointer< T > &right) noexcept
Definition: mitkWeakPointer.h:240
operator<=
bool operator<=(const mitk::WeakPointer< T > &left, const mitk::WeakPointer< T > &right) noexcept
Definition: mitkWeakPointer.h:234
mitk::WeakPointer::operator=
WeakPointer & operator=(const WeakPointer &other)
Definition: mitkWeakPointer.h:68
mitk::WeakPointer
Definition: mitkWeakPointer.h:22
mitk::WeakPointer::SetDeleteEventCallback
void SetDeleteEventCallback(const DeleteEventCallbackType &callback)
Definition: mitkWeakPointer.h:128
mitk::WeakPointer::operator==
friend bool operator==(const WeakPointer &left, const WeakPointer &right) noexcept
Definition: mitkWeakPointer.h:177