~ubuntu-branches/ubuntu/natty/deal.ii/natty

« back to all changes in this revision

Viewing changes to base/include/base/subscriptor.h

  • Committer: Bazaar Package Importer
  • Author(s): Adam C. Powell, IV
  • Date: 2009-05-08 23:13:50 UTC
  • Revision ID: james.westby@ubuntu.com-20090508231350-rrh1ltgi0tifabwc
Tags: upstream-6.2.0
ImportĀ upstreamĀ versionĀ 6.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//---------------------------------------------------------------------------
 
2
//    $Id: subscriptor.h 15292 2007-10-11 16:28:49Z kanschat $
 
3
//    Version: $Name$
 
4
//
 
5
//    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 by the deal.II authors
 
6
//
 
7
//    This file is subject to QPL and may not be  distributed
 
8
//    without copyright and license information. Please refer
 
9
//    to the file deal.II/doc/license.html for the  text  and
 
10
//    further information on this license.
 
11
//
 
12
//---------------------------------------------------------------------------
 
13
#ifndef __deal2__subscriptor_h
 
14
#define __deal2__subscriptor_h
 
15
 
 
16
 
 
17
#include <base/config.h>
 
18
#include <base/exceptions.h>
 
19
 
 
20
#include <typeinfo>
 
21
#include <map>
 
22
#include <string>
 
23
 
 
24
DEAL_II_NAMESPACE_OPEN
 
25
 
 
26
/**
 
27
 * Handling of subscriptions.
 
28
 *
 
29
 * This class, as a base class, allows to keep track of other objects
 
30
 * using a specific object. It is used, when an object, given to a
 
31
 * constructor by reference, is stored. Then, the original object may
 
32
 * not be deleted before the dependent object is deleted. You can assert
 
33
 * this constraint by letting the object passed be derived from this class
 
34
 * and let the user subscribe() to this object. The destructor the used
 
35
 * object inherits from the Subscriptor class then will lead to an error
 
36
 * when destruction is attempted while there are still subscriptions.
 
37
 *
 
38
 * The utility of this class is even enhanced by providing identifying
 
39
 * strings to the functions subscribe() and unsubscribe(). In case of
 
40
 * a hanging subscription during destruction, this string will be
 
41
 * listed in the exception's message. For reasons of efficiency, these
 
42
 * strings are handled as <tt>const char*</tt>. Therefore, the
 
43
 * pointers provided to subscribe() and to unsubscribe() must be the
 
44
 * same. Strings with equal contents will not be recognized to be the
 
45
 * same. The handling in SmartPointer will take care of this.
 
46
 *
 
47
 * @note Due to a problem with <tt>volatile</tt> declarations, this
 
48
 * additional feature is switched of if multithreading is used.
 
49
 *
 
50
 * @ingroup memory
 
51
 * @author Guido Kanschat, 1998 - 2005
 
52
 */
 
53
class Subscriptor
 
54
{
 
55
  public:
 
56
                                     /**
 
57
                                      * Constructor setting the counter to zero.
 
58
                                      */
 
59
    Subscriptor();
 
60
 
 
61
                                     /**
 
62
                                      * Copy-constructor.
 
63
                                      *
 
64
                                      * The counter of the copy is zero,
 
65
                                      * since references point to the
 
66
                                      * original object.
 
67
                                      */
 
68
    Subscriptor(const Subscriptor&);
 
69
 
 
70
                                     /**
 
71
                                      * Destructor, asserting that the counter
 
72
                                      * is zero.
 
73
                                      */
 
74
    virtual ~Subscriptor();
 
75
    
 
76
                                     /**
 
77
                                      * Assignment operator.
 
78
                                      *
 
79
                                      * This has to be handled with
 
80
                                      * care, too, because the counter
 
81
                                      * has to remain the same. It therefore
 
82
                                      * does nothing more than returning
 
83
                                      * <tt>*this</tt>.
 
84
                                      */
 
85
    Subscriptor& operator = (const Subscriptor&);
 
86
        
 
87
                                     /**
 
88
                                      * Subscribes a user of the
 
89
                                      * object. The subscriber may be
 
90
                                      * identified by text supplied as
 
91
                                      * <tt>identifier</tt>.
 
92
                                      */
 
93
    void subscribe (const char* identifier = 0) const;
 
94
      
 
95
                                     /**
 
96
                                      * Unsubscribes a user from the
 
97
                                      * object.
 
98
                                      *
 
99
                                      * @note The <tt>identifier</tt>
 
100
                                      * must be the <b>same
 
101
                                      * pointer</b> as the one
 
102
                                      * supplied to subscribe(), not
 
103
                                      * just the same text.
 
104
                                      */
 
105
    void unsubscribe (const char* identifier = 0) const;
 
106
 
 
107
                                     /**
 
108
                                      * Return the present number of
 
109
                                      * subscriptions to this object.
 
110
                                      * This allows to use this class
 
111
                                      * for reference counted lifetime
 
112
                                      * determination where the last one
 
113
                                      * to unsubscribe also deletes the
 
114
                                      * object.
 
115
                                      */
 
116
    unsigned int n_subscriptions () const;
 
117
 
 
118
                                     /**
 
119
                                      * List the subscribers to #deallog.
 
120
                                      */
 
121
    void list_subscribers () const;
 
122
    
 
123
                                     /** @addtogroup Exceptions
 
124
                                      * @{ */
 
125
    
 
126
                                     /**
 
127
                                      * Exception:
 
128
                                      * Object may not be deleted, since
 
129
                                      * it is used.
 
130
                                      */
 
131
    DeclException3(ExcInUse,
 
132
                   int, char*, std::string&,
 
133
                   << "Object of class " << arg2
 
134
                   << " is still used by " << arg1 << " other objects."
 
135
                   << arg3);
 
136
 
 
137
                                     /**
 
138
                                      * A subscriber with the
 
139
                                      * identification string given to
 
140
                                      * Subscriptor::unsubscribe() did
 
141
                                      * not subscribe to the object.
 
142
                                      */
 
143
    DeclException2(ExcNoSubscriber, char*, char*,
 
144
                   << "No subscriber with identifier \"" << arg2
 
145
                   << "\" did subscribe to this object of class " << arg1);
 
146
    
 
147
                                     /**
 
148
                                      * Exception: object should be
 
149
                                      * used when
 
150
                                      * Subscriptor::unsubscribe() is
 
151
                                      * called.
 
152
                                      */
 
153
    DeclException0(ExcNotUsed);
 
154
                                     //@}
 
155
 
 
156
  private:
 
157
                                     /**
 
158
                                      * Register a subscriber for
 
159
                                      * debugging purposes. Called by
 
160
                                      * subscribe() in debug mode.
 
161
                                      */
 
162
    void do_subscribe(const char* id) const;
 
163
    
 
164
                                     /**
 
165
                                      * Deregister a subscriber for
 
166
                                      * debugging purposes. Called by
 
167
                                      * unsubscribe() in debug mode.
 
168
                                      */
 
169
    void do_unsubscribe(const char* id) const;
 
170
    
 
171
                                     /**
 
172
                                      * The data type used in
 
173
                                      * #counter_map.
 
174
                                      */
 
175
    typedef std::map<const char*, unsigned int>::value_type
 
176
    map_value_type;
 
177
    
 
178
                                     /**
 
179
                                      * The iterator type used in
 
180
                                      * #counter_map.
 
181
                                      */
 
182
    typedef std::map<const char*, unsigned int>::iterator
 
183
    map_iterator;
 
184
    
 
185
                                     /**
 
186
                                      * Store the number of objects
 
187
                                      * which subscribed to this
 
188
                                      * object. Initialally, this
 
189
                                      * number is zero, and upon
 
190
                                      * destruction it shall be zero
 
191
                                      * again (i.e. all objects which
 
192
                                      * subscribed should have
 
193
                                      * unsubscribed again).
 
194
                                      *
 
195
                                      * The creator (and owner) of an
 
196
                                      * object is counted in the map
 
197
                                      * below if HE manages to supply
 
198
                                      * identification.
 
199
                                      *
 
200
                                      * We use the <tt>mutable</tt> keyword
 
201
                                      * in order to allow subscription
 
202
                                      * to constant objects also.
 
203
                                      *
 
204
                                      * In multithreaded mode, this
 
205
                                      * counter may be modified by
 
206
                                      * different threads. We thus
 
207
                                      * have to mark it
 
208
                                      * <tt>volatile</tt>. However, this is
 
209
                                      * counter-productive in non-MT
 
210
                                      * mode since it may pessimize
 
211
                                      * code. So use the macro
 
212
                                      * defined above to selectively
 
213
                                      * add volatility.
 
214
                                      */
 
215
    mutable DEAL_VOLATILE unsigned int counter;
 
216
    
 
217
                                     /**
 
218
                                      * In this map, we count
 
219
                                      * subscriptions for each
 
220
                                      * different identification strig
 
221
                                      * supplied to subscribe().
 
222
                                      */
 
223
    mutable std::map<const char*, unsigned int> counter_map;
 
224
    
 
225
                                     /**
 
226
                                      * Pointer to the typeinfo object
 
227
                                      * of this object, from which we
 
228
                                      * can later deduce the class
 
229
                                      * name. Since this information
 
230
                                      * on the derived class is
 
231
                                      * neither available in the
 
232
                                      * destructor, nor in the
 
233
                                      * constructor, we obtain it in
 
234
                                      * between and store it here.
 
235
                                      */
 
236
    mutable const std::type_info * object_info;
 
237
};
 
238
 
 
239
//---------------------------------------------------------------------------
 
240
 
 
241
// If we are in optimized mode, the subscription checking is turned
 
242
// off. Therefore, we provide inline definitions of subscribe and
 
243
// unsubscribe here. The definitions for debug mode are in
 
244
// subscriptor.cc.
 
245
 
 
246
#ifdef DEBUG
 
247
 
 
248
inline void
 
249
Subscriptor::subscribe(const char* id) const
 
250
{
 
251
  do_subscribe(id);
 
252
}
 
253
 
 
254
 
 
255
inline void
 
256
Subscriptor::unsubscribe(const char* id) const
 
257
{
 
258
  do_unsubscribe(id);
 
259
}
 
260
 
 
261
#else
 
262
 
 
263
inline void
 
264
Subscriptor::subscribe(const char*) const
 
265
{}
 
266
 
 
267
 
 
268
inline void
 
269
Subscriptor::unsubscribe(const char*) const
 
270
{}
 
271
 
 
272
#endif
 
273
DEAL_II_NAMESPACE_CLOSE
 
274
 
 
275
#endif