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\}}\)
subscriptor.cc
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
18
19#include <algorithm>
20#include <iostream>
21#include <string>
22#include <typeinfo>
23
25
26
27static const char *unknown_subscriber = "unknown subscriber";
28
29
30std::mutex Subscriptor::mutex;
31
32
34 : counter(0)
35 , object_info(subscriptor.object_info)
36{
37 for (const auto validity_ptr : subscriptor.validity_pointers)
38 *validity_ptr = false;
39 subscriptor.validity_pointers.clear();
40}
41
42
43
45{
46 for (const auto validity_ptr : validity_pointers)
47 *validity_ptr = false;
48 object_info = nullptr;
49}
50
51
52void
54{
55 // Check whether there are still subscriptions to this object. If so, output
56 // the actual name of the class to which this object belongs, i.e. the most
57 // derived class. Note that the name may be mangled, so it need not be the
58 // clear-text class name. However, you can obtain the latter by running the
59 // c++filt program over the output.
60#ifdef DEBUG
61
62 // If there are still active pointers, show a message and kill the program.
63 // However, under some circumstances, this is not so desirable. For example,
64 // in code like this:
65 //
66 // Triangulation tria;
67 // DoFHandler *dh = new DoFHandler(tria);
68 // ...some function that throws an exception
69 //
70 // the exception will lead to the destruction of the triangulation, but since
71 // the dof_handler is on the heap it will not be destroyed. This will trigger
72 // an assertion in the triangulation. If we kill the program at this point, we
73 // will never be able to learn what caused the problem. In this situation,
74 // just display a message and continue the program.
75 if (counter != 0)
76 {
77# if __cpp_lib_uncaught_exceptions >= 201411
78 // std::uncaught_exception() is deprecated in c++17
79 if (std::uncaught_exceptions() == 0)
80# else
81 if (std::uncaught_exception() == false)
82# endif
83 {
84 std::string infostring;
85 for (const auto &map_entry : counter_map)
86 {
87 if (map_entry.second > 0)
88 infostring += std::string("\n from Subscriber ") +
89 std::string(map_entry.first);
90 }
91
92 if (infostring.empty())
93 infostring = "<none>";
94
96 ExcInUse(counter.load(),
97 object_info->name(),
98 infostring));
99 }
100 else
101 {
102 std::cerr
103 << "---------------------------------------------------------"
104 << std::endl
105 << "An object pointed to by a SmartPointer is being destroyed."
106 << std::endl
107 << "Under normal circumstances, this would abort the program."
108 << std::endl
109 << "However, another exception is being processed at the"
110 << std::endl
111 << "moment, so the program will continue to run to allow"
112 << std::endl
113 << "this exception to be processed." << std::endl
114 << "---------------------------------------------------------"
115 << std::endl;
116 }
117 }
118#endif
119}
120
121
122
125{
126 for (const auto validity_ptr : s.validity_pointers)
127 *validity_ptr = false;
128 s.validity_pointers.clear();
129 object_info = s.object_info;
130 return *this;
131}
132
133
134
135void
136Subscriptor::subscribe(std::atomic<bool> *const validity,
137 const std::string & id) const
138{
139 std::lock_guard<std::mutex> lock(mutex);
140
141 if (object_info == nullptr)
142 object_info = &typeid(*this);
143 ++counter;
144
145 const std::string &name = id.empty() ? unknown_subscriber : id;
146
147 ++counter_map[name];
148
149 *validity = true;
150 validity_pointers.push_back(validity);
151}
152
153
154
155void
156Subscriptor::unsubscribe(std::atomic<bool> *const validity,
157 const std::string & id) const
158{
159 const std::string &name = id.empty() ? unknown_subscriber : id;
160
161 if (counter == 0)
162 {
164 // This is for the case that we do not abort after the exception
165 return;
166 }
167
168 std::lock_guard<std::mutex> lock(mutex);
169
170 map_iterator it = counter_map.find(name);
171 if (it == counter_map.end())
172 {
173 AssertNothrow(it != counter_map.end(),
174 ExcNoSubscriber(object_info->name(), name));
175 // This is for the case that we do not abort after the exception
176 return;
177 }
178 if (it->second == 0)
179 {
180 AssertNothrow(it->second > 0, ExcNoSubscriber(object_info->name(), name));
181 // This is for the case that we do not abort after the exception
182 return;
183 }
184
185 auto validity_ptr_it =
186 std::find(validity_pointers.begin(), validity_pointers.end(), validity);
187 if (validity_ptr_it == validity_pointers.end())
188 {
190 validity_ptr_it != validity_pointers.end(),
192 "This Subscriptor object does not know anything about the supplied pointer!"));
193 return;
194 }
195
196 validity_pointers.erase(validity_ptr_it);
197 --counter;
198 --it->second;
199}
200
201
202
203void
205{
207}
208
Subscriptor & operator=(const Subscriptor &)
Definition: subscriptor.h:292
virtual ~Subscriptor()
Definition: subscriptor.cc:44
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:402
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:403
std::vector< std::atomic< bool > * > validity_pointers
Definition: subscriptor.h:242
void unsubscribe(std::atomic< bool > *const validity, const std::string &identifier="") const
Definition: subscriptor.cc:156
std::atomic< unsigned int > counter
Definition: subscriptor.h:220
void check_no_subscribers() const noexcept
Definition: subscriptor.cc:53
void list_subscribers() const
Definition: subscriptor.cc:204
const std::type_info * object_info
Definition: subscriptor.h:250
void subscribe(std::atomic< bool > *const validity, const std::string &identifier="") const
Definition: subscriptor.cc:136
static ::ExceptionBase & ExcInUse(int arg1, std::string arg2, std::string arg3)
std::map< std::string, unsigned int > counter_map
Definition: subscriptor.h:226
static std::mutex mutex
Definition: subscriptor.h:272
#define AssertNothrow(cond, exc)
Definition: exceptions.h:1528
static ::ExceptionBase & ExcNoSubscriber(std::string arg1, std::string arg2)
decltype(counter_map)::iterator map_iterator
Definition: subscriptor.h:236
static ::ExceptionBase & ExcMessage(std::string arg1)
LogStream deallog
Definition: logstream.cc:37
static const char * unknown_subscriber
Definition: subscriptor.cc:27