/* -*- C++ -*- */ // $Id$ // ============================================================================ // // = LIBRARY // ace // // = FILENAME // Object_Manager.h // // = AUTHORS // David L. Levine, Matthias Kerkhoff, and Per Andersson // // ============================================================================ #ifndef ACE_OBJECT_MANAGER_H #define ACE_OBJECT_MANAGER_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 */ template class ACE_Unbounded_Queue; template 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_Export ACE_Object_Manager : public ACE_Object_Manager_Base { // = TITLE // Manager for ACE library services and singleton cleanup. // // = DESCRIPTION // The 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 API includes . 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, provides two // adapters, the and // template classes for adapting objects of any type to be // easily managed by the . 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 . // 2) Allow the to both dynamically allocate // and deallocate the object. // 3) Provide an cleanup hook for the object or // array. // 4) Allow the 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 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 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 to 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. // // 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 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 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 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. public: virtual int init (void); // 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 fini (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. static int starting_up (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 shutting_down (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 at_exit (ACE_Cleanup *object, void *param = 0); // 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 (void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param); // 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. #if 0 /* not implemented yet */ static int at_thread_exit (void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param); // Similar to at_exit (), except that the cleanup_hook is called // when the current thread exits instead of when the program terminates. #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_LOG_MSG_INSTANCE_LOCK, 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. static ACE_Sig_Set &default_mask (void); // Accesses a default signal set used in ACE_Sig_Guard methods. private: ACE_Unbounded_Queue *registered_objects_; // Keeps track of all registered objects. ACE_Object_Manager_Preallocations *preallocations_; // Preallocated objects collection. ACE_Sig_Set *default_mask_; // Default signal set used in ACE_Sig_Guard. ACE_Sig_Adapter *ace_service_config_sig_handler_; // ACE_Service_Config signal handler. int at_exit_i (void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param); // Register an object or array for deletion at program termination. // See description of static version above for return values. #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) public: // = The accessors are for internal // use by ACE_Singleton _only_. static int get_singleton_lock (ACE_Null_Mutex *&); // Accesses an to be used for construction of // . 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 to be used for // construction of . Returns 0, and the lock in the // argument, on success; returns -1 on failure. static int get_singleton_lock (ACE_Mutex *&); // Accesses a non-recursive to be used for construction // of . 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 recursive to be used for // construction of . Returns 0, and the lock in the // argument, on success; returns -1 on failure. static int get_singleton_lock (ACE_RW_Thread_Mutex *&); // Accesses a readers/writer to be used for // construction of . Returns 0, and the lock in the // argument, on success; returns -1 on failure. #endif /* ACE_MT_SAFE */ public: // For internal use only by ACE_Managed_Objects. static ACE_Object_Manager *instance (void); // 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 can access it. static void *preallocated_object[ACE_PREALLOCATED_OBJECTS]; // Table of preallocated objects. static void *preallocated_array[ACE_PREALLOCATED_ARRAYS]; // Table of 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: static ACE_Object_Manager *instance_; // Singleton pointer. #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) ACE_Recursive_Thread_Mutex *internal_lock_; // Lock that is used to guard internal structures. ACE_Cleanup_Adapter *singleton_null_lock_; // Null lock for guarding singleton creation. ACE_Cleanup_Adapter *singleton_recursive_lock_; // Lock for guarding singleton creation, when Object_Manager // hasn't been started up, or has already been shut down. #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_Export ACE_Static_Object_Lock { // = TITLE // Provide an interface to access a global lock. // // = DESCRIPTION // 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. public: static ACE_Recursive_Thread_Mutex *instance (void); // Static lock access point. static void cleanup_lock (void); // For use only by ACE_Object_Manager to clean up lock if it // what dynamically allocated. }; #endif /* ACE_HAS_THREADS */ #if defined (__ACE_INLINE__) #include "ace/Object_Manager.i" #endif /* __ACE_INLINE__ */ #include "ace/Managed_Object.h" #endif /* ACE_OBJECT_MANAGER_H */