Reference documentation for deal.II version Git 4abc4a1666 2020-07-04 19:58:34 +0200
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
smartpointer.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2019 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_smartpointer_h
17 #define dealii_smartpointer_h
18 
19 
20 #include <deal.II/base/config.h>
21 
23 
24 #include <atomic>
25 #include <typeinfo>
26 
28 
66 template <typename T, typename P = void>
68 {
69 public:
74  SmartPointer();
75 
80  template <class Q>
82 
88 
97  SmartPointer(T *t, const std::string &id);
98 
105  SmartPointer(T *t);
106 
110  ~SmartPointer();
111 
119  operator=(T *tt);
120 
125  template <class Q>
127  operator=(const SmartPointer<T, Q> &tt);
128 
134  operator=(const SmartPointer<T, P> &tt);
135 
139  void
140  clear();
141 
145  operator T *() const;
146 
151  T &operator*() const;
152 
157  T *operator->() const;
158 
168  template <class Q>
169  void
171 
180  void
181  swap(T *&tt);
182 
188  std::size_t
189  memory_consumption() const;
190 
191 private:
197  T *t;
198 
202  const std::string id;
203 
208  std::atomic<bool> pointed_to_object_is_alive;
209 };
210 
211 
212 /* --------------------- inline Template functions ------------------------- */
213 
214 
215 template <typename T, typename P>
217  : t(nullptr)
218  , id(typeid(P).name())
220 {}
221 
222 
223 
224 template <typename T, typename P>
226  : t(t)
227  , id(typeid(P).name())
229 {
230  if (t != nullptr)
231  t->subscribe(&pointed_to_object_is_alive, id);
232 }
233 
234 
235 
236 template <typename T, typename P>
237 inline SmartPointer<T, P>::SmartPointer(T *t, const std::string &id)
238  : t(t)
239  , id(id)
241 {
242  if (t != nullptr)
243  t->subscribe(&pointed_to_object_is_alive, id);
244 }
245 
246 
247 
248 template <typename T, typename P>
249 template <class Q>
251  : t(tt.t)
252  , id(tt.id)
254 {
255  if (tt.pointed_to_object_is_alive && t != nullptr)
256  t->subscribe(&pointed_to_object_is_alive, id);
257 }
258 
259 
260 
261 template <typename T, typename P>
263  : t(tt.t)
264  , id(tt.id)
266 {
267  if (tt.pointed_to_object_is_alive && t != nullptr)
268  t->subscribe(&pointed_to_object_is_alive, id);
269 }
270 
271 
272 
273 template <typename T, typename P>
275 {
276  if (pointed_to_object_is_alive && t != nullptr)
277  t->unsubscribe(&pointed_to_object_is_alive, id);
278 }
279 
280 
281 
282 template <typename T, typename P>
283 inline void
285 {
286  if (pointed_to_object_is_alive && t != nullptr)
287  {
288  t->unsubscribe(&pointed_to_object_is_alive, id);
289  delete t;
291  }
292  t = nullptr;
293 }
294 
295 
296 
297 template <typename T, typename P>
298 inline SmartPointer<T, P> &
300 {
301  // optimize if no real action is
302  // requested
303  if (t == tt)
304  return *this;
305 
306  if (pointed_to_object_is_alive && t != nullptr)
307  t->unsubscribe(&pointed_to_object_is_alive, id);
308  t = tt;
309  if (tt != nullptr)
310  tt->subscribe(&pointed_to_object_is_alive, id);
311  return *this;
312 }
313 
314 
315 
316 template <typename T, typename P>
317 template <class Q>
318 inline SmartPointer<T, P> &
320 {
321  // if objects on the left and right
322  // hand side of the operator= are
323  // the same, then this is a no-op
324  if (&tt == this)
325  return *this;
326 
327  if (pointed_to_object_is_alive && t != nullptr)
328  t->unsubscribe(&pointed_to_object_is_alive, id);
329  t = static_cast<T *>(tt);
330  if (tt.pointed_to_object_is_alive && tt != nullptr)
331  tt->subscribe(&pointed_to_object_is_alive, id);
332  return *this;
333 }
334 
335 
336 
337 template <typename T, typename P>
338 inline SmartPointer<T, P> &
340 {
341  // if objects on the left and right
342  // hand side of the operator= are
343  // the same, then this is a no-op
344  if (&tt == this)
345  return *this;
346 
347  if (pointed_to_object_is_alive && t != nullptr)
348  t->unsubscribe(&pointed_to_object_is_alive, id);
349  t = static_cast<T *>(tt);
350  if (tt.pointed_to_object_is_alive && tt != nullptr)
351  tt->subscribe(&pointed_to_object_is_alive, id);
352  return *this;
353 }
354 
355 
356 
357 template <typename T, typename P>
359 {
360  return t;
361 }
362 
363 
364 
365 template <typename T, typename P>
367 {
368  Assert(t != nullptr, ExcNotInitialized());
370  ExcMessage("The object pointed to is not valid anymore."));
371  return *t;
372 }
373 
374 
375 
376 template <typename T, typename P>
378 {
379  Assert(t != nullptr, ExcNotInitialized());
381  ExcMessage("The object pointed to is not valid anymore."));
382  return t;
383 }
384 
385 
386 
387 template <typename T, typename P>
388 template <class Q>
389 inline void
391 {
392 #ifdef DEBUG
393  SmartPointer<T, P> aux(t, id);
394  *this = tt;
395  tt = aux;
396 #else
397  std::swap(t, tt.t);
398 #endif
399 }
400 
401 
402 
403 template <typename T, typename P>
404 inline void
406 {
407  if (pointed_to_object_is_alive && t != nullptr)
408  t->unsubscribe(pointed_to_object_is_alive, id);
409 
410  std::swap(t, tt);
411 
412  if (t != nullptr)
413  t->subscribe(pointed_to_object_is_alive, id);
414 }
415 
416 
417 
418 template <typename T, typename P>
419 inline std::size_t
421 {
422  return sizeof(SmartPointer<T, P>);
423 }
424 
425 
426 
427 // The following function is not strictly necessary but is an optimization
428 // for places where you call swap(p1,p2) with SmartPointer objects p1, p2.
429 // Unfortunately, MS Visual Studio (at least up to the 2013 edition) trips
430 // over it when calling std::swap(v1,v2) where v1,v2 are std::vectors of
431 // SmartPointer objects: it can't determine whether it should call std::swap
432 // or ::swap on the individual elements (see bug #184 on our Google Code
433 // site. Consequently, just take this function out of the competition for this
434 // compiler.
435 #ifndef _MSC_VER
436 
441 template <typename T, typename P, class Q>
442 inline void
444 {
445  t1.swap(t2);
446 }
447 #endif
448 
449 
457 template <typename T, typename P>
458 inline void
460 {
461  t1.swap(t2);
462 }
463 
464 
465 
473 template <typename T, typename P>
474 inline void
476 {
477  t2.swap(t1);
478 }
479 
481 
482 #endif
std::atomic< bool > pointed_to_object_is_alive
Definition: smartpointer.h:208
T * operator->() const
Definition: smartpointer.h:377
const std::string id
Definition: smartpointer.h:202
void swap(SmartPointer< T, P > &t1, SmartPointer< T, Q > &t2)
Definition: smartpointer.h:443
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMessage(std::string arg1)
static const char T
#define Assert(cond, exc)
Definition: exceptions.h:1403
T & operator*() const
Definition: smartpointer.h:366
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:363
void swap(SmartPointer< T, Q > &tt)
Definition: smartpointer.h:390
SmartPointer< T, P > & operator=(T *tt)
Definition: smartpointer.h:299
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:362
std::size_t memory_consumption() const
Definition: smartpointer.h:420
static ::ExceptionBase & ExcInternalError()