Medical Imaging Interaction Toolkit  2026.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 <compare>
18 #include <functional>
19 
20 namespace mitk
21 {
42  template <class T>
43  class WeakPointer final
44  {
45  public:
47  using DeleteEventCallbackType = std::function<void ()>;
48 
50  WeakPointer() noexcept
51  : m_RawPointer(nullptr)
52  {
53  }
54 
60  WeakPointer(T *rawPointer)
61  : m_RawPointer(rawPointer)
62  {
63  this->AddDeleteEventObserver();
64  }
65 
71  WeakPointer(const WeakPointer &other)
72  : m_RawPointer(other.m_RawPointer)
73  {
74  this->AddDeleteEventObserver();
75  }
76 
85  : m_RawPointer(other.m_RawPointer)
86  {
87  other.RemoveDeleteEventObserver();
88  other.m_RawPointer = nullptr;
89  this->AddDeleteEventObserver();
90  }
91 
93  ~WeakPointer() noexcept
94  {
95  try
96  {
97  this->RemoveDeleteEventObserver();
98  }
99  catch (...)
100  {
101  // Swallow. Otherwise, the application would terminate if another
102  // exception is already propagating.
103  }
104  }
105 
116  {
117  if (this != &other)
118  {
119  this->RemoveDeleteEventObserver();
120  m_RawPointer = other.m_RawPointer;
121  this->AddDeleteEventObserver();
122  }
123 
124  return *this;
125  }
126 
136  {
137  // No check for self-assignment as it is allowed to assume that the
138  // parameter is a unique reference to this argument.
139 
140  this->RemoveDeleteEventObserver();
141  m_RawPointer = other.m_RawPointer;
142  other.m_RawPointer = nullptr;
143  this->AddDeleteEventObserver();
144 
145  return *this;
146  }
147 
153  WeakPointer & operator =(std::nullptr_t)
154  {
155  this->RemoveDeleteEventObserver();
156  m_RawPointer = nullptr;
157 
158  return *this;
159  }
160 
168  {
169  if (m_RawPointer != other)
170  {
171  this->RemoveDeleteEventObserver();
172  m_RawPointer = other;
173  this->AddDeleteEventObserver();
174  }
175 
176  return *this;
177  }
178 
184  explicit operator bool() const noexcept
185  {
186  return nullptr != m_RawPointer;
187  }
188 
194  bool IsExpired() const noexcept
195  {
196  return !*this;
197  }
198 
208  {
209  return m_RawPointer;
210  }
211 
218  {
219  m_DeleteEventCallback = callback;
220  }
221 
222  private:
223  void AddDeleteEventObserver()
224  {
225  if (nullptr != m_RawPointer)
226  {
227  auto command = itk::SimpleMemberCommand<WeakPointer>::New();
228  command->SetCallbackFunction(this, &WeakPointer::OnDeleteEvent);
229 
230  using TWithoutConst = typename std::remove_const_t<T>;
231  //cast the pointer to non const before adding the observer. This is done to ensure that
232  //weak pointer also supports const pointers.
233  auto nonConstPointer = const_cast<TWithoutConst*>(m_RawPointer);
234  m_ObserverTag = nonConstPointer->AddObserver(itk::DeleteEvent(), command);
235  }
236  }
237 
238  void RemoveDeleteEventObserver()
239  {
240  if (nullptr != m_RawPointer)
241  {
242  using TWithoutConst = typename std::remove_const_t<T>;
243  //cast the pointer to non const before removing the observer. This is done to ensure that
244  //weak pointer also supports const pointers.
245  auto nonConstPointer = const_cast<TWithoutConst*>(m_RawPointer);
246  nonConstPointer->RemoveObserver(m_ObserverTag);
247  }
248  }
249 
250  void OnDeleteEvent() noexcept
251  {
252  // Don't remove any observers from the observed object as it is about to
253  // die and can't handle this operation anymore.
254 
255  m_RawPointer = nullptr;
256 
257  if (m_DeleteEventCallback)
258  m_DeleteEventCallback();
259  }
260 
261  // In C++20, operator== and operator<=> generate all comparison operators
262  // (!=, <, >, <=, >=) and their reversed-argument forms automatically.
263  // This also covers comparisons to T::Pointer and T::ConstPointer as
264  // itk::SmartPointer can be implicitly converted to a raw pointer.
265 
266  friend bool operator ==(const WeakPointer &left, const WeakPointer &right) noexcept
267  {
268  return left.m_RawPointer == right.m_RawPointer;
269  }
270 
271  friend std::strong_ordering operator <=>(const WeakPointer &left, const WeakPointer &right) noexcept
272  {
273  return std::compare_three_way()(left.m_RawPointer, right.m_RawPointer);
274  }
275 
276  friend bool operator ==(const WeakPointer &left, const T *right) noexcept
277  {
278  return left.m_RawPointer == right;
279  }
280 
281  friend std::strong_ordering operator <=>(const WeakPointer &left, const T *right) noexcept
282  {
283  return std::compare_three_way()(left.m_RawPointer, right);
284  }
285 
286  T *m_RawPointer;
287 
288  // m_ObserverTag is completely managed by the two methods
289  // AddDeleteEventObserver() and RemoveDeleteEventObserver(). There
290  // isn't any need to initialize or use it at all outside of these methods.
291  unsigned long m_ObserverTag;
292 
293  DeleteEventCallbackType m_DeleteEventCallback;
294  };
295 }
296 
297 #endif
A weak pointer that observes an itk::Object without preventing its deletion.
WeakPointer() noexcept
Default constructor. Creates an expired weak pointer (null).
WeakPointer(const WeakPointer &other)
Copy constructor. Observes the same object as other.
~WeakPointer() noexcept
Destructor. Removes the delete-event observer from the observed object.
friend bool operator==(const WeakPointer &left, const WeakPointer &right) noexcept
void SetDeleteEventCallback(const DeleteEventCallbackType &callback)
Set a callback to be invoked when the observed object is deleted.
itk::SmartPointer< T > Lock() const
Obtain a smart pointer to the observed object.
WeakPointer & operator=(const WeakPointer &other)
Copy assignment operator.
friend std::strong_ordering operator<=>(const WeakPointer &left, const WeakPointer &right) noexcept
WeakPointer(T *rawPointer)
Construct a weak pointer observing the given raw pointer.
WeakPointer(WeakPointer &&other)
Move constructor. Takes over the observed object from other.
std::function< void()> DeleteEventCallbackType
Callback type invoked when the observed object is deleted.
bool IsExpired() const noexcept
Check whether the observed object has been deleted.
Find image slices visible on a given plane.