TAO_Singleton_Manager.cpp

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

Generated on Tue Feb 2 17:37:53 2010 for TAO by  doxygen 1.4.7