#include <ace/Object_Manager.h>
class ACE_Object_Manager : public ACE_Object_Manager_Base {
public:
virtual int init (void);
virtual int fini (void);
static int starting_up (void);
static int shutting_down (void);
static int at_exit (ACE_Cleanup *object, void *param = 0);
static int at_exit ( void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param );
static int at_thread_exit ( void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param );
enum Preallocated_Object{ ACE_FILECACHE_LOCK, #if defined ( ACE_HAS_THREADS) ACE_STATIC_OBJECT_LOCK, #endif #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_PROACTOR_EVENT_LOOP_LOCK, #endif ACE_APPLICATION_PREALLOCATED_OBJECT_DECLARATIONS ACE_PREALLOCATED_OBJECTS };
enum Preallocated_Array{ ACE_EMPTY_PREALLOCATED_ARRAY, ACE_APPLICATION_PREALLOCATED_ARRAY_DECLARATIONS ACE_PREALLOCATED_ARRAYS };static ACE_Sig_Set &default_mask (void);
static int get_singleton_lock (ACE_Null_Mutex *&);
static int get_singleton_lock (ACE_Thread_Mutex *&);
static int get_singleton_lock (ACE_Mutex *&);
static int get_singleton_lock (ACE_Recursive_Thread_Mutex *&);
static int get_singleton_lock (ACE_RW_Thread_Mutex *&);
static ACE_Object_Manager *instance (void);
static void *preallocated_object[ACE_PREALLOCATED_OBJECTS];
static void *preallocated_array[ACE_PREALLOCATED_ARRAYS];
ACE_Object_Manager (void);
~ACE_Object_Manager (void);
private:
ACE_OS_Exit_Info exit_info_;
ACE_Object_Manager_Preallocations *preallocations_;
ACE_Sig_Adapter *ace_service_config_sig_handler_;
int at_exit_i ( void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param );
static ACE_Object_Manager *instance_;
ACE_Recursive_Thread_Mutex *internal_lock_;
ACE_Cleanup_Adapter<ACE_Null_Mutex> *singleton_null_lock_;
ACE_Cleanup_Adapter<ACE_Recursive_Thread_Mutex> *singleton_recursive_lock_;void *ts_storage_[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX];
friend class ACE_Object_Manager_Manager;
ACE_Object_Manager (const ACE_Object_Manager &);
ACE_Object_Manager &operator= (const ACE_Object_Manager &);
};
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
static 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
.
virtual int init (void);
virtual int fini (void);
static int starting_up (void);
static int shutting_down (void);
static int at_exit (ACE_Cleanup *object, void *param = 0);
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 (
void *object,
ACE_CLEANUP_FUNC cleanup_hook,
void *param
);
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_thread_exit (
void *object,
ACE_CLEANUP_FUNC cleanup_hook,
void *param
);
at_exit
, except that the cleanup_hook is called
when the current thread exits instead of when the program terminates.
static ACE_Sig_Set &default_mask (void);
static int get_singleton_lock (ACE_Null_Mutex *&);
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_Thread_Mutex *&);
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_Mutex *&);
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_Recursive_Thread_Mutex *&);
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_RW_Thread_Mutex *&);
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 ACE_Object_Manager *instance (void);
TYPE
can access it.
static void *preallocated_object[ACE_PREALLOCATED_OBJECTS];
static void *preallocated_array[ACE_PREALLOCATED_ARRAYS];
ACE_Object_Manager (void);
~ACE_Object_Manager (void);
ACE_OS_Exit_Info exit_info_;
ACE_Object_Manager_Preallocations *preallocations_;
ACE_Sig_Adapter *ace_service_config_sig_handler_;
int at_exit_i (
void *object,
ACE_CLEANUP_FUNC cleanup_hook,
void *param
);
static ACE_Object_Manager *instance_;
ACE_Recursive_Thread_Mutex *internal_lock_;
ACE_Cleanup_Adapter<ACE_Null_Mutex> *singleton_null_lock_;
ACE_Cleanup_Adapter<ACE_Recursive_Thread_Mutex> *singleton_recursive_lock_;
void *ts_storage_[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX];
friend class ACE_Object_Manager_Manager;
ACE_Object_Manager (const ACE_Object_Manager &);
ACE_Object_Manager &operator= (const ACE_Object_Manager &);