Reference documentation for deal.II version 9.5.0
\(\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\}}\)
Loading...
Searching...
No Matches
smartpointer.h
Go to the documentation of this file.
1// ---------------------------------------------------------------------
2//
3// Copyright (C) 1998 - 2021 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
66template <typename T, typename P = void>
68{
69public:
75
80 template <class Q>
82
88
97 SmartPointer(T *t, const std::string &id);
98
106
111
119 operator=(T *tt);
120
125 template <class Q>
128
135
139 void
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
192
193private:
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
217template <typename T, typename P>
219 : t(nullptr)
220 , id(typeid(P).name())
221 , pointed_to_object_is_alive(false)
222{}
223
224
225
226template <typename T, typename P>
228 : t(t)
229 , id(typeid(P).name())
230 , pointed_to_object_is_alive(false)
231{
232 if (t != nullptr)
233 t->subscribe(&pointed_to_object_is_alive, id);
234}
235
236
237
238template <typename T, typename P>
239inline SmartPointer<T, P>::SmartPointer(T *t, const std::string &id)
240 : t(t)
241 , id(id)
242 , pointed_to_object_is_alive(false)
243{
244 if (t != nullptr)
245 t->subscribe(&pointed_to_object_is_alive, id);
246}
247
248
249
250template <typename T, typename P>
251template <class Q>
253 : t(tt.t)
254 , id(tt.id)
255 , pointed_to_object_is_alive(false)
256{
257 if (tt.pointed_to_object_is_alive && t != nullptr)
258 t->subscribe(&pointed_to_object_is_alive, id);
259}
260
261
262
263template <typename T, typename P>
265 : t(tt.t)
266 , id(tt.id)
267 , pointed_to_object_is_alive(false)
268{
269 if (tt.pointed_to_object_is_alive && t != nullptr)
270 t->subscribe(&pointed_to_object_is_alive, id);
271}
272
273
274
275template <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
284template <typename T, typename P>
285inline void
287{
288 if (pointed_to_object_is_alive && t != nullptr)
289 {
290 t->unsubscribe(&pointed_to_object_is_alive, id);
291 delete t;
292 Assert(pointed_to_object_is_alive == false, ExcInternalError());
293 }
294 t = nullptr;
295}
296
297
298
299template <typename T, typename P>
300inline 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
318template <typename T, typename P>
319template <class Q>
320inline 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
339template <typename T, typename P>
340inline 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
359template <typename T, typename P>
361{
362 return t;
363}
364
365
366
367template <typename T, typename P>
368inline T &
370{
371 Assert(t != nullptr, ExcNotInitialized());
372 Assert(pointed_to_object_is_alive,
373 ExcMessage("The object pointed to is not valid anymore."));
374 return *t;
375}
376
377
378
379template <typename T, typename P>
380inline T *
382{
383 Assert(t != nullptr, ExcNotInitialized());
384 Assert(pointed_to_object_is_alive,
385 ExcMessage("The object pointed to is not valid anymore."));
386 return t;
387}
388
389
390
391template <typename T, typename P>
392template <class Q>
393inline 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
407template <typename T, typename P>
408inline 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
422template <typename T, typename P>
423inline 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
445template <typename T, typename P, class Q>
446inline void
448{
449 t1.swap(t2);
450}
451#endif
452
453
461template <typename T, typename P>
462inline void
464{
465 t1.swap(t2);
466}
467
468
469
477template <typename T, typename P>
478inline void
480{
481 t2.swap(t1);
482}
483
485
486#endif
const std::string id
T * operator->() const
void swap(SmartPointer< T, Q > &tt)
SmartPointer(const SmartPointer< T, P > &tt)
SmartPointer< T, P > & operator=(const SmartPointer< T, P > &tt)
std::atomic< bool > pointed_to_object_is_alive
SmartPointer(const SmartPointer< T, Q > &tt)
std::size_t memory_consumption() const
SmartPointer< T, P > & operator=(const SmartPointer< T, Q > &tt)
SmartPointer(T *t, const std::string &id)
void swap(T *&tt)
SmartPointer< T, P > & operator=(T *tt)
T & operator*() const
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:472
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:473
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMessage(std::string arg1)
void swap(SmartPointer< T, P > &t1, SmartPointer< T, Q > &t2)