diff options
author | iliyan <iliyan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2007-02-13 17:18:59 +0000 |
---|---|---|
committer | iliyan <iliyan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2007-02-13 17:18:59 +0000 |
commit | de68c990dc9a25bcf050412c23fa5983b7e9a7d5 (patch) | |
tree | e61fb67b8e973b401eb9e34061f65e1276481c2d | |
parent | b5e4fa24bc319330b2980bf988e41cc4b2f4bb15 (diff) | |
download | ATCD-de68c990dc9a25bcf050412c23fa5983b7e9a7d5.tar.gz |
ChangeLogTag: Tue Feb 13 15:35:54 UTC 2007 Iliyan Jeliazkov <iliyan@ociweb.com>
-rw-r--r-- | ACE/ChangeLog | 19 | ||||
-rw-r--r-- | ACE/ace/Dynamic_Service_Base.cpp | 8 | ||||
-rw-r--r-- | ACE/ace/Dynamic_Service_Dependency.cpp | 2 | ||||
-rw-r--r-- | ACE/ace/Service_Config.cpp | 136 | ||||
-rw-r--r-- | ACE/ace/Service_Config.h | 93 | ||||
-rw-r--r-- | ACE/ace/Service_Config.inl | 41 | ||||
-rw-r--r-- | ACE/ace/Service_Gestalt.cpp | 229 |
7 files changed, 299 insertions, 229 deletions
diff --git a/ACE/ChangeLog b/ACE/ChangeLog index ebec87b0461..b160b912277 100644 --- a/ACE/ChangeLog +++ b/ACE/ChangeLog @@ -1,3 +1,22 @@ +Tue Feb 13 15:35:54 UTC 2007 Iliyan Jeliazkov <iliyan@ociweb.com> + + * ace/Service_Config.{h,inl,cpp}: + + Refactoring to simplify the TSS usage, reduce overhead and + eliminate a memory leak. + + * ace/Service_Gestalt.cpp: + + Fixed a memory leak in Service_Type_Dynamic_Guard dtor. Updated + logging. + + * ace/Dynamic_Service_Base.cpp: + * ace/Dynamic_Service_Dependency.cpp: + + Updated to use SC::instance () to better express the contract + for these classes. They simply don't need to be aware whether + they are using a global, or a TSS-local gestalt . + Tue Feb 13 14:44:06 UTC 2007 Johnny Willemsen <jwillemsen@remedy.nl> * ace/config-vxworks5.x.h: diff --git a/ACE/ace/Dynamic_Service_Base.cpp b/ACE/ace/Dynamic_Service_Base.cpp index cc5e9114871..94400ddffdc 100644 --- a/ACE/ace/Dynamic_Service_Base.cpp +++ b/ACE/ace/Dynamic_Service_Base.cpp @@ -32,7 +32,7 @@ void * ACE_Dynamic_Service_Base::instance (const ACE_TCHAR *name, bool no_global) { ACE_TRACE ("ACE_Dynamic_Service_Base::instance"); - return instance (ACE_Service_Config::current (), name, no_global); + return instance (ACE_Service_Config::instance (), name, no_global); } @@ -40,7 +40,7 @@ void * ACE_Dynamic_Service_Base::instance (const ACE_TCHAR *name) { ACE_TRACE ("ACE_Dynamic_Service_Base::instance"); - return instance (ACE_Service_Config::current (), name, false); + return instance (ACE_Service_Config::instance (), name, false); } @@ -49,14 +49,14 @@ ACE_Dynamic_Service_Base::instance (const ACE_TCHAR *name) const ACE_Service_Type * ACE_Dynamic_Service_Base::find_i (const ACE_Service_Gestalt* &repo, const ACE_TCHAR *name, - bool no_global) + bool local_only) { ACE_TRACE ("ACE_Dynamic_Service_Base::find_i"); const ACE_Service_Type *svc_rec = 0; ACE_Service_Gestalt* global = ACE_Service_Config::global (); - for ( ; (repo->find (name, &svc_rec) == -1) && !no_global; repo = global) + for ( ; (repo->find (name, &svc_rec) == -1) && !local_only; repo = global) { // Check the static repo, too if different if (repo == global) diff --git a/ACE/ace/Dynamic_Service_Dependency.cpp b/ACE/ace/Dynamic_Service_Dependency.cpp index f2a9b45d61c..a2c25c2e6bf 100644 --- a/ACE/ace/Dynamic_Service_Dependency.cpp +++ b/ACE/ace/Dynamic_Service_Dependency.cpp @@ -14,7 +14,7 @@ ACE_RCSID (ace, ACE_Dynamic_Service_Dependency::ACE_Dynamic_Service_Dependency (const ACE_TCHAR *principal) { - this->init (ACE_Service_Config::current (), principal); + this->init (ACE_Service_Config::instance (), principal); } ACE_Dynamic_Service_Dependency::ACE_Dynamic_Service_Dependency (const ACE_Service_Gestalt *cfg, diff --git a/ACE/ace/Service_Config.cpp b/ACE/ace/Service_Config.cpp index 2a564868937..ab9c2c440d2 100644 --- a/ACE/ace/Service_Config.cpp +++ b/ACE/ace/Service_Config.cpp @@ -30,15 +30,16 @@ ACE_RCSID (ace, /// ACE_Service_Config_Guard::ACE_Service_Config_Guard (ACE_Service_Gestalt * psg) - : saved_ (ACE_Service_Config::current ()) + : saved_ (ACE_Service_Config::instance ()) { if (ACE::debug ()) ACE_DEBUG ((LM_DEBUG, - ACE_LIB_TEXT ("(%P|%t) SCG::ctor, repo=%@ - guard with %@\n"), + ACE_LIB_TEXT ("ACE (%P|%t) Service_Config_Guard:<ctor>") + ACE_LIB_TEXT (" - repo=%@ superceded by repo=%@\n"), this->saved_->repo_, psg->repo_)); - // Modify the TSS - no locking needed + // Modify the TSS if the repo has changed if (saved_ != psg) (void)ACE_Service_Config::current (psg); } @@ -50,7 +51,8 @@ ACE_Service_Config_Guard::~ACE_Service_Config_Guard (void) if (ACE::debug ()) ACE_DEBUG ((LM_DEBUG, - ACE_LIB_TEXT ("(%P|%t) SCG::dtor, repo=%@ - un-guard\n"), + ACE_LIB_TEXT ("ACE (%P|%t) Service_Config_Guard:<dtor>") + ACE_LIB_TEXT (" - new repo=%@\n"), this->saved_->repo_)); } @@ -75,6 +77,25 @@ int ACE_Service_Config::be_a_daemon_ = 0; int ACE_Service_Config::signum_ = SIGHUP; +/// +ACE_Service_Config::TSS_Resources::TSS_Resources (void) + : ptr_ (ACE_Service_Config::global()) +{ +} + +/// +ACE_Service_Gestalt *ACE_Service_Config::TSS_Resources::ptr () const +{ + return ptr_; +} + +/// +ACE_Service_Gestalt *ACE_Service_Config::TSS_Resources::ptr (ACE_Service_Gestalt *n) +{ + return ptr_ = n; +} + + void ACE_Service_Config::dump (void) const { @@ -287,102 +308,6 @@ ACE_Service_Config::open_i (const ACE_TCHAR program_name[], ignore_debug_flag); } -/// Return the global configuration instance. Allways returns the same -/// instance -ACE_Service_Gestalt * -ACE_Service_Config::global (void) -{ - return ACE_Singleton<ACE_Service_Config, ACE_SYNCH_MUTEX>::instance (); -} - - -/// -ACE_Service_Gestalt * -ACE_Service_Config::instance (void) -{ - return ACE_Service_Config::current (); -} - - -// A thread-specific storage to keep a pointer to the (current) global -// configuration. Using a pointer to avoid the order of initialization -// debacle possible when using static class instances. The memory is -// dynamicaly allocated and leaked from current() - -/// Provides access to the static ptr, containing the TSS -/// accessor. Ensures the desired order of initialization, even when -/// other static initializers need the value. -ACE_Service_Config::TSS_Service_Gestalt_Ptr * -ACE_Service_Config::impl_ (void) -{ - /// A "straight" static ptr does not work in static builds, because - /// some static initializer may call current() method and assign - /// value to instance_ *before* the startup code has had a chance to - /// initialize it . This results in instance_ being "zeroed" out - /// after it was assigned the correct value. Having a method scoped - /// static guarantees that the first time the method is invoked, the - /// instance_ will be initialized before returning. - - static TSS_Service_Gestalt_Ptr * instance_ = 0; - - // We can't possibly rely on ACE_STATIC_OBJECT_LOCK or any other - // object that may be managed by the Object Manager. It is very - // likely we are called in a static initializer context, before the - // ACE_Object_Manager has been instantiated. This of course only - // matters for threaded environments. - ACE_MT (static ACE_SYNCH_RECURSIVE_MUTEX guardian_); - - if (instance_ == 0) - { - // TSS not initialized yet - first thread to hit this, so doing - // the double-checked locking thing - ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, - guardian_, 0)); - - if (instance_ == 0) - ACE_NEW_RETURN (instance_, - TSS_Service_Gestalt_Ptr, - 0); - } - - return instance_; -} - -/// Return the configuration instance, considered "global" in the -/// current thread. This may be the same as instance(), but on some -/// occasions, it may be a different one. For example, -/// ACE_Service_Config_Guard provides a way of temporarily replacing -/// the "current" configuration instance in the context of a thread. -ACE_Service_Gestalt * -ACE_Service_Config::current (void) -{ - TSS_Service_Gestalt_Ptr * const impl = ACE_Service_Config::impl_ (); - if (impl == 0) - return 0; - - ACE_Service_Gestalt* & gestalt = ACE_TSS_GET (impl, TSS_Resources)->ptr_; - - if (gestalt == 0) - gestalt = ACE_Service_Config::global (); - - return gestalt; -} - -/// A mutator to set the "current" (TSS) gestalt instance. -ACE_Service_Gestalt* -ACE_Service_Config::current (ACE_Service_Gestalt *newcurrent) -{ - TSS_Service_Gestalt_Ptr * const impl = ACE_Service_Config::impl_ (); - if (impl == 0) - return 0; - - ACE_Service_Gestalt* & gestalt = ACE_TSS_GET (impl, TSS_Resources)->ptr_; - - gestalt = newcurrent; - - return gestalt; -} - // This method has changed to return the gestalt instead of the // container, underlying the service repository and defined // ACE_Service_Gestalt::insert (ACE_Static_Svc_Descriptor*). This way @@ -394,14 +319,14 @@ ACE_Service_Config::current (ACE_Service_Gestalt *newcurrent) ACE_Service_Gestalt * ACE_Service_Config::static_svcs (void) { - return ACE_Service_Config::current (); + return ACE_Service_Config::instance (); } /// int ACE_Service_Config::insert (ACE_Static_Svc_Descriptor* stsd) { - return ACE_Service_Config::current ()->insert (stsd); + return ACE_Service_Config::instance ()->insert (stsd); } @@ -574,12 +499,15 @@ ACE_Service_Config::reconfigure (void) int ACE_Service_Config::close (void) { - int result1 = ACE_Service_Config::current ()->close (); + int result1 = ACE_Service_Config::instance ()->close (); // Delete the service repository. All the objects inside the // service repository should already have been finalized. int result2 = ACE_Service_Config::close_svcs (); + // Do away with the Singleton + ACE_SERVICE_CONFIG_SINGLETON::close (); + return (result1 | result2); } @@ -589,7 +517,7 @@ ACE_Service_Config::close_svcs (void) ACE_TRACE ("ACE_Service_Config::close_svcs"); ACE_Service_Repository::close_singleton (); - ACE_Service_Config::current (0); + ACE_Service_Config::current (global ()); return 0; } diff --git a/ACE/ace/Service_Config.h b/ACE/ace/Service_Config.h index 6c7b87427e1..c0cbe2ef473 100644 --- a/ACE/ace/Service_Config.h +++ b/ACE/ace/Service_Config.h @@ -213,49 +213,70 @@ protected: private: - /// A Wrapper for the TSS-stored pointer. - struct TSS_Resources { - TSS_Resources (void) : ptr_ (0) {} + /** + * @c ACE_Service_Config is supposed to be a Singleton. This is the + * only Configuration Gestalt available for access from static + * initializers at proces start-up time. Using Unmanaged Singleton + * makes it safe since OM may not yet be fully initialized in the + * context of a static initializer that uses SC, and also because we + * know that upon process exit, the SC will be explicitely closed + * (in the @c ACE_Object_Manager::fini()). + */ + typedef ACE_Unmanaged_Singleton<ACE_Service_Config, + ACE_SYNCH_RECURSIVE_MUTEX> ACE_SERVICE_CONFIG_SINGLETON; + + /** + * A Wrapper for the TSS-stored pointer to the "current" + * configuration Gestalt. Static initializers from any DLL loaded + * through the SC will find the SC instance through the TSS pointer, + * instead of the global singleton. This makes it possible to ensure + * that the new services are loaded in the correct Gestalt, + * independent of which thread is actually using the SC at the time + * to do so. + */ + class TSS_Resources + { + public: + TSS_Resources (void); + ACE_Service_Gestalt *ptr () const; + ACE_Service_Gestalt *ptr (ACE_Service_Gestalt *n); + private: ACE_Service_Gestalt *ptr_; }; - - /// A type for the TSS-stored resources. The typedef helps to - /// abstract from the particularities of single-threaded vs - /// multi-threaded environments. - typedef ACE_TSS_TYPE (ACE_Service_Config::TSS_Resources) TSS_Service_Gestalt_Ptr; - - /// Provides access to the static ptr, containing the TSS - /// accessor. Ensures the desired order of initialization, even when - /// other static initializers need the value. - static TSS_Service_Gestalt_Ptr * impl_ (void); - -protected: - - /// Mutator to set the (TSS) global instance. Intended for use by helper - /// classes, like ACE_Service_Config_Guard which when instantiated on the - /// stack, can temporarily change which gestalt instance is viewed as - /// global from the point of view of the static initializers in DLLs. - static ACE_Service_Gestalt* current (ACE_Service_Gestalt*); - + + ACE_TSS_TYPE (TSS_Resources) tss_; + public: - - /// If not yet initialized, creates a process-wide instance - /// global instance, which is registered with the ACE_Object_Manager, - /// via ACE_Singleton. Note that this is allways the same instance, - /// in contrast with current (), which may be different instance at - /// different times, dependent on the context. + /** + * Mutator to set the (TSS) global instance. Intended for use by + * helper classes like @see ACE_Service_Config_Guard. Stack-based + * instances of it can temporarily change which Gestalt is + * considered global by any static initializer (especially those in + * DLLs, loaded at run-time). + */ + static ACE_Service_Gestalt* current (ACE_Service_Gestalt*); + + /** + * Returns a process-wide global singleton instance in contrast with + * current (), which may return a different instance at different + * times, dependent on the context. Use of this method is + * discouraged as it allows circumvention of the mechanism for + * dynamically loading services. Use with extreme caution! + */ static ACE_Service_Gestalt* global (void); - /// Accessor for the "current" service repository through a pointer - /// held in TSS. + /// Accessor for the "current" service gestalt static ACE_Service_Gestalt* current (void); - /// This is what the static service initializators are hard-wired - /// to use, so in order to keep interface changes to a minimum this - /// method merely forwards to current(). Thus it is possible to - /// temporarily replace what those initializers think is the global - /// service repository, for instance when dynamically loading a - /// service from a DLL, which in turn, contains its own static services. + /** + * This is what the static service initializators are hard-wired to + * use, so in order to avoid interface changes this method merely + * forwards to @c ACE_Service_Config::current. This enables us to + * enforce which Service Gestalt is used for services registering + * through static initializers. Especially important for DLL-based + * dynamic services, which can contain their own static services and + * static initializers. + */ static ACE_Service_Gestalt* instance (void); /** diff --git a/ACE/ace/Service_Config.inl b/ACE/ace/Service_Config.inl index 895c2340232..c0cd157d566 100644 --- a/ACE/ace/Service_Config.inl +++ b/ACE/ace/Service_Config.inl @@ -51,6 +51,47 @@ ACE_Service_Config::parse_args (int argc, ACE_TCHAR *argv[]) return ACE_Service_Config::current ()->parse_args (argc, argv); } + +/// Return the global configuration instance. Allways returns the same +/// instance +ACE_INLINE ACE_Service_Gestalt * +ACE_Service_Config::global (void) +{ + return ACE_SERVICE_CONFIG_SINGLETON::instance (); +} + + +/// Return the configuration instance, considered "global" in the +/// current thread. This may be the same as instance(), but on some +/// occasions, it may be a different one. For example, +/// ACE_Service_Config_Guard provides a way of temporarily replacing +/// the "current" configuration instance in the context of a thread. +ACE_INLINE ACE_Service_Gestalt * +ACE_Service_Config::instance (void) +{ + return ACE_SERVICE_CONFIG_SINGLETON::instance ()->tss_->ptr (); +} + + +/// Return the configuration instance, considered "global" in the +/// current thread. This may be the same as instance(), but on some +/// occasions, it may be a different one. For example, +/// ACE_Service_Config_Guard provides a way of temporarily replacing +/// the "current" configuration instance in the context of a thread. +ACE_INLINE ACE_Service_Gestalt * +ACE_Service_Config::current (void) +{ + return ACE_SERVICE_CONFIG_SINGLETON::instance ()->tss_->ptr (); +} + +/// A mutator to set the "current" (TSS) gestalt instance. +ACE_INLINE ACE_Service_Gestalt* +ACE_Service_Config::current (ACE_Service_Gestalt *newcurrent) +{ + return ACE_SERVICE_CONFIG_SINGLETON::instance ()->tss_->ptr (newcurrent); +} + + // Compare two service descriptors for equality. ACE_INLINE bool diff --git a/ACE/ace/Service_Gestalt.cpp b/ACE/ace/Service_Gestalt.cpp index 8b6eeb9fc97..90f7a7b49e5 100644 --- a/ACE/ace/Service_Gestalt.cpp +++ b/ACE/ace/Service_Gestalt.cpp @@ -104,118 +104,180 @@ ACE_Service_Type_Dynamic_Guard::ACE_Service_Type_Dynamic_Guard #endif { ACE_ASSERT (this->name_ != 0); // No name? - ACE_NEW_NORETURN (this->dummy_, // Allocate the forward declaration ... + + // Heap-allocate the forward declaration because that's where the + // repository exects them to be ... + ACE_NEW_NORETURN (this->dummy_, ACE_Service_Type (this->name_, // ... use the same name 0, // ... inactive this->dummy_dll_, // ... bogus ACE_DLL 0)); // ... no type_impl - ACE_ASSERT (this->dummy_ != 0); // No memory? - +#ifndef ACE_NLOGGING if(ACE::debug ()) ACE_DEBUG ((LM_DEBUG, - ACE_LIB_TEXT ("ACE (%P|%t) STDG::<ctor>, repo=%@ [%d], ") - ACE_LIB_TEXT ("name=%s, type=%@, impl=%@, object=%@, active=%d - inserting dummy forward\n"), - &this->repo_, this->repo_begin_, this->name_, this->dummy_, + ACE_LIB_TEXT ("ACE (%P|%t) Service_Type_Dynamic_Guard") + ACE_LIB_TEXT (":<ctor> - new fwd decl") + ACE_LIB_TEXT (", repo[%d]=%@, name=%s, type=%@") + ACE_LIB_TEXT (", impl=%@, object=%@, active=%d\n"), + this->repo_begin_, + &this->repo_, + this->name_, + this->dummy_, this->dummy_->type (), - (this->dummy_->type () != 0) ? this->dummy_->type ()->object () : 0, + (this->dummy_->type () != 0) + ? this->dummy_->type ()->object () + : 0, this->dummy_->active ())); +#endif /* ACE_NLOGGING */ + + // No memory ... + if (this->dummy_ == 0) + return; // Note that the dummy_'s memory may be deallocated between invoking - // the ctor and dtor, if the expected ("real") dynamic service is + // the ctor and dtor. For example, if the real dynamic service is // inserted in the repository. See how this affects the destructor's // behavior, below. - this->repo_.insert (this->dummy_); + if (this->repo_.insert (this->dummy_) != 0) + { + delete this->dummy_; + this->dummy_ = 0; + }; } /// Destructor - ACE_Service_Type_Dynamic_Guard::~ACE_Service_Type_Dynamic_Guard (void) { - const ACE_Service_Type *tmp = 0; - - // Lookup without ignoring suspended services. Making sure - // not to ignore any inactive services, since those may be forward + // Lookup without ignoring suspended services. Making sure not to + // ignore any inactive services, since those may be forward // declarations size_t slot = 0; + const ACE_Service_Type *tmp = 0; int const ret = this->repo_.find_i (this->name_, slot, &tmp, false); // We inserted it (as inactive), so we expect to find it, right? if (ret < 0 && ret != -2) { +#ifndef ACE_NLOGGING if (ACE::debug ()) ACE_ERROR ((LM_WARNING, - ACE_LIB_TEXT ("ACE (%P|%t) STDG::<dtor> - Failed (%d) to find %s\n"), - ret, this->name_)); - return; - } - - if (tmp != 0 && tmp->type () != 0) - { - // Something has registered a proper (non-forward-decl) service with - // the same name as our dummy. - - if(ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_LIB_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@, name=%s - updating [%d - %d]\n"), - &this->repo_, - this->name_, - this->repo_begin_, - this->repo_.current_size ())); - - // Relocate any static services. If any have been registered in - // the context of this guard, those really aren't static - // services because their code is in the DLL's code segment - this->repo_.relocate_i (this->repo_begin_, this->repo_.current_size (), tmp->dll()); - - // The ACE_Service_Gestalt::insert() modifies the memory for the - // original ACE_Service_Type instance. It deletes our dummy - // instance when replacing it with the actual implementation, so - // we are hereby simply giving up ownership. - this->dummy_ = 0; - - if(ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_LIB_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@ [%d], ") - ACE_LIB_TEXT ("name=%s, type=%@, impl=%@, object=%@, active=%d - loaded\n"), - &this->repo_, this->repo_begin_, this->name_, tmp, tmp->type (), - (tmp->type () != 0) ? tmp->type ()->object () : 0, - tmp->active ())); - } + ACE_LIB_TEXT ("ACE (%P|%t) Service_Type_Dynamic_Guard") + ACE_LIB_TEXT (":<dtor> - find %s failed, returns %d/%d\n"), + this->name_, + ret, + errno)); +#endif /* ACE_NLOGGING */ + + delete this->dummy_; + } else - { - if(ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_LIB_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@, ") - ACE_LIB_TEXT ("name=%s, type=%@, impl=%@, object=%@, active=%d - removing dummy forward\n"), - &this->repo_, this->name_, this->dummy_, this->dummy_->type (), - (this->dummy_->type () != 0) ? this->dummy_->type ()->object () : 0, - this->dummy_->active ())); - - // The (dummy) forward declaration is still there and is - // the same, which means that no actual declaration was - // provided inside the guarded scope. Therefore, the forward - // declaration is no longer necessary. - if (this->repo_.remove_i (this->name_, - const_cast< ACE_Service_Type**> (&this->dummy_)) == 0) - { - // If it is a dummy then deleting it while holding the repo lock is okay. There will be no - // call to service object's fini() and no possibility for deadlocks. - delete this->dummy_; - } - else - { - ACE_ERROR ((LM_WARNING, - ACE_LIB_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@, name=%s, ") - ACE_LIB_TEXT ("type=%@, impl=%@, object=%@, active=%d - dummy remove failed\n"), - &this->repo_, this->name_, this->dummy_, this->dummy_->type (), - (this->dummy_->type () != 0) ? this->dummy_->type ()->object () : 0, + { + // So we found a service with the same name + if (tmp != 0 && tmp->type () != 0) + { + // If something did register a proper (non-forward-decl) + // service with the same name as our dummy, then it has + // acquired the ownership of the instance dummy_ points to. +#ifndef ACE_NLOGGING + if(ACE::debug ()) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("ACE (%P|%t) Service_Type_Dynamic_Guard") + ACE_LIB_TEXT (":<dtor> - relocating [%d-%d]") + ACE_LIB_TEXT (", repo=%@, name=%s\n"), + this->repo_begin_, + this->repo_.current_size (), + &this->repo_, + this->name_)); +#endif /* ACE_NLOGGING */ + + // Relocate any related static services. If any have been + // registered in the context of this guard, those really + // aren't static services because their code is in the DLL's + // code segment + this->repo_.relocate_i (this->repo_begin_, + this->repo_.current_size (), + tmp->dll()); + + // The ACE_Service_Gestalt::insert() modifies the memory for + // the original ACE_Service_Type instance. It will delete our + // dummy instance when replacing it with the actual + // implementation. We are hereby simply giving up ownership of + // something that no longer exists. + this->dummy_ = 0; + +#ifndef ACE_NLOGGING + if(ACE::debug ()) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("ACE (%P|%t) Service_Type_Dynamic_Guard") + ACE_LIB_TEXT (":<dtor> - done loading of %s") + ACE_LIB_TEXT (", repo[%d]=%@, type=%@, impl=%@") + ACE_LIB_TEXT (", object=%@, active=%d\n"), + this->name_, + this->repo_begin_, + &this->repo_, + tmp, + tmp->type (), + (tmp->type () != 0) ? tmp->type ()->object () : 0, + tmp->active ())); +#endif /* ACE_NLOGGING */ + } + else + { +#ifndef ACE_NLOGGING + if(ACE::debug ()) + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("ACE (%P|%t) Service_Type_Dynamic_Guard") + ACE_LIB_TEXT (":<dtor> - removing fwd decl for %s") + ACE_LIB_TEXT (", repo=%@, type=%@, impl=%@") + ACE_LIB_TEXT (", object=%@, active=%d\n"), + this->name_, + &this->repo_, + this->dummy_, + this->dummy_->type (), + (this->dummy_->type () != 0) + ? this->dummy_->type ()->object () + : 0, this->dummy_->active ())); - } - } - - // Clean up +#endif /* ACE_NLOGGING */ + + // The (dummy) forward declaration is still there and is the + // same, which means that no actual declaration was provided + // inside the guarded scope. Therefore, the forward + // declaration is no longer necessary. + if (this->repo_.remove_i (this->name_, + const_cast< ACE_Service_Type**> + (&this->dummy_)) == 0) + { + // If it is a dummy then deleting it while holding the + // repo lock is okay. There will be no call to service + // object's fini() and no possibility for deadlocks. + delete this->dummy_; + } + else + { +#ifndef ACE_NLOGGING + ACE_ERROR ((LM_WARNING, + ACE_LIB_TEXT ("ACE (%P|%t) Service_Type_Dynamic_Guard") + ACE_LIB_TEXT (":<dtor> - failed to remove fwd decl %s") + ACE_LIB_TEXT (", repo=%@, type=%@, impl=%@") + ACE_LIB_TEXT (", object=%@, active=%d: -1/%d\n"), + this->name_, + &this->repo_, + this->dummy_, + this->dummy_->type (), + (this->dummy_->type () != 0) + ? this->dummy_->type ()->object () + : 0, + this->dummy_->active (), + errno)); +#endif /* ACE_NLOGGING */ + } + } + } + + // Clean up and bail ... this->dummy_ = 0; } @@ -256,7 +318,7 @@ ACE_Service_Gestalt::~ACE_Service_Gestalt (void) ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("ACE (%P|%t) SG::dtor - this=%@, pss = %@\n"), this, this->processed_static_svcs_)); -#endif +#endif /* ACE_NLOGGING */ if (this->processed_static_svcs_ && !this->processed_static_svcs_->is_empty()) @@ -532,7 +594,6 @@ ACE_Service_Gestalt::initialize (const ACE_TCHAR *svc_name, const ACE_Service_Type *srp = 0; for (int i = 0; this->find (svc_name, &srp) == -1 && i < 2; i++) - // if (this->repo_->find (svc_name, &srp) == -1) { const ACE_Static_Svc_Descriptor *assd = ACE_Service_Config::global()->find_processed_static_svc(svc_name); |