Reference documentation for deal.II version Git d4ec8156ca 2019-11-18 14:03:00 -0700
\(\newcommand{\dealcoloneq}{\mathrel{\vcenter{:}}=}\)
smartpointer.h
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 
22 #include <deal.II/base/exceptions.h>
23 
24 #include <atomic>
25 #include <typeinfo>
26 
27 DEAL_II_NAMESPACE_OPEN
28 
67 template <typename T, typename P = void>
69 {
70 public:
75  SmartPointer();
76 
81  template <class Q>
83 
89 
98  SmartPointer(T *t, const std::string &id);
99 
106  SmartPointer(T *t);
107 
111  ~SmartPointer();
112 
120  operator=(T *tt);
121 
126  template <class Q>
128  operator=(const SmartPointer<T, Q> &tt);
129 
135  operator=(const SmartPointer<T, P> &tt);
136 
140  void
141  clear();
142 
146  operator T *() const;
147 
152  T &operator*() const;
153 
158  T *operator->() const;
159 
169  template <class Q>
170  void
172 
181  void
182  swap(T *&tt);
183 
189  std::size_t
190  memory_consumption() const;
191 
192 private:
198  T *t;
199 
203  const std::string id;
204 
209  std::atomic<bool> pointed_to_object_is_alive;
210 };
211 
212 
213 /* --------------------- inline Template functions ------------------------- */
214 
215 
216 template <typename T, typename P>
218  : t(nullptr)
219  , id(typeid(P).name())
221 {}
222 
223 
224 
225 template <typename T, typename P>
227  : t(t)
228  , id(typeid(P).name())
230 {
231  if (t != nullptr)
232  t->subscribe(&pointed_to_object_is_alive, id);
233 }
234 
235 
236 
237 template <typename T, typename P>
238 inline SmartPointer<T, P>::SmartPointer(T *t, const std::string &id)
239  : t(t)
240  , id(id)
242 {
243  if (t != nullptr)
244  t->subscribe(&pointed_to_object_is_alive, id);
245 }
246 
247 
248 
249 template <typename T, typename P>
250 template <class Q>
252  : t(tt.t)
253  , id(tt.id)
255 {
256  if (tt.pointed_to_object_is_alive && t != nullptr)
257  t->subscribe(&pointed_to_object_is_alive, id);
258 }
259 
260 
261 
262 template <typename T, typename P>
264  : t(tt.t)
265  , id(tt.id)
267 {
268  if (tt.pointed_to_object_is_alive && t != nullptr)
269  t->subscribe(&pointed_to_object_is_alive, id);
270 }
271 
272 
273 
274 template <typename T, typename P>
276 {
277  if (pointed_to_object_is_alive && t != nullptr)
278  t->unsubscribe(&pointed_to_object_is_alive, id);
279 }
280 
281 
282 
283 template <typename T, typename P>
284 inline void
286 {
287  if (pointed_to_object_is_alive && t != nullptr)
288  {
289  t->unsubscribe(&pointed_to_object_is_alive, id);
290  delete t;
292  }
293  t = nullptr;
294 }
295 
296 
297 
298 template <typename T, typename P>
299 inline SmartPointer<T, P> &
301 {
302  // optimize if no real action is
303  // requested
304  if (t == tt)
305  return *this;
306 
307  if (pointed_to_object_is_alive && t != nullptr)
308  t->unsubscribe(&pointed_to_object_is_alive, id);
309  t = tt;
310  if (tt != nullptr)
311  tt->subscribe(&pointed_to_object_is_alive, id);
312  return *this;
313 }
314 
315 
316 
317 template <typename T, typename P>
318 template <class Q>
319 inline SmartPointer<T, P> &
321 {
322  // if objects on the left and right
323  // hand side of the operator= are
324  // the same, then this is a no-op
325  if (&tt == this)
326  return *this;
327 
328  if (pointed_to_object_is_alive && t != nullptr)
329  t->unsubscribe(&pointed_to_object_is_alive, id);
330  t = static_cast<T *>(tt);
331  if (tt.pointed_to_object_is_alive && tt != nullptr)
332  tt->subscribe(&pointed_to_object_is_alive, id);
333  return *this;
334 }
335 
336 
337 
338 template <typename T, typename P>
339 inline SmartPointer<T, P> &
341 {
342  // if objects on the left and right
343  // hand side of the operator= are
344  // the same, then this is a no-op
345  if (&tt == this)
346  return *this;
347 
348  if (pointed_to_object_is_alive && t != nullptr)
349  t->unsubscribe(&pointed_to_object_is_alive, id);
350  t = static_cast<T *>(tt);
351  if (tt.pointed_to_object_is_alive && tt != nullptr)
352  tt->subscribe(&pointed_to_object_is_alive, id);
353  return *this;
354 }
355 
356 
357 
358 template <typename T, typename P>
360 {
361  return t;
362 }
363 
364 
365 
366 template <typename T, typename P>
368 {
369  Assert(t != nullptr, ExcNotInitialized());
371  ExcMessage("The object pointed to is not valid anymore."));
372  return *t;
373 }
374 
375 
376 
377 template <typename T, typename P>
379 {
380  Assert(t != nullptr, ExcNotInitialized());
382  ExcMessage("The object pointed to is not valid anymore."));
383  return t;
384 }
385 
386 
387 
388 template <typename T, typename P>
389 template <class Q>
390 inline void
392 {
393 #ifdef DEBUG
394  SmartPointer<T, P> aux(t, id);
395  *this = tt;
396  tt = aux;
397 #else
398  std::swap(t, tt.t);
399 #endif
400 }
401 
402 
403 
404 template <typename T, typename P>
405 inline void
407 {
408  if (pointed_to_object_is_alive && t != nullptr)
409  t->unsubscribe(pointed_to_object_is_alive, id);
410 
411  std::swap(t, tt);
412 
413  if (t != nullptr)
414  t->subscribe(pointed_to_object_is_alive, id);
415 }
416 
417 
418 
419 template <typename T, typename P>
420 inline std::size_t
422 {
423  return sizeof(SmartPointer<T, P>);
424 }
425 
426 
427 
428 // The following function is not strictly necessary but is an optimization
429 // for places where you call swap(p1,p2) with SmartPointer objects p1, p2.
430 // Unfortunately, MS Visual Studio (at least up to the 2013 edition) trips
431 // over it when calling std::swap(v1,v2) where v1,v2 are std::vectors of
432 // SmartPointer objects: it can't determine whether it should call std::swap
433 // or ::swap on the individual elements (see bug #184 on our Google Code
434 // site. Consequently, just take this function out of the competition for this
435 // compiler.
436 #ifndef _MSC_VER
437 
442 template <typename T, typename P, class Q>
443 inline void
445 {
446  t1.swap(t2);
447 }
448 #endif
449 
450 
458 template <typename T, typename P>
459 inline void
460 swap(SmartPointer<T, P> &t1, T *&t2)
461 {
462  t1.swap(t2);
463 }
464 
465 
466 
474 template <typename T, typename P>
475 inline void
476 swap(T *&t1, SmartPointer<T, P> &t2)
477 {
478  t2.swap(t1);
479 }
480 
481 DEAL_II_NAMESPACE_CLOSE
482 
483 #endif
std::atomic< bool > pointed_to_object_is_alive
Definition: smartpointer.h:209
T * operator->() const
Definition: smartpointer.h:378
const std::string id
Definition: smartpointer.h:203
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
Definition: exceptions.h:1411
T & operator*() const
Definition: smartpointer.h:367
void swap(SmartPointer< T, Q > &tt)
Definition: smartpointer.h:391
SmartPointer< T, P > & operator=(T *tt)
Definition: smartpointer.h:300
void swap(Vector< Number > &u, Vector< Number > &v)
Definition: vector.h:1376
std::size_t memory_consumption() const
Definition: smartpointer.h:421
static ::ExceptionBase & ExcInternalError()