1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
|
/* -*- C++ -*- */
//=============================================================================
/**
* @file Object_Manager.h
*
* $Id$
*
* @author David L. Levine <levine@cs.wustl.edu>
* @author Matthias Kerkhoff
* @author and Per Andersson
*/
//=============================================================================
#ifndef ACE_OBJECT_MANAGER_H
#define ACE_OBJECT_MANAGER_H
#include "ace/pre.h"
#include "ace/OS.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
// Forward declarations.
class ACE_Object_Manager_Preallocations;
class ACE_Sig_Adapter;
class ACE_Sig_Set;
#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
class ACE_Mutex;
class ACE_Null_Mutex;
class ACE_Thread_Mutex;
class ACE_Recursive_Thread_Mutex;
class ACE_RW_Thread_Mutex;
#endif /* ACE_MT_SAFE */
class ACE_Cleanup_Info_Node;
template <class T> class ACE_Cleanup_Adapter;
// Configuration parameters.
#if !defined (ACE_MAX_MANAGED_OBJECTS)
# define ACE_MAX_MANAGED_OBJECTS 128
#endif /* ! ACE_MAX_MANAGED_OBJECTS */
#if !defined (ACE_APPLICATION_PREALLOCATED_OBJECT_DECLARATIONS)
# define ACE_APPLICATION_PREALLOCATED_OBJECT_DECLARATIONS
#endif /* ! ACE_APPLICATION_PREALLOCATED_OBJECT_DECLARATIONS */
#if !defined (ACE_APPLICATION_PREALLOCATED_ARRAY_DECLARATIONS)
# define ACE_APPLICATION_PREALLOCATED_ARRAY_DECLARATIONS
#endif /* ! ACE_APPLICATION_PREALLOCATED_ARRAY_DECLARATIONS */
/**
* @class ACE_Object_Manager
*
* @brief Manager for ACE library services and singleton cleanup.
*
* The <ACE_Object_Manager> manages cleanup of objects, typically
* singletons, at program termination. In addition to managing
* the cleanup of the ACE library, it provides an interface for
* application to register objects to be cleaned up.
* This class also shuts down ACE library services, so that they
* can reclaim their storage, at program termination. It works
* by creating a static instance whose destructor gets called
* along with those of all other static objects. Hooks are
* provided for application code to register objects and arrays
* for cleanup, e.g., destruction. The order of such cleanup
* calls is in the reverse order of registration, i.e., that
* last object/array to register gets cleaned up first.
* The <ACE_Object_Manager> API includes <ACE_Managed_Object>. That
* class is contained in a separate file because it is a
* template class, and some compilers require that template and
* non-template class definitions appear in separate files.
* Please see ace/Managed_Object.h for a description of that
* part of the API. In summary, <ACE_Managed_Object> provides two
* adapters, the <ACE_Cleanup_Adapter> and <ACE_Managed_Object>
* template classes for adapting objects of any type to be
* easily managed by the <ACE_Object_Manager>. There are several
* mechanisms for adapting objects and arrays for cleanup at
* program termination, in roughly increasing order of ease-of-use:
* 1) Derive the object's class from <ACE_Cleanup>.
* 2) Allow the <ACE_Object_Manager> to both dynamically allocate
* and deallocate the object.
* 3) Provide an <ACE_CLEANUP_FUNC> cleanup hook for the object or
* array.
* 4) Allow the <ACE_Object_Manager> to both preallocate the object
* or array, either statically in global data or dynamically on
* the heap, when its singleton instance is construction.
*
* There are also several mechanisms for registering objects and
* arrays for cleanup. In decreasing order of flexibility and
* complexity (with the exception of the last mechanism):
*
* 1) ACE_Object_Manager::at_exit (void *object,
* ACE_CLEANUP_FUNC cleanup_hook,
* void *param);
* can be used to register any object or array for any
* cleanup activity at program termination.
* 2) ACE_Object_Manager::at_exit (ACE_Cleanup *object,
* void *param = 0);
* can be used to register an <ACE_Cleanup> object
* for any cleanup activity at program termination.
* The final mechanism is not general purpose, but can only
* be used to allocate objects and arrays at program startup:
* 3) ACE_Managed_Object::get_preallocated_object
* (ACE_Object_Manager::Preallocated_Object id);
* and
* ACE_Managed_Object::get_preallocated_array
* (ACE_Object_Manager::Preallocated_Array id);
* can only be used to allocate objects at program startup,
* either in global data or on the heap (selected at compile
* time). These are intended to replace static locks, etc.
* Instead of creating a static <ACE_Object_Manager> instance, one
* can alternatively be created on the stack of the main program
* thread. It is created just after entry to ::main (int, char
* *[]), and before any existing code in that function is
* executed. To enable this alternative, add #define
* ACE_HAS_NONSTATIC_OBJECT_MANAGER before including the platform
* specific config-* file in ace/config.h prior to
* building the ACE library and your applications. This #define
* is enabled in some config files that are supplied with ACE.
*
* To ensure a static object manager is used, #undef
* ACE_HAS_NONSTATIC_OBJECT_MANAGER *after* including the platform
* specific config-* file.
* Note that the ACE_Object_Manager _must_ be created before
* any threads are spawned by the program.
* If ACE_HAS_NONSTATIC_OBJECT_MANAGER is not #defined, the ACE
* library creates a static, singleton <ACE_Object_Manager> instance.
* The instance is placed in global program data, and constructed
* via a static object constructor. If ACE_HAS_NONSTATIC_OBJECT_MANAGER
* is #defined, the <ACE_Object_Manager> instance is created on the stack
* of the main program thread, as noted above.
*
* With ACE_HAS_NONSTATIC_OBJECT_MANAGER enabled, the ACE
* library has no static objects that require destruction.
* However, there are two drawbacks to using it:
* 1) main (int, char *[]) must be declared with arguments, even
* if they're not used. All of ACE is converted to this, so
* just applications have to be concerned with it.
* 2) If there any static objects that depend on those that are
* cleaned up by the Object_Manager, they'll get cleaned up too
* late. The ACE tests do not violate this requirement.
* However, applications may have trouble with it.
* NOTE on the use of <::exit> -- <::exit> does not destroy
* automatic objects. Therefore, if
* ACE_HAS_NONSTATIC_OBJECT_MANAGER is enabled, the
* <ACE_Object_Manager> instance will *not* be destroyed if
* <::exit> is called! However, <ACE_OS::exit> will properly
* destroy the ACE_Object_Manager. It is highly recommended
* that <ACE_OS::exit> be used instead of <::exit>.
*
* However, <::exit> and <ACE_OS::exit> are tricky to use
* properly, especially in multithread programs. It is much
* safer to throw an exception (or simulate that effect) that
* will be caught by <main> instead of calling exit. Then,
* <main> can perform any necessary application-specific cleanup
* and return the status value. In addition, it's usually best
* to avoid calling <::exit> and <ACE_OS::exit> from threads
* other than the main thread. Thanks to Jeff Greif
* <jmg@trivida.com> for pointing out that <::exit> doesn't
* destroy automatic objects, and for developing the
* recommendations in this paragraph.
*
* Instead of creating a static <ACE_Object_Manager>, or letting
* ACE create it on the stack of <main> for you, another
* alternative is to #define
* ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER. With that
* #define, the application must create the ACE_Object_Manager.
* The recommended way is to call <ACE::init> at the start of
* the program, and call <ACE::fini> at the end. Alternatively,
* the application could explicity construct an
* <ACE_Object_Manager>.
*/
class ACE_Export ACE_Object_Manager : public ACE_Object_Manager_Base
{
public:
/**
* Explicitly initialize (construct the singleton instance of) the
* ACE_Object_Manager. Returns 0 on success, -1 on failure, and 1
* if it had already been called.
*/
virtual int init (void);
/**
* Explicitly destroy the singleton instance of the
* ACE_Object_Manager. Returns 0 on success, -1 on failure, and 1
* if it had already been called.
*/
virtual int fini (void);
/**
* Returns 1 before the ACE_Object_Manager has been constructed.
* This flag can be used to determine if the program is constructing
* static objects. If no static object spawns any threads, the
* program will be single-threaded when this flag returns 1. (Note
* that the program still might construct some static objects when
* this flag returns 0, if ACE_HAS_NONSTATIC_OBJECT_MANAGER is not
* defined.)
*/
static int starting_up (void);
/**
* Returns 1 after the ACE_Object_Manager has been destroyed. This
* flag can be used to determine if the program is in the midst of
* destroying static objects. (Note that the program might destroy
* some static objects before this flag can return 1, if
* ACE_HAS_NONSTATIC_OBJECT_MANAGER is not defined.)
*/
static int shutting_down (void);
/**
* Register an ACE_Cleanup object for cleanup at process
* termination. The object is deleted via the
* <ace_cleanup_destroyer>. If you need more flexiblity, see the
* <other at_exit> method below. For OS's that do not have
* processes, cleanup takes place at the end of <main>. Returns 0
* on success. On failure, returns -1 and sets errno to: EAGAIN if
* shutting down, ENOMEM if insufficient virtual memory, or EEXIST
* if the object (or array) had already been registered.
*/
static int at_exit (ACE_Cleanup *object, void *param = 0);
/**
* Register an object (or array) for cleanup at process termination.
* "cleanup_hook" points to a (global, or static member) function
* that is called for the object or array when it to be destroyed.
* It may perform any necessary cleanup specific for that object or
* its class. "param" is passed as the second parameter to the
* "cleanup_hook" function; the first parameter is the object (or
* array) to be destroyed. "cleanup_hook", for example, may delete
* the object (or array). For OS's that do not have processes, this
* function is the same as <at_thread_exit>. Returns 0 on success.
* On failure, returns -1 and sets errno to: EAGAIN if shutting
* down, ENOMEM if insufficient virtual memory, or EEXIST if the
* object (or array) had already been registered.
*/
static int at_exit (void *object,
ACE_CLEANUP_FUNC cleanup_hook,
void *param);
#if 0 /* not implemented yet */
/// Similar to <at_exit>, except that the cleanup_hook is called
/// when the current thread exits instead of when the program terminates.
static int at_thread_exit (void *object,
ACE_CLEANUP_FUNC cleanup_hook,
void *param);
#endif /* 0 */
enum Preallocated_Object
{
ACE_FILECACHE_LOCK,
#if defined (ACE_HAS_THREADS)
ACE_STATIC_OBJECT_LOCK,
#endif /* ACE_HAS_THREADS */
#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
ACE_MT_CORBA_HANDLER_LOCK,
ACE_DUMP_LOCK,
ACE_SIG_HANDLER_LOCK,
ACE_SINGLETON_NULL_LOCK,
ACE_SINGLETON_RECURSIVE_THREAD_LOCK,
ACE_THREAD_EXIT_LOCK,
#if !defined (ACE_LACKS_ACE_TOKEN)
ACE_TOKEN_MANAGER_CREATION_LOCK,
ACE_TOKEN_INVARIANTS_CREATION_LOCK,
#endif /* ! ACE_LACKS_ACE_TOKEN */
ACE_PROACTOR_EVENT_LOOP_LOCK,
#endif /* ACE_MT_SAFE */
// Hook for preallocated objects provided by application.
ACE_APPLICATION_PREALLOCATED_OBJECT_DECLARATIONS
ACE_PREALLOCATED_OBJECTS // This enum value must be last!
};
// Unique identifiers for preallocated objects. Please see
// ace/Managed_Object.h for information on accessing preallocated
// objects.
enum Preallocated_Array
{
// There currently are no preallocated arrays in the ACE
// library. If the application doesn't have any, make sure
// the the preallocated_array size is at least one by declaring
// this dummy . . .
ACE_EMPTY_PREALLOCATED_ARRAY,
// Hook for preallocated arrays provided by application.
ACE_APPLICATION_PREALLOCATED_ARRAY_DECLARATIONS
ACE_PREALLOCATED_ARRAYS // This enum value must be last!
};
// Unique identifiers for preallocated arrays. Please see
// ace/Managed_Object.h for information on accessing preallocated
// arrays.
/**
* Accesses a default signal set used, for example, in ACE_Sig_Guard
* methods.
* Deprecated: use ACE_Object_Manager::default_mask () instead.
*/
static ACE_Sig_Set &default_mask (void);
private:
/// For at_exit support.
ACE_OS_Exit_Info exit_info_;
#if !defined (ACE_LACKS_ACE_SVCCONF)
/// Preallocated objects collection.
ACE_Object_Manager_Preallocations *preallocations_;
/// ACE_Service_Config signal handler.
ACE_Sig_Adapter *ace_service_config_sig_handler_;
#endif /* ! ACE_LACKS_ACE_SVCCONF */
/// Register an object or array for deletion at program termination.
/// See description of static version above for return values.
int at_exit_i (void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param);
#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
public:
// = The <get_singleton_lock> accessors are for internal
// use by ACE_Singleton _only_.
/**
* Accesses an <ACE_Null_Mutex> to be used for construction of
* <ACE_Singletons>. Returns 0, and the lock in the argument, on
* success; returns -1 on failure.
*/
static int get_singleton_lock (ACE_Null_Mutex *&);
/**
* Accesses a non-recursive <ACE_Thread_Mutex> to be used for
* construction of <ACE_Singletons>. Returns 0, and the lock in the
* argument, on success; returns -1 on failure.
*/
static int get_singleton_lock (ACE_Thread_Mutex *&);
/**
* Accesses a non-recursive <ACE_Mutex> to be used for construction
* of <ACE_Singletons>. Returns 0, and the lock in the argument, on
* success; returns -1 on failure.
*/
static int get_singleton_lock (ACE_Mutex *&);
/**
* Accesses a recursive <ACE_Recursive_Thread_Mutex> to be used for
* construction of <ACE_Singletons>. Returns 0, and the lock in the
* argument, on success; returns -1 on failure.
*/
static int get_singleton_lock (ACE_Recursive_Thread_Mutex *&);
/**
* Accesses a readers/writer <ACE_RW_Thread_Mutex> to be used for
* construction of <ACE_Singletons>. Returns 0, and the lock in the
* argument, on success; returns -1 on failure.
*/
static int get_singleton_lock (ACE_RW_Thread_Mutex *&);
#endif /* ACE_MT_SAFE */
public:
// For internal use only by ACE_Managed_Objects.
/**
* Accessor to singleton instance. Because static member functions
* are provided in the interface, this should not be public. However,
* it is public so that ACE_Managed_Object<TYPE> can access it.
*/
static ACE_Object_Manager *instance (void);
/// Table of preallocated objects.
static void *preallocated_object[ACE_PREALLOCATED_OBJECTS];
/// Table of preallocated arrays.
static void *preallocated_array[ACE_PREALLOCATED_ARRAYS];
public:
// Application code should not use these explicitly, so they're
// hidden here. They're public so that the ACE_Object_Manager can
// be constructed/destructed in <main> with
// ACE_HAS_NONSTATIC_OBJECT_MANAGER.
ACE_Object_Manager (void);
~ACE_Object_Manager (void);
private:
/// Singleton pointer.
static ACE_Object_Manager *instance_;
#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
/// Lock that is used to guard internal structures.
ACE_Recursive_Thread_Mutex *internal_lock_;
/// Null lock for guarding singleton creation.
ACE_Cleanup_Adapter<ACE_Null_Mutex> *singleton_null_lock_;
/// Lock for guarding singleton creation, when Object_Manager
/// hasn't been started up, or has already been shut down.
ACE_Cleanup_Adapter<ACE_Recursive_Thread_Mutex> *singleton_recursive_lock_;
#endif /* ACE_MT_SAFE */
#if defined (ACE_HAS_TSS_EMULATION)
// Main thread's thread-specific storage array.
void *ts_storage_[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX];
#endif /* ACE_HAS_TSS_EMULATION */
#if !defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER)
friend class ACE_Object_Manager_Manager;
#endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER */
// Disallow copying by not implementing the following . . .
ACE_Object_Manager (const ACE_Object_Manager &);
ACE_Object_Manager &operator= (const ACE_Object_Manager &);
};
#if defined (ACE_HAS_THREADS)
class ACE_Recursive_Thread_Mutex;
/**
* @class ACE_Static_Object_Lock
*
* @brief Provide an interface to access a global lock.
*
* This class is used to serialize the creation of static
* singleton objects. It really isn't needed any more, because
* anyone can access ACE_STATIC_OBJECT_LOCK directly. But, it
* is retained for backward compatibility.
*/
class ACE_Export ACE_Static_Object_Lock
{
public:
/// Static lock access point.
static ACE_Recursive_Thread_Mutex *instance (void);
/// For use only by ACE_Object_Manager to clean up lock if it
/// what dynamically allocated.
static void cleanup_lock (void);
};
#endif /* ACE_HAS_THREADS */
#if defined (__ACE_INLINE__)
#include "ace/Object_Manager.i"
#endif /* __ACE_INLINE__ */
#include "ace/Managed_Object.h"
#if !defined (ACE_LACKS_ACE_SVCCONF)
// We can't use the ACE_SVC_FACTORY_DECLARE macro here because this
// needs to be in the ACE_Export context rather than the
// ACE_Svc_Export context.
class ACE_Service_Object;
extern "C" ACE_Export
ACE_Service_Object *
_make_ACE_Service_Manager (ACE_Service_Object_Exterminator *);
#endif /* ! ACE_LACKS_ACE_SVCCONF */
// hack to get around errors while compiling using split-cpp
#if defined (ACE_HAS_THREADS)
# if defined (ACE_IS_SPLITTING)
typedef ACE_Cleanup_Adapter<ACE_Recursive_Thread_Mutex> ACE_Static_Object_Lock_Type;
# if defined (__GNUC__)
// With g++, suppress the warning that this is unused.
static ACE_Static_Object_Lock_Type *ACE_Static_Object_Lock_lock __attribute__ ((unused)) = 0;
# else
static ACE_Static_Object_Lock_Type *ACE_Static_Object_Lock_lock = 0;
# endif /* __GNUC__ */
# endif /* ACE_IS_SPLITTING */
#endif /* ACE_HAS_THREADS */
#include "ace/post.h"
#endif /* ACE_OBJECT_MANAGER_H */
|