Reference documentation for deal.II version GIT relicensing-1321-g19b0133728 2024-07-26 07:50:01+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
172 void
174
178 operator T *() const;
179
184 T &
185 operator*() const;
186
191 T *
192 get() const;
193
198 T *
199 operator->() const;
200
210 template <class Q>
211 void
213
222 void
223 swap(T *&tt);
224
230 std::size_t
232
233private:
239 T *t;
240
244 const std::string id;
245
250 std::atomic<bool> pointed_to_object_is_alive;
251};
252
253
254/* --------------------- inline Template functions ------------------------- */
255
256
257template <typename T, typename P>
259 : t(nullptr)
260 , id(typeid(P).name())
261 , pointed_to_object_is_alive(false)
262{}
263
264
265
266template <typename T, typename P>
268 : t(t)
269 , id(typeid(P).name())
270 , pointed_to_object_is_alive(false)
271{
272 if (t != nullptr)
273 t->subscribe(&pointed_to_object_is_alive, id);
274}
275
276
277
278template <typename T, typename P>
279inline SmartPointer<T, P>::SmartPointer(T *t, const std::string &id)
280 : t(t)
281 , id(id)
282 , pointed_to_object_is_alive(false)
283{
284 if (t != nullptr)
285 t->subscribe(&pointed_to_object_is_alive, id);
286}
287
288
289
290template <typename T, typename P>
291template <class Q>
293 : t(tt.t)
294 , id(tt.id)
295 , pointed_to_object_is_alive(false)
296{
297 if (tt.pointed_to_object_is_alive && t != nullptr)
298 t->subscribe(&pointed_to_object_is_alive, id);
299}
300
301
302
303template <typename T, typename P>
305 : t(tt.t)
306 , id(tt.id)
307 , pointed_to_object_is_alive(false)
308{
309 if (tt.pointed_to_object_is_alive && t != nullptr)
310 t->subscribe(&pointed_to_object_is_alive, id);
311}
312
313
314
315template <typename T, typename P>
317{
318 if (pointed_to_object_is_alive && t != nullptr)
319 t->unsubscribe(&pointed_to_object_is_alive, id);
320}
321
322
323
324template <typename T, typename P>
325inline void
327{
328 if (pointed_to_object_is_alive && t != nullptr)
329 {
330 t->unsubscribe(&pointed_to_object_is_alive, id);
331 delete t;
332 Assert(pointed_to_object_is_alive == false, ExcInternalError());
333 }
334 t = nullptr;
335}
336
337
338
339template <typename T, typename P>
340inline SmartPointer<T, P> &
342{
343 // optimize if no real action is
344 // requested
345 if (t == tt)
346 return *this;
347
348 if (pointed_to_object_is_alive && t != nullptr)
349 t->unsubscribe(&pointed_to_object_is_alive, id);
350 t = tt;
351 if (tt != nullptr)
352 tt->subscribe(&pointed_to_object_is_alive, id);
353 return *this;
354}
355
356
357
358template <typename T, typename P>
359template <class Q>
360inline SmartPointer<T, P> &
362{
363 // if objects on the left and right
364 // hand side of the operator= are
365 // the same, then this is a no-op
366 if (&tt == this)
367 return *this;
368
369 if (pointed_to_object_is_alive && t != nullptr)
370 t->unsubscribe(&pointed_to_object_is_alive, id);
371 t = static_cast<T *>(tt);
372 if (tt.pointed_to_object_is_alive && tt != nullptr)
373 tt->subscribe(&pointed_to_object_is_alive, id);
374 return *this;
375}
376
377
378
379template <typename T, typename P>
380inline SmartPointer<T, P> &
382{
383 // if objects on the left and right
384 // hand side of the operator= are
385 // the same, then this is a no-op
386 if (&tt == this)
387 return *this;
388
389 if (pointed_to_object_is_alive && t != nullptr)
390 t->unsubscribe(&pointed_to_object_is_alive, id);
391 t = static_cast<T *>(tt);
392 if (tt.pointed_to_object_is_alive && tt != nullptr)
393 tt->subscribe(&pointed_to_object_is_alive, id);
394 return *this;
395}
396
397
398
399template <typename T, typename P>
401{
402 return t;
403}
404
405
406
407template <typename T, typename P>
408inline T &
410{
411 Assert(t != nullptr, ExcNotInitialized());
412 Assert(pointed_to_object_is_alive,
413 ExcMessage("The object pointed to is not valid anymore."));
414 return *t;
415}
416
417
418
419template <typename T, typename P>
420inline T *
422{
423 Assert(t != nullptr, ExcNotInitialized());
424 Assert(pointed_to_object_is_alive,
425 ExcMessage("The object pointed to is not valid anymore."));
426 return t;
427}
428
429
430
431template <typename T, typename P>
432inline T *
434{
435 return this->get();
436}
437
438
439
440template <typename T, typename P>
441template <class Q>
442inline void
444{
445#ifdef DEBUG
446 SmartPointer<T, P> aux(t, id);
447 *this = tt;
448 tt = aux;
449#else
450 std::swap(t, tt.t);
451#endif
452}
453
454
455
456template <typename T, typename P>
457inline void
459{
460 if (pointed_to_object_is_alive && t != nullptr)
461 t->unsubscribe(pointed_to_object_is_alive, id);
462
463 std::swap(t, tt);
464
465 if (t != nullptr)
466 t->subscribe(pointed_to_object_is_alive, id);
467}
468
469
470
471template <typename T, typename P>
472inline std::size_t
474{
475 return sizeof(SmartPointer<T, P>);
476}
477
478
479
480// The following function is not strictly necessary but is an optimization
481// for places where you call swap(p1,p2) with SmartPointer objects p1, p2.
482// Unfortunately, MS Visual Studio (at least up to the 2013 edition) trips
483// over it when calling std::swap(v1,v2) where v1,v2 are std::vectors of
484// SmartPointer objects: it can't determine whether it should call std::swap
485// or ::swap on the individual elements (see bug #184 on our Google Code
486// site. Consequently, just take this function out of the competition for this
487// compiler.
488#ifndef _MSC_VER
494template <typename T, typename P, class Q>
495inline void
497{
498 t1.swap(t2);
499}
500#endif
501
502
510template <typename T, typename P>
511inline void
513{
514 t1.swap(t2);
515}
516
517
518
526template <typename T, typename P>
527inline void
529{
530 t2.swap(t1);
531}
532
534
535#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_DEPRECATED
Definition config.h:207
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:503
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:504
#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)