Medical Imaging Interaction Toolkit  2023.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  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
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:241
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:217
mitk::WeakPointer::operator<
friend bool operator<(const WeakPointer &left, const WeakPointer &right) noexcept
Definition: mitkWeakPointer.h:178
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:235
operator>
bool operator>(const mitk::WeakPointer< T > &left, const mitk::WeakPointer< T > &right) noexcept
Definition: mitkWeakPointer.h:229
operator<=
bool operator<=(const mitk::WeakPointer< T > &left, const mitk::WeakPointer< T > &right) noexcept
Definition: mitkWeakPointer.h:223
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:166