TAO_Singleton_Manager.cpp

Go to the documentation of this file.
00001 // TAO_Singleton_Manager.cpp,v 1.20 2006/04/19 08:58:21 jwillemsen Exp
00002 
00003 #include "tao/TAO_Singleton_Manager.h"
00004 #include "tao/Exception.h"
00005 
00006 #include "ace/Guard_T.h"
00007 #include "ace/Recursive_Thread_Mutex.h"
00008 #include "ace/Log_Msg.h"
00009 #include "ace/Object_Manager.h"
00010 
00011 #if !defined (__ACE_INLINE__)
00012 # include "tao/TAO_Singleton_Manager.inl"
00013 #endif /* ! __ACE_INLINE__ */
00014 
00015 #if defined (ACE_HAS_EXCEPTIONS)
00016 # if defined (ACE_MVS)
00017 #   include /**/ <unexpect.h>
00018 # else
00019 #  if defined (ACE_HAS_STANDARD_CPP_LIBRARY)
00020 #   include /**/ <exception>
00021 #  else
00022 #   include /**/ <exception.h>
00023 #  endif /* ACE_HAS_STANDARD_CPP_LIBRARY */
00024 # endif /* ACE_MVS */
00025 #endif /* ACE_HAS_EXCEPTIONS */
00026 
00027 ACE_RCSID (tao,
00028            TAO_Singleton_Manager,
00029            "TAO_Singleton_Manager.cpp,v 1.20 2006/04/19 08:58:21 jwillemsen Exp")
00030 
00031 
00032 namespace
00033 {
00034   // Singleton instance pointer.
00035   TAO_Singleton_Manager * the_instance = 0;
00036 }
00037 
00038 #if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1)
00039 # define TAO_SINGLETON_MANAGER_CLEANUP_DESTROYER_NAME ACE_PREPROC_CONCATENATE(TAO_VERSIONED_NAMESPACE_NAME, _TAO_Singleton_Manager_cleanup_destroyer)
00040 #endif  /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
00041 
00042 // Adapter for cleanup, used to register cleanup function with the
00043 // ACE_Object_Manager.
00044 extern "C" void
00045 TAO_SINGLETON_MANAGER_CLEANUP_DESTROYER_NAME (void *, void *)
00046 {
00047 #if defined (TAO_HAS_VERSIONED_NAMESPACE) \
00048     && TAO_HAS_VERSIONED_NAMESPACE == 1
00049   using namespace TAO_VERSIONED_NAMESPACE_NAME;
00050 #endif  /* TAO_HAS_VERSIONED_NAMESPACE */
00051 
00052   if (the_instance)
00053     {
00054       (void) TAO_Singleton_Manager::instance ()->fini ();
00055     }
00056 }
00057 
00058 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00059 
00060 TAO_Singleton_Manager::TAO_Singleton_Manager (void)
00061   // default_mask_ isn't initialized, because it's defined by <init>.
00062   : thread_hook_ (0),
00063     exit_info_ (),
00064     registered_with_object_manager_ (-1)
00065 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
00066     , internal_lock_ (new TAO_SYNCH_RECURSIVE_MUTEX)
00067 # endif /* ACE_MT_SAFE */
00068 #if defined (ACE_HAS_EXCEPTIONS)
00069     , old_unexpected_ (0)
00070 #endif  /* ACE_HAS_EXCEPTIONS */
00071 {
00072   // Be sure that no further instances are created via instance ().
00073   if (the_instance == 0)
00074     {
00075       the_instance = this;
00076     }
00077 
00078   // @@ This is a hack.  Allow the TAO_Singleton_Manager to be registered
00079   //    with the ACE_Object_Manager (or not) in an explicit call to
00080   //    TAO_Singleton_Manager::init().  However, once the explicit call is
00081   //    made, it will not be possible to alter the setting.
00082   int register_with_object_manager = -1;
00083   (void) this->init (register_with_object_manager);
00084 }
00085 
00086 TAO_Singleton_Manager::~TAO_Singleton_Manager (void)
00087 {
00088   this->dynamically_allocated_ = 0;   // Don't delete this again in fini()
00089   (void) this->fini ();
00090 }
00091 
00092 sigset_t *
00093 TAO_Singleton_Manager::default_mask (void)
00094 {
00095   return TAO_Singleton_Manager::instance ()->default_mask_;
00096 }
00097 
00098 ACE_Thread_Hook *
00099 TAO_Singleton_Manager::thread_hook (void)
00100 {
00101   return TAO_Singleton_Manager::instance ()->thread_hook_;
00102 }
00103 
00104 ACE_Thread_Hook *
00105 TAO_Singleton_Manager::thread_hook (ACE_Thread_Hook *new_thread_hook)
00106 {
00107   TAO_Singleton_Manager *tao_om = TAO_Singleton_Manager::instance ();
00108   ACE_Thread_Hook *old_hook = tao_om->thread_hook_;
00109   tao_om->thread_hook_ = new_thread_hook;
00110   return old_hook;
00111 }
00112 
00113 TAO_Singleton_Manager *
00114 TAO_Singleton_Manager::instance (void)
00115 {
00116   // This function should be called during construction of static
00117   // instances, or before any other threads have been created in the
00118   // process.  So, it's not thread safe.
00119 
00120   if (the_instance == 0)
00121     {
00122       TAO_Singleton_Manager *instance_pointer;
00123 
00124       ACE_NEW_RETURN (instance_pointer,
00125                       TAO_Singleton_Manager,
00126                       0);
00127       ACE_ASSERT (instance_pointer == the_instance);
00128 
00129       instance_pointer->dynamically_allocated_ = 1;
00130 
00131       return instance_pointer;
00132     }
00133   else
00134     {
00135       return the_instance;
00136     }
00137 }
00138 
00139 int
00140 TAO_Singleton_Manager::init (void)
00141 {
00142   if (this->registered_with_object_manager_ == -1)
00143     {
00144       // Register the TAO_Singleton_Manager with the
00145       // ACE_Object_Manager.
00146       int register_with_object_manager = 1;
00147 
00148       return this->init (register_with_object_manager);
00149     }
00150 
00151   return 1;  // Already initialized.
00152 }
00153 
00154 int
00155 TAO_Singleton_Manager::init (int register_with_object_manager)
00156 {
00157   if (this->starting_up_i ())
00158     {
00159       // First, indicate that this TAO_Singleton_Manager instance is being
00160       // initialized.
00161       this->object_manager_state_ = OBJ_MAN_INITIALIZING;
00162 
00163       if (this == the_instance)
00164         {
00165 # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
00166           // @@ No MT-specific pre-allocated objects.
00167 # endif /* ACE_MT_SAFE */
00168         }
00169 
00170       ACE_NEW_RETURN (this->default_mask_, sigset_t, -1);
00171       ACE_OS::sigfillset (this->default_mask_);
00172 
00173       // Finally, indicate that the TAO_Singleton_Manager instance has
00174       // been initialized.
00175       this->object_manager_state_ = OBJ_MAN_INITIALIZED;
00176 
00177       return 0;
00178     }
00179 
00180   // @@ This strange looking code is what provides the "register on
00181   //    explicit call to init()" semantics.  This was needed since the
00182   //    TAO_Singleton_Manager constructor invokes init().
00183   //    Unfortunately, I couldn't get rid of that init() call without
00184   //    breaking things.  The fact things broke needs to be
00185   //    investigated further.
00186   if (this->registered_with_object_manager_ != -1
00187       && register_with_object_manager != this->registered_with_object_manager_)
00188     {
00189       // An attempt was made to register the TAO_Singleton_Manager
00190       // with a manager of a different type from the one it is
00191       // currently registered with.  This indicates a problem with the
00192       // caller's logic.
00193 
00194       errno = EINVAL;
00195       return -1;
00196     }
00197 
00198   if (this->registered_with_object_manager_ == -1)
00199     {
00200       if (register_with_object_manager == 1
00201           && ACE_Object_Manager::at_exit (
00202                this,
00203                (ACE_CLEANUP_FUNC) TAO_SINGLETON_MANAGER_CLEANUP_DESTROYER_NAME,
00204                0) != 0)
00205         return -1;
00206 
00207       this->registered_with_object_manager_ =
00208         register_with_object_manager;
00209     }
00210 
00211   // Had already initialized.
00212   return 1;
00213 }
00214 
00215 // Clean up a TAO_Singleton_Manager.  There can be instances of this object
00216 // other than The Instance.  This can happen if a user creates one for some
00217 // reason.  All objects clean up their per-object information and managed
00218 // objects, but only The Instance cleans up the static preallocated objects.
00219 
00220 int
00221 TAO_Singleton_Manager::fini (void)
00222 {
00223   if (the_instance == 0  ||  this->shutting_down_i ())
00224     // Too late.  Or, maybe too early.  Either fini () has already
00225     // been called, or init () was never called.
00226     return this->object_manager_state_ == OBJ_MAN_SHUT_DOWN  ?  1  :  -1;
00227 
00228   // No mutex here.  Only the main thread should destroy the singleton
00229   // TAO_Singleton_Manager instance.
00230 
00231   // Indicate that the TAO_Singleton_Manager instance is being shut
00232   // down.  This object manager should be the last one to be shut
00233   // down.
00234   this->object_manager_state_ = OBJ_MAN_SHUTTING_DOWN;
00235 
00236   // If another Object_Manager has registered for termination, do it.
00237   if (this->next_)
00238     {
00239       this->next_->fini ();
00240       this->next_ = 0;  // Protect against recursive calls.
00241     }
00242 
00243   // Call all registered cleanup hooks, in reverse order of
00244   // registration.
00245   this->exit_info_.call_hooks ();
00246 
00247 //   // Only clean up preallocated objects when the singleton Instance is being
00248 //   // destroyed.
00249 //   if (this == the_instance)
00250 //     {
00251 // #if ! defined (ACE_HAS_STATIC_PREALLOCATION)
00252 //       // Cleanup the dynamically preallocated objects.
00253 // # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
00254 //       // @@ No MT-specific preallocated objects yet.
00255 // # endif  /* ACE_MT_SAFE */
00256 //       // @@ No preallocated objects yet.
00257 // #endif  /* ! ACE_HAS_STATIC_PREALLOCATION */
00258 //     }
00259 
00260   delete this-> default_mask_;
00261   this->default_mask_ = 0;
00262 
00263 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
00264   delete this->internal_lock_;
00265   this->internal_lock_ = 0;
00266 #endif /* ACE_MT_SAFE */
00267 
00268 #if defined (ACE_HAS_EXCEPTIONS)
00269   // Restore the old unexpected exception handler since TAO will no
00270   // longer be handling exceptions.  Allow the application to once
00271   // again handle unexpected exceptions.
00272 # if (!defined (_MSC_VER) \
00273       && defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB) \
00274       && (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB != 0)) || defined (ghs)
00275   (void) std::set_unexpected (this->old_unexpected_);
00276 # else
00277   (void) set_unexpected (this->old_unexpected_);
00278 # endif  /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
00279 #endif /* ACE_HAS_EXCEPTIONS */
00280 
00281   // Indicate that this TAO_Singleton_Manager instance has been shut down.
00282   this->object_manager_state_ = OBJ_MAN_SHUT_DOWN;
00283 
00284   if (this == the_instance)
00285     the_instance = 0;
00286 
00287   if (this->dynamically_allocated_)
00288     {
00289       delete this;
00290     }
00291 
00292   return 0;
00293 }
00294 
00295 int
00296 TAO_Singleton_Manager::starting_up (void)
00297 {
00298   return
00299     the_instance
00300     ? the_instance->starting_up_i ()
00301     : 1;
00302 }
00303 
00304 int
00305 TAO_Singleton_Manager::shutting_down (void)
00306 {
00307   return
00308     the_instance
00309     ? the_instance->shutting_down_i ()
00310     : 1;
00311 }
00312 
00313 #if defined (ACE_HAS_EXCEPTIONS)
00314 void
00315 TAO_Singleton_Manager::_set_unexpected (TAO_unexpected_handler u)
00316 {
00317   // This must be done after the system TypeCodes and Exceptions have
00318   // been initialized.  An unexpected exception will cause TAO's
00319   // unexpected exception handler to be called.  That handler
00320   // transforms all unexpected exceptions to CORBA::UNKNOWN, which of
00321   // course requires the TypeCode constants and system exceptions to
00322   // have been initialized.
00323 # if (!defined (_MSC_VER) \
00324       && defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB) \
00325       && (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB != 0)) || defined (ghs)
00326   this->old_unexpected_ = std::set_unexpected (u);
00327 # else
00328   this->old_unexpected_ = set_unexpected (u);
00329 # endif  /* ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB */
00330 }
00331 #endif /* ACE_HAS_EXCEPTIONS */
00332 
00333 int
00334 TAO_Singleton_Manager::at_exit_i (void *object,
00335                                   ACE_CLEANUP_FUNC cleanup_hook,
00336                                   void *param)
00337 {
00338   ACE_MT (ACE_GUARD_RETURN (TAO_SYNCH_RECURSIVE_MUTEX,
00339                             ace_mon,
00340                             *the_instance->internal_lock_,
00341                             -1));
00342 
00343   if (this->shutting_down_i ())
00344     {
00345       errno = EAGAIN;
00346       return -1;
00347     }
00348 
00349   if (this->exit_info_.find (object))
00350     {
00351       // The object has already been registered.
00352       errno = EEXIST;
00353       return -1;
00354     }
00355 
00356   return this->exit_info_.at_exit_i (object, cleanup_hook, param);
00357 }
00358 
00359 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 11:54:24 2006 for TAO by doxygen 1.3.6