Reference documentation for deal.II version 9.3.3
\(\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
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
120
125 template <class Q>
128
135
139 void
141
145 operator T *() const;
146
151 T &operator*() const;
152
157 T *operator->() const;
158
168 template <class Q>
169 void
171
180 void
181 swap(T *&tt);
182
188 std::size_t
190
191private:
197 T *t;
198
202 const std::string id;
203
208 std::atomic<bool> pointed_to_object_is_alive;
209};
210
211
212/* --------------------- inline Template functions ------------------------- */
213
214
215template <typename T, typename P>
217 : t(nullptr)
218 , id(typeid(P).name())
219 , pointed_to_object_is_alive(false)
220{}
221
222
223
224template <typename T, typename P>
226 : t(t)
227 , id(typeid(P).name())
228 , pointed_to_object_is_alive(false)
229{
230 if (t != nullptr)
231 t->subscribe(&pointed_to_object_is_alive, id);
232}
233
234
235
236template <typename T, typename P>
237inline SmartPointer<T, P>::SmartPointer(T *t, const std::string &id)
238 : t(t)
239 , id(id)
240 , pointed_to_object_is_alive(false)
241{
242 if (t != nullptr)
243 t->subscribe(&pointed_to_object_is_alive, id);
244}
245
246
247
248template <typename T, typename P>
249template <class Q>
251 : t(tt.t)
252 , id(tt.id)
253 , pointed_to_object_is_alive(false)
254{
255 if (tt.pointed_to_object_is_alive && t != nullptr)
256 t->subscribe(&pointed_to_object_is_alive, id);
257}
258
259
260
261template <typename T, typename P>
263 : t(tt.t)
264 , id(tt.id)
265 , pointed_to_object_is_alive(false)
266{
267 if (tt.pointed_to_object_is_alive && t != nullptr)
268 t->subscribe(&pointed_to_object_is_alive, id);
269}
270
271
272
273template <typename T, typename P>
275{
276 if (pointed_to_object_is_alive && t != nullptr)
277 t->unsubscribe(&pointed_to_object_is_alive, id);
278}
279
280
281
282template <typename T, typename P>
283inline void
285{
286 if (pointed_to_object_is_alive && t != nullptr)
287 {
288 t->unsubscribe(&pointed_to_object_is_alive, id);
289 delete t;
290 Assert(pointed_to_object_is_alive == false, ExcInternalError());
291 }
292 t = nullptr;
293}
294
295
296
297template <typename T, typename P>
298inline SmartPointer<T, P> &
300{
301 // optimize if no real action is
302 // requested
303 if (t == tt)
304 return *this;
305
306 if (pointed_to_object_is_alive && t != nullptr)
307 t->unsubscribe(&pointed_to_object_is_alive, id);
308 t = tt;
309 if (tt != nullptr)
310 tt->subscribe(&pointed_to_object_is_alive, id);
311 return *this;
312}
313
314
315
316template <typename T, typename P>
317template <class Q>
318inline SmartPointer<T, P> &
320{
321 // if objects on the left and right
322 // hand side of the operator= are
323 // the same, then this is a no-op
324 if (&tt == this)
325 return *this;
326
327 if (pointed_to_object_is_alive && t != nullptr)
328 t->unsubscribe(&pointed_to_object_is_alive, id);
329 t = static_cast<T *>(tt);
330 if (tt.pointed_to_object_is_alive && tt != nullptr)
331 tt->subscribe(&pointed_to_object_is_alive, id);
332 return *this;
333}
334
335
336
337template <typename T, typename P>
338inline SmartPointer<T, P> &
340{
341 // if objects on the left and right
342 // hand side of the operator= are
343 // the same, then this is a no-op
344 if (&tt == this)
345 return *this;
346
347 if (pointed_to_object_is_alive && t != nullptr)
348 t->unsubscribe(&pointed_to_object_is_alive, id);
349 t = static_cast<T *>(tt);
350 if (tt.pointed_to_object_is_alive && tt != nullptr)
351 tt->subscribe(&pointed_to_object_is_alive, id);
352 return *this;
353}
354
355
356
357template <typename T, typename P>
359{
360 return t;
361}
362
363
364
365template <typename T, typename P>
367{
368 Assert(t != nullptr, ExcNotInitialized());
369 Assert(pointed_to_object_is_alive,
370 ExcMessage("The object pointed to is not valid anymore."));
371 return *t;
372}
373
374
375
376template <typename T, typename P>
378{
379 Assert(t != nullptr, ExcNotInitialized());
380 Assert(pointed_to_object_is_alive,
381 ExcMessage("The object pointed to is not valid anymore."));
382 return t;
383}
384
385
386
387template <typename T, typename P>
388template <class Q>
389inline void
391{
392#ifdef DEBUG
393 SmartPointer<T, P> aux(t, id);
394 *this = tt;
395 tt = aux;
396#else
397 std::swap(t, tt.t);
398#endif
399}
400
401
402
403template <typename T, typename P>
404inline void
406{
407 if (pointed_to_object_is_alive && t != nullptr)
408 t->unsubscribe(pointed_to_object_is_alive, id);
409
410 std::swap(t, tt);
411
412 if (t != nullptr)
413 t->subscribe(pointed_to_object_is_alive, id);
414}
415
416
417
418template <typename T, typename P>
419inline std::size_t
421{
422 return sizeof(SmartPointer<T, P>);
423}
424
425
426
427// The following function is not strictly necessary but is an optimization
428// for places where you call swap(p1,p2) with SmartPointer objects p1, p2.
429// Unfortunately, MS Visual Studio (at least up to the 2013 edition) trips
430// over it when calling std::swap(v1,v2) where v1,v2 are std::vectors of
431// SmartPointer objects: it can't determine whether it should call std::swap
432// or ::swap on the individual elements (see bug #184 on our Google Code
433// site. Consequently, just take this function out of the competition for this
434// compiler.
435#ifndef _MSC_VER
441template <typename T, typename P, class Q>
442inline void
444{
445 t1.swap(t2);
446}
447#endif
448
449
457template <typename T, typename P>
458inline void
460{
461 t1.swap(t2);
462}
463
464
465
473template <typename T, typename P>
474inline void
476{
477 t2.swap(t1);
478}
479
481
482#endif
void swap(BlockIndices &u, BlockIndices &v)
SmartPointer(T *t)
Definition: smartpointer.h:225
const std::string id
Definition: smartpointer.h:202
T * operator->() const
Definition: smartpointer.h:377
void swap(SmartPointer< T, Q > &tt)
Definition: smartpointer.h:390
SmartPointer(const SmartPointer< T, P > &tt)
Definition: smartpointer.h:262
SmartPointer< T, P > & operator=(const SmartPointer< T, P > &tt)
Definition: smartpointer.h:339
std::atomic< bool > pointed_to_object_is_alive
Definition: smartpointer.h:208
SmartPointer(const SmartPointer< T, Q > &tt)
Definition: smartpointer.h:250
std::size_t memory_consumption() const
Definition: smartpointer.h:420
SmartPointer< T, P > & operator=(const SmartPointer< T, Q > &tt)
Definition: smartpointer.h:319
SmartPointer(T *t, const std::string &id)
Definition: smartpointer.h:237
void swap(T *&tt)
Definition: smartpointer.h:405
SmartPointer< T, P > & operator=(T *tt)
Definition: smartpointer.h:299
T & operator*() const
Definition: smartpointer.h:366
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:402
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:403
#define Assert(cond, exc)
Definition: exceptions.h:1465
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcNotInitialized()
static ::ExceptionBase & ExcMessage(std::string arg1)
static const char T
void swap(SmartPointer< T, P > &t1, SmartPointer< T, Q > &t2)
Definition: smartpointer.h:443