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