Reference documentation for deal.II version GIT relicensing-222-g16f23ad599 2024-03-28 18:20:02+00:00
\(\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// SPDX-License-Identifier: LGPL-2.1-or-later
4// Copyright (C) 1998 - 2023 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Part of the source code is dual licensed under Apache-2.0 WITH
9// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
10// governing the source code and code contributions can be found in
11// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
12//
13// ------------------------------------------------------------------------
14
15#ifndef dealii_smartpointer_h
16#define dealii_smartpointer_h
17
18
19#include <deal.II/base/config.h>
20
22
23#include <atomic>
24#include <typeinfo>
25
27
91template <typename T, typename P = void>
93{
94public:
100
105 template <class Q>
107
113
122 SmartPointer(T *t, const std::string &id);
123
131
136
144 operator=(T *tt);
145
150 template <class Q>
153
160
164 void
166
170 operator T *() const;
171
176 T &
177 operator*() const;
178
183 T *
184 get() const;
185
190 T *
191 operator->() const;
192
202 template <class Q>
203 void
205
214 void
215 swap(T *&tt);
216
222 std::size_t
224
225private:
231 T *t;
232
236 const std::string id;
237
242 std::atomic<bool> pointed_to_object_is_alive;
243};
244
245
246/* --------------------- inline Template functions ------------------------- */
247
248
249template <typename T, typename P>
251 : t(nullptr)
252 , id(typeid(P).name())
253 , pointed_to_object_is_alive(false)
254{}
255
256
257
258template <typename T, typename P>
260 : t(t)
261 , id(typeid(P).name())
262 , pointed_to_object_is_alive(false)
263{
264 if (t != nullptr)
265 t->subscribe(&pointed_to_object_is_alive, id);
266}
267
268
269
270template <typename T, typename P>
271inline SmartPointer<T, P>::SmartPointer(T *t, const std::string &id)
272 : t(t)
273 , id(id)
274 , pointed_to_object_is_alive(false)
275{
276 if (t != nullptr)
277 t->subscribe(&pointed_to_object_is_alive, id);
278}
279
280
281
282template <typename T, typename P>
283template <class Q>
285 : t(tt.t)
286 , id(tt.id)
287 , pointed_to_object_is_alive(false)
288{
289 if (tt.pointed_to_object_is_alive && t != nullptr)
290 t->subscribe(&pointed_to_object_is_alive, id);
291}
292
293
294
295template <typename T, typename P>
297 : t(tt.t)
298 , id(tt.id)
299 , pointed_to_object_is_alive(false)
300{
301 if (tt.pointed_to_object_is_alive && t != nullptr)
302 t->subscribe(&pointed_to_object_is_alive, id);
303}
304
305
306
307template <typename T, typename P>
309{
310 if (pointed_to_object_is_alive && t != nullptr)
311 t->unsubscribe(&pointed_to_object_is_alive, id);
312}
313
314
315
316template <typename T, typename P>
317inline void
319{
320 if (pointed_to_object_is_alive && t != nullptr)
321 {
322 t->unsubscribe(&pointed_to_object_is_alive, id);
323 delete t;
324 Assert(pointed_to_object_is_alive == false, ExcInternalError());
325 }
326 t = nullptr;
327}
328
329
330
331template <typename T, typename P>
332inline SmartPointer<T, P> &
334{
335 // optimize if no real action is
336 // requested
337 if (t == tt)
338 return *this;
339
340 if (pointed_to_object_is_alive && t != nullptr)
341 t->unsubscribe(&pointed_to_object_is_alive, id);
342 t = tt;
343 if (tt != nullptr)
344 tt->subscribe(&pointed_to_object_is_alive, id);
345 return *this;
346}
347
348
349
350template <typename T, typename P>
351template <class Q>
352inline SmartPointer<T, P> &
354{
355 // if objects on the left and right
356 // hand side of the operator= are
357 // the same, then this is a no-op
358 if (&tt == this)
359 return *this;
360
361 if (pointed_to_object_is_alive && t != nullptr)
362 t->unsubscribe(&pointed_to_object_is_alive, id);
363 t = static_cast<T *>(tt);
364 if (tt.pointed_to_object_is_alive && tt != nullptr)
365 tt->subscribe(&pointed_to_object_is_alive, id);
366 return *this;
367}
368
369
370
371template <typename T, typename P>
372inline SmartPointer<T, P> &
374{
375 // if objects on the left and right
376 // hand side of the operator= are
377 // the same, then this is a no-op
378 if (&tt == this)
379 return *this;
380
381 if (pointed_to_object_is_alive && t != nullptr)
382 t->unsubscribe(&pointed_to_object_is_alive, id);
383 t = static_cast<T *>(tt);
384 if (tt.pointed_to_object_is_alive && tt != nullptr)
385 tt->subscribe(&pointed_to_object_is_alive, id);
386 return *this;
387}
388
389
390
391template <typename T, typename P>
393{
394 return t;
395}
396
397
398
399template <typename T, typename P>
400inline T &
402{
403 Assert(t != nullptr, ExcNotInitialized());
404 Assert(pointed_to_object_is_alive,
405 ExcMessage("The object pointed to is not valid anymore."));
406 return *t;
407}
408
409
410
411template <typename T, typename P>
412inline T *
414{
415 Assert(t != nullptr, ExcNotInitialized());
416 Assert(pointed_to_object_is_alive,
417 ExcMessage("The object pointed to is not valid anymore."));
418 return t;
419}
420
421
422
423template <typename T, typename P>
424inline T *
426{
427 return this->get();
428}
429
430
431
432template <typename T, typename P>
433template <class Q>
434inline void
436{
437#ifdef DEBUG
438 SmartPointer<T, P> aux(t, id);
439 *this = tt;
440 tt = aux;
441#else
442 std::swap(t, tt.t);
443#endif
444}
445
446
447
448template <typename T, typename P>
449inline void
451{
452 if (pointed_to_object_is_alive && t != nullptr)
453 t->unsubscribe(pointed_to_object_is_alive, id);
454
455 std::swap(t, tt);
456
457 if (t != nullptr)
458 t->subscribe(pointed_to_object_is_alive, id);
459}
460
461
462
463template <typename T, typename P>
464inline std::size_t
466{
467 return sizeof(SmartPointer<T, P>);
468}
469
470
471
472// The following function is not strictly necessary but is an optimization
473// for places where you call swap(p1,p2) with SmartPointer objects p1, p2.
474// Unfortunately, MS Visual Studio (at least up to the 2013 edition) trips
475// over it when calling std::swap(v1,v2) where v1,v2 are std::vectors of
476// SmartPointer objects: it can't determine whether it should call std::swap
477// or ::swap on the individual elements (see bug #184 on our Google Code
478// site. Consequently, just take this function out of the competition for this
479// compiler.
480#ifndef _MSC_VER
486template <typename T, typename P, class Q>
487inline void
489{
490 t1.swap(t2);
491}
492#endif
493
494
502template <typename T, typename P>
503inline void
505{
506 t1.swap(t2);
507}
508
509
510
518template <typename T, typename P>
519inline void
521{
522 t2.swap(t1);
523}
524
526
527#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
T * get() 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:502
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:503
#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)