diff options
-rw-r--r-- | ChangeLog-99b | 12 | ||||
-rw-r--r-- | ace/Singleton.cpp | 201 | ||||
-rw-r--r-- | ace/Singleton.h | 79 | ||||
-rw-r--r-- | ace/Singleton.i | 11 |
4 files changed, 288 insertions, 15 deletions
diff --git a/ChangeLog-99b b/ChangeLog-99b index 4502197f41d..21f1c9ffdcf 100644 --- a/ChangeLog-99b +++ b/ChangeLog-99b @@ -1,3 +1,15 @@ +Wed Jul 14 10:22:29 1999 David L. Levine <levine@cs.wustl.edu> + + * ace/Singleton.*: added ACE_Unmanaged_Singleton and + ACE_Unmanaged_TSS_Singleton template class. They're + identical to ACE_Singleton and ACE_TSS_Singleton, + respectively, except that they don't register for + cleanup with the ACE_Object_Manager. Therefore, + the application is responsible for explicitly destroying + the instance after it is no longer needed (if it wants to + avoid memory leaks, at least). The close () static member + function must be used to explicitly destroy the Singleton. + Wed Jul 14 10:01:47 1999 David L. Levine <levine@cs.wustl.edu> * ace/OS.h (ACE_{,U_}ONE_SECOND_IN*): made the trailing diff --git a/ace/Singleton.cpp b/ace/Singleton.cpp index 6dc4def40c4..4aaf6be5e14 100644 --- a/ace/Singleton.cpp +++ b/ace/Singleton.cpp @@ -68,9 +68,7 @@ ACE_Singleton<TYPE, ACE_LOCK>::instance (void) // ACE_Object_Manager: we'll have to leak this instance. #endif /* ACE_MT_SAFE */ - ACE_NEW_RETURN (singleton, - (ACE_Singleton<TYPE, - ACE_LOCK>), 0); + ACE_NEW_RETURN (singleton, (ACE_Singleton<TYPE, ACE_LOCK>), 0); #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) } else @@ -87,9 +85,8 @@ ACE_Singleton<TYPE, ACE_LOCK>::instance (void) if (singleton == 0) { - ACE_NEW_RETURN (singleton, - (ACE_Singleton<TYPE, ACE_LOCK>), - 0); + ACE_NEW_RETURN (singleton, (ACE_Singleton<TYPE, ACE_LOCK>), 0); + // Register for destruction with ACE_Object_Manager. ACE_Object_Manager::at_exit (singleton); } @@ -111,9 +108,99 @@ ACE_Singleton<TYPE, ACE_LOCK>::cleanup (void *) // Pointer to the Singleton instance. template <class TYPE, class ACE_LOCK> ACE_Singleton<TYPE, ACE_LOCK> * ACE_Singleton<TYPE, ACE_LOCK>::singleton_ = 0; + +template <class TYPE, class ACE_LOCK> ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> * +ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::singleton_ = 0; #endif /* !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) */ template <class TYPE, class ACE_LOCK> void +ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::dump (void) +{ + ACE_TRACE ("ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::dump"); + +#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("instance_ = %x"), + ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance_i ())); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */ +} + +template <class TYPE, class ACE_LOCK> +ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *& +ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance_i (void) +{ +#if defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + // Pointer to the Singleton instance. This works around a bug with + // G++ and it's (mis-)handling of templates and statics... + static ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *singleton_ = 0; + + return singleton_; +#else + return ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::singleton_; +#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */ +} + +template <class TYPE, class ACE_LOCK> TYPE * +ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance (void) +{ + ACE_TRACE ("ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance"); + + ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *&singleton = + ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance_i (); + + // Perform the Double-Check pattern... + if (singleton == 0) + { +#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) + if (ACE_Object_Manager::starting_up () || + ACE_Object_Manager::shutting_down ()) + { + // The program is still starting up, and therefore assumed + // to be single threaded. There's no need to double-check. + // Or, the ACE_Object_Manager instance has been destroyed, + // so the preallocated lock is not available. Either way, + // don't register for destruction with the + // ACE_Object_Manager: we'll have to leak this instance. +#endif /* ACE_MT_SAFE */ + + ACE_NEW_RETURN (singleton, (ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>), + 0); +#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) + } + else + { + // Obtain a lock from the ACE_Object_Manager. The pointer + // is static, so we only obtain one per + // ACE_Unmanaged_Singleton instantiation. + static ACE_LOCK *lock = 0; + if (ACE_Object_Manager::get_singleton_lock (lock) != 0) + // Failed to acquire the lock! + return 0; + + ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *lock, 0); + + if (singleton == 0) + ACE_NEW_RETURN (singleton, + (ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>), + 0); + } +#endif /* ACE_MT_SAFE */ + } + + return &singleton->instance_; +} + +template <class TYPE, class ACE_LOCK> void +ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::close (void) +{ + ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *&singleton = + ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::instance_i (); + + if (singleton) + singleton->cleanup (); +} + +template <class TYPE, class ACE_LOCK> void ACE_TSS_Singleton<TYPE, ACE_LOCK>::dump (void) { ACE_TRACE ("ACE_TSS_Singleton<TYPE, ACE_LOCK>::dump"); @@ -161,9 +248,8 @@ ACE_TSS_Singleton<TYPE, ACE_LOCK>::instance (void) // don't register for destruction with the // ACE_Object_Manager: we'll have to leak this instance. #endif /* ACE_MT_SAFE */ - ACE_NEW_RETURN (singleton, - (ACE_TSS_Singleton<TYPE, ACE_LOCK>), - 0); + + ACE_NEW_RETURN (singleton, (ACE_TSS_Singleton<TYPE, ACE_LOCK>), 0); #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) } else @@ -179,9 +265,9 @@ ACE_TSS_Singleton<TYPE, ACE_LOCK>::instance (void) if (singleton == 0) { - ACE_NEW_RETURN (singleton, - (ACE_TSS_Singleton<TYPE, ACE_LOCK>), + ACE_NEW_RETURN (singleton, (ACE_TSS_Singleton<TYPE, ACE_LOCK>), 0); + // Register for destruction with ACE_Object_Manager. ACE_Object_Manager::at_exit (singleton); } @@ -195,16 +281,105 @@ ACE_TSS_Singleton<TYPE, ACE_LOCK>::instance (void) template <class TYPE, class ACE_LOCK> void ACE_TSS_Singleton<TYPE, ACE_LOCK>::cleanup (void *) { - ACE_TRACE ("ACE_TSS_Singleton::cleanup"); - delete this; ACE_TSS_Singleton<TYPE, ACE_LOCK>::instance_i () = 0; } +template <class TYPE, class ACE_LOCK> void +ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::dump (void) +{ + ACE_TRACE ("ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::dump"); + +#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("instance_ = %x"), + ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::instance_i ())); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */ +} + +template <class TYPE, class ACE_LOCK> +ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *& +ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::instance_i (void) +{ +#if defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + // Pointer to the Singleton instance. This works around a bug with + // G++ and it's (mis-)handling of templates and statics... + static ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *singleton_ = 0; + + return singleton_; +#else + return ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::singleton_; +#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */ +} + +template <class TYPE, class ACE_LOCK> TYPE * +ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::instance (void) +{ + ACE_TRACE ("ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::instance"); + + ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *&singleton = + ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::instance_i (); + + // Perform the Double-Check pattern... + if (singleton == 0) + { +#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) + if (ACE_Object_Manager::starting_up () || + ACE_Object_Manager::shutting_down ()) + { + // The program is still starting up, and therefore assumed + // to be single threaded. There's no need to double-check. + // Or, the ACE_Object_Manager instance has been destroyed, + // so the preallocated lock is not available. Either way, + // don't register for destruction with the + // ACE_Object_Manager: we'll have to leak this instance. +#endif /* ACE_MT_SAFE */ + ACE_NEW_RETURN (singleton, + (ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>), + 0); +#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) + } + else + { + // Obtain a lock from the ACE_Object_Manager. The pointer + // is static, so we only obtain one per + // ACE_Unmanaged_Singleton instantiation. + static ACE_LOCK *lock = 0; + if (ACE_Object_Manager::get_singleton_lock (lock) != 0) + // Failed to acquire the lock! + return 0; + + ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *lock, 0); + + if (singleton == 0) + ACE_NEW_RETURN (singleton, + (ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>), + 0); + } +#endif /* ACE_MT_SAFE */ + } + + return ACE_TSS_GET (&singleton->instance_, TYPE); +} + +template <class TYPE, class ACE_LOCK> void +ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::close (void) +{ + ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *&singleton = + ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::instance_i (); + + if (singleton) + singleton->cleanup (); +} + #if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) // Pointer to the Singleton instance. template <class TYPE, class ACE_LOCK> ACE_TSS_Singleton <TYPE, ACE_LOCK> * ACE_TSS_Singleton<TYPE, ACE_LOCK>::singleton_ = 0; + +template <class TYPE, class ACE_LOCK> +ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> * +ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::singleton_ = 0; #endif /* !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) */ #endif /* ACE_SINGLETON_C */ diff --git a/ace/Singleton.h b/ace/Singleton.h index 14bb6461ccb..9bef9acf126 100644 --- a/ace/Singleton.h +++ b/ace/Singleton.h @@ -104,6 +104,45 @@ protected: }; template <class TYPE, class ACE_LOCK> +class ACE_Unmanaged_Singleton : public ACE_Singleton <TYPE, ACE_LOCK> +{ + // = TITLE + // Same as <ACE_Singleton>, except does _not_ register with + // <ACE_Object_Manager> for destruction. + // + // = DESCRIPTION + // This version of <ACE_Singleton> can be used if, for example, + // its DLL will be unloaded before the <ACE_Object_Manager> + // destroys the instance. Unlike with <ACE_Singleton>, the + // application is responsible for explicitly destroying the + // instance after it is no longer needed (if it wants to avoid + // memory leaks, at least). The close () static member function + // must be used to explicitly destroy the Singleton. + // +public: + static TYPE *instance (void); + // Global access point to the Singleton. + + static void close (void); + // Explicitly delete the Singleton instance. + + static void dump (void); + // Dump the state of the object. + +protected: + ACE_Unmanaged_Singleton (void); + // Default constructor. + +#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + static ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *singleton_; + // Pointer to the Singleton (ACE_Cleanup) instance. +#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */ + + static ACE_Unmanaged_Singleton<TYPE, ACE_LOCK> *&instance_i (void); + // Get pointer to the Singleton instance. +}; + +template <class TYPE, class ACE_LOCK> class ACE_TSS_Singleton : public ACE_Cleanup { // = TITLE @@ -149,6 +188,46 @@ protected: // Get pointer to the TSS Singleton instance. }; +template <class TYPE, class ACE_LOCK> +class ACE_Unmanaged_TSS_Singleton : public ACE_TSS_Singleton <TYPE, ACE_LOCK> +{ + // = TITLE + // Same as <ACE_TSS_Singleton>, except does _not_ register with + // <ACE_Object_Manager> for destruction. + // + // = DESCRIPTION + // This version of <ACE_TSS_Singleton> can be used if, for + // example, its DLL will be unloaded before the + // <ACE_Object_Manager> destroys the instance. Unlike with + // <ACE_Singleton>, the application is responsible for + // explicitly destroying the instance after it is no longer + // needed (if it wants to avoid memory leaks, at least). The + // close () static member function must be used to explicitly + // destroy the Singleton. + // +public: + static TYPE *instance (void); + // Global access point to the Singleton. + + static void close (void); + // Explicitly delete the Singleton instance. + + static void dump (void); + // Dump the state of the object. + +protected: + ACE_Unmanaged_TSS_Singleton (void); + // Default constructor. + +#if !defined (ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES) + static ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *singleton_; + // Pointer to the Singleton (ACE_Cleanup) instance. +#endif /* ACE_LACKS_STATIC_DATA_MEMBER_TEMPLATES */ + + static ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK> *&instance_i (void); + // Get pointer to the Singleton instance. +}; + #if defined (__ACE_INLINE__) #include "ace/Singleton.i" #endif /* __ACE_INLINE__ */ diff --git a/ace/Singleton.i b/ace/Singleton.i index c49bd5a0428..38e37fc3d7c 100644 --- a/ace/Singleton.i +++ b/ace/Singleton.i @@ -1,8 +1,6 @@ /* -*- C++ -*- */ // $Id$ -// Singleton.i - // Default constructors. // // Note: don't explicitly initialize "instance_", because TYPE may not @@ -14,7 +12,16 @@ ACE_Singleton<TYPE, ACE_LOCK>::ACE_Singleton (void) } template <class TYPE, class ACE_LOCK> ACE_INLINE +ACE_Unmanaged_Singleton<TYPE, ACE_LOCK>::ACE_Unmanaged_Singleton (void) +{ +} + +template <class TYPE, class ACE_LOCK> ACE_INLINE ACE_TSS_Singleton<TYPE, ACE_LOCK>::ACE_TSS_Singleton (void) { } +template <class TYPE, class ACE_LOCK> ACE_INLINE +ACE_Unmanaged_TSS_Singleton<TYPE, ACE_LOCK>::ACE_Unmanaged_TSS_Singleton (void) +{ +} |