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