Reference documentation for deal.II version Git 497f915867 2021-09-17 22:46:48 +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 - 2020 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 &
152  operator*() const;
153 
158  T *
159  operator->() const;
160 
170  template <class Q>
171  void
173 
182  void
183  swap(T *&tt);
184 
190  std::size_t
191  memory_consumption() const;
192 
193 private:
199  T *t;
200 
204  const std::string id;
205 
210  std::atomic<bool> pointed_to_object_is_alive;
211 };
212 
213 
214 /* --------------------- inline Template functions ------------------------- */
215 
216 
217 template <typename T, typename P>
219  : t(nullptr)
220  , id(typeid(P).name())
222 {}
223 
224 
225 
226 template <typename T, typename P>
228  : t(t)
229  , id(typeid(P).name())
231 {
232  if (t != nullptr)
233  t->subscribe(&pointed_to_object_is_alive, id);
234 }
235 
236 
237 
238 template <typename T, typename P>
239 inline SmartPointer<T, P>::SmartPointer(T *t, const std::string &id)
240  : t(t)
241  , id(id)
243 {
244  if (t != nullptr)
245  t->subscribe(&pointed_to_object_is_alive, id);
246 }
247 
248 
249 
250 template <typename T, typename P>
251 template <class Q>
253  : t(tt.t)
254  , id(tt.id)
256 {
257  if (tt.pointed_to_object_is_alive && t != nullptr)
258  t->subscribe(&pointed_to_object_is_alive, id);
259 }
260 
261 
262 
263 template <typename T, typename P>
265  : t(tt.t)
266  , id(tt.id)
268 {
269  if (tt.pointed_to_object_is_alive && t != nullptr)
270  t->subscribe(&pointed_to_object_is_alive, id);
271 }
272 
273 
274 
275 template <typename T, typename P>
277 {
278  if (pointed_to_object_is_alive && t != nullptr)
279  t->unsubscribe(&pointed_to_object_is_alive, id);
280 }
281 
282 
283 
284 template <typename T, typename P>
285 inline void
287 {
288  if (pointed_to_object_is_alive && t != nullptr)
289  {
290  t->unsubscribe(&pointed_to_object_is_alive, id);
291  delete t;
293  }
294  t = nullptr;
295 }
296 
297 
298 
299 template <typename T, typename P>
300 inline SmartPointer<T, P> &
302 {
303  // optimize if no real action is
304  // requested
305  if (t == tt)
306  return *this;
307 
308  if (pointed_to_object_is_alive && t != nullptr)
309  t->unsubscribe(&pointed_to_object_is_alive, id);
310  t = tt;
311  if (tt != nullptr)
312  tt->subscribe(&pointed_to_object_is_alive, id);
313  return *this;
314 }
315 
316 
317 
318 template <typename T, typename P>
319 template <class Q>
320 inline SmartPointer<T, P> &
322 {
323  // if objects on the left and right
324  // hand side of the operator= are
325  // the same, then this is a no-op
326  if (&tt == this)
327  return *this;
328 
329  if (pointed_to_object_is_alive && t != nullptr)
330  t->unsubscribe(&pointed_to_object_is_alive, id);
331  t = static_cast<T *>(tt);
332  if (tt.pointed_to_object_is_alive && tt != nullptr)
333  tt->subscribe(&pointed_to_object_is_alive, id);
334  return *this;
335 }
336 
337 
338 
339 template <typename T, typename P>
340 inline SmartPointer<T, P> &
342 {
343  // if objects on the left and right
344  // hand side of the operator= are
345  // the same, then this is a no-op
346  if (&tt == this)
347  return *this;
348 
349  if (pointed_to_object_is_alive && t != nullptr)
350  t->unsubscribe(&pointed_to_object_is_alive, id);
351  t = static_cast<T *>(tt);
352  if (tt.pointed_to_object_is_alive && tt != nullptr)
353  tt->subscribe(&pointed_to_object_is_alive, id);
354  return *this;
355 }
356 
357 
358 
359 template <typename T, typename P>
361 {
362  return t;
363 }
364 
365 
366 
367 template <typename T, typename P>
368 inline T &
370 {
371  Assert(t != nullptr, ExcNotInitialized());
373  ExcMessage("The object pointed to is not valid anymore."));
374  return *t;
375 }
376 
377 
378 
379 template <typename T, typename P>
380 inline T *
382 {
383  Assert(t != nullptr, ExcNotInitialized());
385  ExcMessage("The object pointed to is not valid anymore."));
386  return t;
387 }
388 
389 
390 
391 template <typename T, typename P>
392 template <class Q>
393 inline void
395 {
396 #ifdef DEBUG
397  SmartPointer<T, P> aux(t, id);
398  *this = tt;
399  tt = aux;
400 #else
401  std::swap(t, tt.t);
402 #endif
403 }
404 
405 
406 
407 template <typename T, typename P>
408 inline void
410 {
411  if (pointed_to_object_is_alive && t != nullptr)
412  t->unsubscribe(pointed_to_object_is_alive, id);
413 
414  std::swap(t, tt);
415 
416  if (t != nullptr)
417  t->subscribe(pointed_to_object_is_alive, id);
418 }
419 
420 
421 
422 template <typename T, typename P>
423 inline std::size_t
425 {
426  return sizeof(SmartPointer<T, P>);
427 }
428 
429 
430 
431 // The following function is not strictly necessary but is an optimization
432 // for places where you call swap(p1,p2) with SmartPointer objects p1, p2.
433 // Unfortunately, MS Visual Studio (at least up to the 2013 edition) trips
434 // over it when calling std::swap(v1,v2) where v1,v2 are std::vectors of
435 // SmartPointer objects: it can't determine whether it should call std::swap
436 // or ::swap on the individual elements (see bug #184 on our Google Code
437 // site. Consequently, just take this function out of the competition for this
438 // compiler.
439 #ifndef _MSC_VER
440 
445 template <typename T, typename P, class Q>
446 inline void
448 {
449  t1.swap(t2);
450 }
451 #endif
452 
453 
461 template <typename T, typename P>
462 inline void
464 {
465  t1.swap(t2);
466 }
467 
468 
469 
477 template <typename T, typename P>
478 inline void
480 {
481  t2.swap(t1);
482 }
483 
485 
486 #endif
std::atomic< bool > pointed_to_object_is_alive
Definition: smartpointer.h:210
T * operator->() const
Definition: smartpointer.h:381
const std::string id
Definition: smartpointer.h:204
void swap(SmartPointer< T, P > &t1, SmartPointer< T, Q > &t2)
Definition: smartpointer.h:447
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMessage(std::string arg1)
static const char T
#define Assert(cond, exc)
Definition: exceptions.h:1461
T & operator*() const
Definition: smartpointer.h:369
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:401
void swap(SmartPointer< T, Q > &tt)
Definition: smartpointer.h:394
SmartPointer< T, P > & operator=(T *tt)
Definition: smartpointer.h:301
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:400
std::size_t memory_consumption() const
Definition: smartpointer.h:424
static ::ExceptionBase & ExcInternalError()