diff options
author | iliyan <iliyan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2007-12-16 21:25:31 +0000 |
---|---|---|
committer | iliyan <iliyan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2007-12-16 21:25:31 +0000 |
commit | 6ece019eb2e50991446d80f5e4f0639291fb3007 (patch) | |
tree | 4bce73c64877e8cf2a696fc7c6f16b1fbfd640e6 | |
parent | 2b88b9c32377192ecc2f56fbaac2800e45b1fc42 (diff) | |
download | ATCD-6ece019eb2e50991446d80f5e4f0639291fb3007.tar.gz |
ChangeLogTag: Sun Dec 16 20:48:39 UTC 2007 Iliyan Jeliazkov <iliyan@ociweb.com>
-rw-r--r-- | ACE/ChangeLog.iliyan-gestalt | 42 | ||||
-rw-r--r-- | ACE/ace/Dynamic_Service.cpp | 4 | ||||
-rw-r--r-- | ACE/ace/Dynamic_Service.h | 8 | ||||
-rw-r--r-- | ACE/ace/Dynamic_Service.inl | 4 | ||||
-rw-r--r-- | ACE/ace/Dynamic_Service_Base.cpp | 6 | ||||
-rw-r--r-- | ACE/ace/Dynamic_Service_Base.h | 5 | ||||
-rw-r--r-- | ACE/ace/Dynamic_Service_Dependency.cpp | 2 | ||||
-rw-r--r-- | ACE/ace/Intrusive_Auto_Ptr.cpp | 19 | ||||
-rw-r--r-- | ACE/ace/Intrusive_Auto_Ptr.h | 160 | ||||
-rw-r--r-- | ACE/ace/Intrusive_Auto_Ptr.inl | 149 | ||||
-rw-r--r-- | ACE/ace/Refcounted_Auto_Ptr.h | 23 | ||||
-rw-r--r-- | ACE/ace/Refcounted_Auto_Ptr.inl | 21 | ||||
-rw-r--r-- | ACE/ace/Service_Config.cpp | 171 | ||||
-rw-r--r-- | ACE/ace/Service_Config.h | 71 | ||||
-rw-r--r-- | ACE/ace/Service_Config.inl | 50 | ||||
-rw-r--r-- | ACE/ace/Service_Gestalt.cpp | 38 | ||||
-rw-r--r-- | ACE/ace/Service_Gestalt.h | 17 | ||||
-rw-r--r-- | ACE/ace/Thread_Adapter.cpp | 5 | ||||
-rw-r--r-- | ACE/ace/ace.mpc | 4 | ||||
-rw-r--r-- | ACE/tests/Intrusive_Auto_Ptr_Test.cpp | 104 | ||||
-rw-r--r-- | ACE/tests/Object_Manager_Flipping_Test.cpp | 11 | ||||
-rw-r--r-- | ACE/tests/tests.mpc | 7 |
22 files changed, 773 insertions, 148 deletions
diff --git a/ACE/ChangeLog.iliyan-gestalt b/ACE/ChangeLog.iliyan-gestalt new file mode 100644 index 00000000000..f06e543e398 --- /dev/null +++ b/ACE/ChangeLog.iliyan-gestalt @@ -0,0 +1,42 @@ +Sun Dec 16 20:48:39 UTC 2007 Iliyan Jeliazkov <iliyan@ociweb.com> + + Changed the Service Config to use the PIMPL pattern instead of + inheriting from Service Gestalt. This allowed the use of a + reference counting to manage the lifetime of a Gestalt. This + begins to solve the problem discussed in in bugzilla 2980, whereby + the root service configuration context (gestalt) may end up being + finalized either by the main thread, or by the thread specific + storage cleanup. + + Added an intrusive auto pointer implementation. It is a reference + counted auto pointer that can be used for types with explicit + reference management implementations. Updated interfaces to use + the new ref-counted gestalt. + + * ace/Dynamic_Service.h: + * ace/Dynamic_Service.inl: + * ace/Dynamic_Service.cpp: + * ace/Dynamic_Service_Base.h: + * ace/Dynamic_Service_Base.cpp: + * ace/Dynamic_Service_Dependency.cpp: + * ace/Intrusive_Auto_Ptr.h: + * ace/Intrusive_Auto_Ptr.inl: + * ace/Intrusive_Auto_Ptr.cpp: + * ace/Refcounted_Auto_Ptr.h: + * ace/Refcounted_Auto_Ptr.inl: + * ace/Service_Config.h: + * ace/Service_Config.inl: + * ace/Service_Config.cpp: + * ace/Service_Gestalt.h: + * ace/Service_Gestalt.cpp: + * ace/Thread_Adapter.cpp: + * ace/ace.mpc: + + * tests/Intrusive_Auto_Ptr_Test.cpp: + + Added a new test for the intrusive reference counted auto pointer. + + * tests/Object_Manager_Flipping_Test.cpp: + * tests/tests.mpc: + + Updated to use the intrusive auto pointer diff --git a/ACE/ace/Dynamic_Service.cpp b/ACE/ace/Dynamic_Service.cpp index 53d762dc364..5522316c1bf 100644 --- a/ACE/ace/Dynamic_Service.cpp +++ b/ACE/ace/Dynamic_Service.cpp @@ -38,7 +38,7 @@ ACE_Dynamic_Service<TYPE>::instance (const ACE_TCHAR *name, } template <class TYPE> TYPE * -ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt* conf, +ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt_Auto_Ptr conf, const ACE_TCHAR *name) { ACE_Service_Object * svc_obj = @@ -48,7 +48,7 @@ ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt* conf, } template <class TYPE> TYPE * -ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt* conf, +ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt_Auto_Ptr conf, const ACE_TCHAR *name, bool no_global) { diff --git a/ACE/ace/Dynamic_Service.h b/ACE/ace/Dynamic_Service.h index ed7317ef562..3aea0e4a869 100644 --- a/ACE/ace/Dynamic_Service.h +++ b/ACE/ace/Dynamic_Service.h @@ -46,9 +46,9 @@ public: static TYPE* instance (const ACE_TCHAR *name); static TYPE* instance (const ACE_TCHAR *name, bool no_global); - static TYPE* instance (const ACE_Service_Gestalt* repo, + static TYPE* instance (const ACE_Service_Gestalt_Auto_Ptr repo, const ACE_TCHAR *name); - static TYPE* instance (const ACE_Service_Gestalt* repo, + static TYPE* instance (const ACE_Service_Gestalt_Auto_Ptr repo, const ACE_TCHAR *name, bool no_global); #if defined (ACE_USES_WCHAR) @@ -58,9 +58,9 @@ public: static TYPE* instance (const ACE_ANTI_TCHAR *name, bool no_global); - static TYPE* instance (const ACE_Service_Gestalt* repo, + static TYPE* instance (const ACE_Service_Gestalt_Auto_Ptr repo, const ACE_ANTI_TCHAR *name); - static TYPE* instance (const ACE_Service_Gestalt* repo, + static TYPE* instance (const ACE_Service_Gestalt_Auto_Ptr repo, const ACE_ANTI_TCHAR *name, bool no_global); #endif // ACE_USES_WCHAR diff --git a/ACE/ace/Dynamic_Service.inl b/ACE/ace/Dynamic_Service.inl index 48978c595ed..40c4a6bbe0a 100644 --- a/ACE/ace/Dynamic_Service.inl +++ b/ACE/ace/Dynamic_Service.inl @@ -20,14 +20,14 @@ ACE_Dynamic_Service<TYPE>::instance (const ACE_ANTI_TCHAR *name, } template <class TYPE> ACE_INLINE TYPE * -ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt* repo, +ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt_Auto_Ptr repo, const ACE_ANTI_TCHAR *name) { return instance (repo, ACE_TEXT_CHAR_TO_TCHAR (name),false); } template <class TYPE> ACE_INLINE TYPE * -ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt* repo, +ACE_Dynamic_Service<TYPE>::instance (const ACE_Service_Gestalt_Auto_Ptr repo, const ACE_ANTI_TCHAR *name, bool no_global) { diff --git a/ACE/ace/Dynamic_Service_Base.cpp b/ACE/ace/Dynamic_Service_Base.cpp index e93dde6e905..60886f7e0f7 100644 --- a/ACE/ace/Dynamic_Service_Base.cpp +++ b/ACE/ace/Dynamic_Service_Base.cpp @@ -45,7 +45,7 @@ ACE_Dynamic_Service_Base::find_i (const ACE_Service_Gestalt* &repo, ACE_TRACE ("ACE_Dynamic_Service_Base::find_i"); const ACE_Service_Type *svc_rec = 0; - ACE_Service_Gestalt* global = ACE_Service_Config::global (); + ACE_Service_Gestalt* global = ACE_Service_Config::global ().get(); for ( ; (repo->find (name, &svc_rec) == -1) && !no_global; repo = global) { @@ -60,7 +60,7 @@ ACE_Dynamic_Service_Base::find_i (const ACE_Service_Gestalt* &repo, // Get the instance using <name> for specific configuration repository. void * -ACE_Dynamic_Service_Base::instance (const ACE_Service_Gestalt* repo, +ACE_Dynamic_Service_Base::instance (const ACE_Service_Gestalt_Auto_Ptr repo, const ACE_TCHAR *name, bool no_global) { @@ -69,7 +69,7 @@ ACE_Dynamic_Service_Base::instance (const ACE_Service_Gestalt* repo, void *obj = 0; const ACE_Service_Type_Impl *type = 0; - const ACE_Service_Gestalt* repo_found = repo; + const ACE_Service_Gestalt* repo_found = repo.get (); const ACE_Service_Type *svc_rec = find_i (repo_found, name, no_global); if (svc_rec != 0) { diff --git a/ACE/ace/Dynamic_Service_Base.h b/ACE/ace/Dynamic_Service_Base.h index 7a039a1a6b2..2422b55078e 100644 --- a/ACE/ace/Dynamic_Service_Base.h +++ b/ACE/ace/Dynamic_Service_Base.h @@ -24,7 +24,8 @@ ACE_BEGIN_VERSIONED_NAMESPACE_DECL -class ACE_Service_Gestalt; +#include "ace/Service_Config.h" + class ACE_Service_Type; /** @@ -47,7 +48,7 @@ protected: /// repo. static void* instance (const ACE_TCHAR *name, bool no_global = false); - static void* instance (const ACE_Service_Gestalt* repo, + static void* instance (const ACE_Service_Gestalt_Auto_Ptr repo, const ACE_TCHAR *name, bool no_global = false); diff --git a/ACE/ace/Dynamic_Service_Dependency.cpp b/ACE/ace/Dynamic_Service_Dependency.cpp index f2a9b45d61c..cb607918851 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::current ().get(), principal); } ACE_Dynamic_Service_Dependency::ACE_Dynamic_Service_Dependency (const ACE_Service_Gestalt *cfg, diff --git a/ACE/ace/Intrusive_Auto_Ptr.cpp b/ACE/ace/Intrusive_Auto_Ptr.cpp new file mode 100644 index 00000000000..ebfb25847b4 --- /dev/null +++ b/ACE/ace/Intrusive_Auto_Ptr.cpp @@ -0,0 +1,19 @@ +// $Id$ + +#ifndef ACE_INTRUSIVE_AUTO_PTR_CPP +#define ACE_INTRUSIVE_AUTO_PTR_CPP + + +#include "ace/Intrusive_Auto_Ptr.h" + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +template <class X> +ACE_Intrusive_Auto_Ptr<X>::~ACE_Intrusive_Auto_Ptr (void) +{ + reset (0); +} + +ACE_END_VERSIONED_NAMESPACE_DECL + +#endif /* !ACE_INTRUSIVE_AUTO_PTR_CPP */ diff --git a/ACE/ace/Intrusive_Auto_Ptr.h b/ACE/ace/Intrusive_Auto_Ptr.h new file mode 100644 index 00000000000..482aff5dde0 --- /dev/null +++ b/ACE/ace/Intrusive_Auto_Ptr.h @@ -0,0 +1,160 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Intrusive_Auto_Ptr.h + * + * $Id$ + * + * @author Iliyan Jeliazkov <iliyan@ociweb.com> + * + * @note Modeled on http://www.boost.org/boost/intrusive_ptr.hpp + */ +//============================================================================= + +#ifndef ACE_INTRUSIVE_AUTO_PTR_H +#define ACE_INTRUSIVE_AUTO_PTR_H + +#include /**/ "ace/pre.h" + +#include "ace/Auto_Ptr.h" +#include "ace/Atomic_Op.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +// Forward decl. +template <class X> class ACE_Intrusive_Auto_Ptr; + +/** + * @class ACE_Intrusive_Auto_Ptr + * + * @brief This class implements support for a reference counted + * auto_ptr. It assumes refernce counting abilities of the + * parameterizing class. + * + * Assigning or copying instances of an ACE_Intrusive_Auto_Ptr will + * automatically increment the reference count. When the last instance + * that references a ACE_Intrusive_Auto_Ptr instance is destroyed or + * overwritten, it will invoke delete on its underlying pointer. + * + * The ACE_Intrusive_Auto_Ptr works by maintaining a reference to a + * separate representation object, ACE_Intrusive_Auto_Ptr_Rep. That + * separate representation object contains the reference count and the + * actual pointer value. + */ +template <class X> +class ACE_Intrusive_Auto_Ptr +{ +protected: + + /// Used to define a proper boolean conversion + static void unspecified_bool( ACE_Intrusive_Auto_Ptr<X>***){}; + typedef void (*unspecified_bool_type)( ACE_Intrusive_Auto_Ptr<X>***); + +public: + + // = Initialization and termination methods. + + /// Constructor that initializes an ACE_Intrusive_Auto_Ptr to + /// the specified pointer value. + ACE_Intrusive_Auto_Ptr (X *p = 0, bool addref = true); + + /// Copy constructor binds the new ACE_Intrusive_Auto_Ptr to the + /// representation object referenced by @a r. + /// An ACE_Intrusive_Auto_Ptr_Rep is created if necessary. + ACE_Intrusive_Auto_Ptr (const ACE_Intrusive_Auto_Ptr<X> &r); + + // Derived class copy ctor + template<class U> ACE_Intrusive_Auto_Ptr(const ACE_Intrusive_Auto_Ptr<U> & rhs); + + // Boolean conversion + // never throws + operator unspecified_bool_type() const; + + /// Destructor. Releases the reference to the underlying representation. + /// If the release of that reference causes its reference count to reach 0, + /// the representation object will also be destroyed. + virtual ~ACE_Intrusive_Auto_Ptr (void); + + /// Assignment operator that binds the current object and @a r to the same + /// ACE_Intrusive_Auto_Ptr_Rep. An ACE_Intrusive_Auto_Ptr_Rep + /// is created if necessary. + void operator = (const ACE_Intrusive_Auto_Ptr<X> &r); + + /// Redirection operator + X *operator-> (void) const; + + /// Accessor method. + X &operator *() const; + + /// Releases the reference to the underlying representation object. + /// @retval The pointer value prior to releasing it. + X *release (void); + + /// Releases the current pointer value and then sets a new + /// pointer value specified by @a p. + void reset (X *p = 0); + + /// Get the pointer value. + X *get (void) const; + + /// Get the reference count value. + long count (void) const; + + /// Returns @c true if this object does not contain a valid pointer. + // bool null (void) const; + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + +protected: + + /// Protect operations on the ACE_Intrusive_Auto_Ptr. + X *rep_; +}; + + /// Equality operator that returns @c true if both + /// ACE_Intrusive_Auto_Ptr objects point to the same underlying + /// representation. It does not compare the actual pointers. + /** + * @note It also returns @c true if both objects have just been + * instantiated and not used yet. + */ +template<class T, class U> +bool operator==(ACE_Intrusive_Auto_Ptr<T> const & a, ACE_Intrusive_Auto_Ptr<U> const & b); + +/// Inequality operator, which is the opposite of equality. +template<class T, class U> +bool operator!=(ACE_Intrusive_Auto_Ptr<T> const & a, ACE_Intrusive_Auto_Ptr<U> const & b); + +template<class T, class U> +bool operator==(ACE_Intrusive_Auto_Ptr<T> const & a, U * b); + +template<class T, class U> +bool operator!=(ACE_Intrusive_Auto_Ptr<T> & a, U * b); + +template<class T, class U> +bool operator==(T * a, ACE_Intrusive_Auto_Ptr<U> const & b); + +template<class T, class U> +bool operator!=(T * a, ACE_Intrusive_Auto_Ptr<U> const & b); + +ACE_END_VERSIONED_NAMESPACE_DECL + +#include "ace/Intrusive_Auto_Ptr.inl" + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ace/Intrusive_Auto_Ptr.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Intrusive_Auto_Ptr.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#include /**/ "ace/post.h" + +#endif /* ACE_INTRUSIVE_AUTO_PTR_H */ diff --git a/ACE/ace/Intrusive_Auto_Ptr.inl b/ACE/ace/Intrusive_Auto_Ptr.inl new file mode 100644 index 00000000000..fc52eb929c4 --- /dev/null +++ b/ACE/ace/Intrusive_Auto_Ptr.inl @@ -0,0 +1,149 @@ +// -*- C++ -*- +// +// $Id$ + +#include "ace/Guard_T.h" +#include "ace/Log_Msg.h" + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +template <class X> ACE_INLINE +ACE_Intrusive_Auto_Ptr<X>::ACE_Intrusive_Auto_Ptr (X *p, bool addref) + : rep_ (p) +{ + if (rep_ != 0 )//&& addref) + X::intrusive_add_ref (rep_); +} + +template <class X> ACE_INLINE +ACE_Intrusive_Auto_Ptr<X>::ACE_Intrusive_Auto_Ptr (const ACE_Intrusive_Auto_Ptr<X> &r) + : rep_ (r.rep_) +{ + if (rep_ != 0) + X::intrusive_add_ref (rep_); +} + +template <class X> ACE_INLINE +ACE_Intrusive_Auto_Ptr<X>::operator unspecified_bool_type() const +{ + return rep_ == 0 ? 0: unspecified_bool; +} + +template <class X> ACE_INLINE X * +ACE_Intrusive_Auto_Ptr<X>::operator-> (void) const +{ + return this->rep_; +} + +template<class X> ACE_INLINE X & +ACE_Intrusive_Auto_Ptr<X>::operator *() const +{ + return *this->rep_; +} + +template <class X> ACE_INLINE X* +ACE_Intrusive_Auto_Ptr<X>::get (void) const +{ + // We return the ACE_Future_rep. + return this->rep_; +} + +template<class X> ACE_INLINE X * +ACE_Intrusive_Auto_Ptr<X>::release (void) +{ + X *p = this->rep_; + if (this->rep_ != 0) + X::intrusive_remove_ref (this->rep_); + + this->rep_ = 0; + return p; +} + +template<class X> ACE_INLINE void +ACE_Intrusive_Auto_Ptr<X>::reset (X *p) +{ + // Avoid deleting the underlying auto_ptr if assigning the same actual + // pointer value. + if (this->rep_ == p) + return; + + X *old_rep = this->rep_; + this->rep_ = p; + + if (this->rep_ != 0) + X::intrusive_add_ref (this->rep_); + + if (old_rep != 0) + X::intrusive_remove_ref (old_rep); + + return; +} + +template <class X> ACE_INLINE void +ACE_Intrusive_Auto_Ptr<X>::operator = (const ACE_Intrusive_Auto_Ptr<X> &rhs) +{ + // bind <this> to the same <ACE_Intrusive_Auto_Ptr_Rep> as <r>. + X *old_rep = this->rep_; + if (rhs.rep_ != 0) + { + this->rep_ = rhs.rep_; + X::intrusive_add_ref (this->rep_); + X::intrusive_remove_ref (old_rep); + } + else // Assign a 0 rep to this + { + X::intrusive_remove_ref (old_rep); + this->rep_ = 0; + } +} + +// Copy derived class constructor +template<class X> template <class U> ACE_INLINE +ACE_Intrusive_Auto_Ptr<X>::ACE_Intrusive_Auto_Ptr (const ACE_Intrusive_Auto_Ptr<U> & rhs) +{ + // note implicit cast from U* to T* so illegal copy will generate a + // compiler warning here + this->rep_ = rhs.operator-> (); + X::intrusive_add_ref(this->rep_); +} + + /// Equality operator that returns @c true if both + /// ACE_Intrusive_Auto_Ptr objects point to the same underlying + /// representation. It does not compare the actual pointers. + /** + * @note It also returns @c true if both objects have just been + * instantiated and not used yet. + */ +template<class T, class U> ACE_INLINE bool operator==(ACE_Intrusive_Auto_Ptr<T> const & a, ACE_Intrusive_Auto_Ptr<U> const & b) +{ + return a.get() == b.get(); +} + + /// Inequality operator, which is the opposite of equality. + template<class T, class U> ACE_INLINE bool operator!=(ACE_Intrusive_Auto_Ptr<T> const & a, ACE_Intrusive_Auto_Ptr<U> const & b) +{ + return a.get() != b.get(); +} + + template<class T, class U> ACE_INLINE bool operator==(ACE_Intrusive_Auto_Ptr<T> const & a, U * b) +{ + return a.get() == b; +} + + template<class T, class U> ACE_INLINE bool operator!=(ACE_Intrusive_Auto_Ptr<T> & a, U * b) +{ + return a.get() != b; +} + + template<class T, class U> ACE_INLINE bool operator==(T * a, ACE_Intrusive_Auto_Ptr<U> const & b) +{ + return a == b.get(); +} + + template<class T, class U> ACE_INLINE bool operator!=(T * a, ACE_Intrusive_Auto_Ptr<U> const & b) +{ + return a != b.get(); +} + + +ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/Refcounted_Auto_Ptr.h b/ACE/ace/Refcounted_Auto_Ptr.h index 782f9ab85db..4498fa25709 100644 --- a/ACE/ace/Refcounted_Auto_Ptr.h +++ b/ACE/ace/Refcounted_Auto_Ptr.h @@ -46,6 +46,16 @@ template <class X, class ACE_LOCK> class ACE_Refcounted_Auto_Ptr; template <class X, class ACE_LOCK> class ACE_Refcounted_Auto_Ptr { +protected: + /// the ACE_Refcounted_Auto_Ptr_Rep + typedef ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> AUTO_REFCOUNTED_PTR_REP; + + /// Used to define a proper boolean conversion + typedef ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> RAP; + static void unspecified_bool( RAP***){}; + typedef void (*unspecified_bool_type)( RAP***); + + public: // = Initialization and termination methods. @@ -59,6 +69,13 @@ public: /// An ACE_Refcounted_Auto_Ptr_Rep is created if necessary. ACE_Refcounted_Auto_Ptr (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &r); + // Boolean conversion + // never throws + operator unspecified_bool_type() const; + + ACE_Refcounted_Auto_Ptr (ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *); + ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *rep() const; + /// Destructor. Releases the reference to the underlying representation. /// If the release of that reference causes its reference count to reach 0, /// the representation object will also be destroyed. @@ -98,7 +115,7 @@ public: /// Get the pointer value. X *get (void) const; - /// Get the reference count value. + /// Get the reference count value. long count (void) const; /// Returns @c true if this object does not contain a valid pointer. @@ -108,8 +125,6 @@ public: ACE_ALLOC_HOOK_DECLARE; protected: - /// the ACE_Refcounted_Auto_Ptr_Rep - typedef ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> AUTO_REFCOUNTED_PTR_REP; /// Protect operations on the ACE_Refcounted_Auto_Ptr. AUTO_REFCOUNTED_PTR_REP *rep_; @@ -170,7 +185,7 @@ private: /// Reference count. mutable ACE_Atomic_Op<ACE_LOCK, long> ref_count_; -private: +public: // = Constructor and destructor private. ACE_Refcounted_Auto_Ptr_Rep (X *p = 0); ~ACE_Refcounted_Auto_Ptr_Rep (void); diff --git a/ACE/ace/Refcounted_Auto_Ptr.inl b/ACE/ace/Refcounted_Auto_Ptr.inl index f44159606ff..f0a192047d6 100644 --- a/ACE/ace/Refcounted_Auto_Ptr.inl +++ b/ACE/ace/Refcounted_Auto_Ptr.inl @@ -95,11 +95,32 @@ ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::ACE_Refcounted_Auto_Ptr (X *p) } template <class X, class ACE_LOCK> inline +ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::operator unspecified_bool_type() const +{ + return null() ? 0: unspecified_bool; +} + + +template <class X, class ACE_LOCK> inline ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::ACE_Refcounted_Auto_Ptr (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &r) : rep_ (AUTO_REFCOUNTED_PTR_REP::attach (((ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &) r).rep_)) { } +template <class X, class ACE_LOCK> inline +ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::ACE_Refcounted_Auto_Ptr (ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK> *p) + : rep_ (AUTO_REFCOUNTED_PTR_REP::attach (p)) +{ +} + +template <class X, class ACE_LOCK> inline ACE_Refcounted_Auto_Ptr_Rep<X, ACE_LOCK>* +ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::rep (void) const +{ + return this->rep_; +} + + + template <class X, class ACE_LOCK> inline bool ACE_Refcounted_Auto_Ptr<X, ACE_LOCK>::operator== (const ACE_Refcounted_Auto_Ptr<X, ACE_LOCK> &r) const { diff --git a/ACE/ace/Service_Config.cpp b/ACE/ace/Service_Config.cpp index 02fc863790c..05b9d2a4b19 100644 --- a/ACE/ace/Service_Config.cpp +++ b/ACE/ace/Service_Config.cpp @@ -41,8 +41,8 @@ typedef ACE_Unmanaged_Singleton<ACE_Service_Config, ACE_SYNCH_RECURSIVE_MUTEX> ACE_SERVICE_CONFIG_SINGLETON; -/// -ACE_Service_Config_Guard::ACE_Service_Config_Guard (ACE_Service_Gestalt * psg) +/// ctor +ACE_Service_Config_Guard::ACE_Service_Config_Guard (ACE_Service_Gestalt_Auto_Ptr psg) : saved_ (ACE_Service_Config::instance ()) { if (ACE::debug ()) @@ -50,7 +50,7 @@ ACE_Service_Config_Guard::ACE_Service_Config_Guard (ACE_Service_Gestalt * psg) ACE_TEXT ("ACE (%P|%t) SCG:<ctor=%@>") ACE_TEXT (" - config=%@ repo=%@ superceded by repo=%@\n"), this, - this->saved_, + this->saved_.get (), this->saved_->repo_, psg->repo_)); @@ -160,8 +160,8 @@ ACE_Service_Config::parse_args_i (int argc, ACE_TCHAR *argv[]) for (int c = getopt.opt_ind (); c < argc; ++c) superargv.add (argv[c-1], true); - return ACE_Service_Gestalt::parse_args_i (superargv.argc (), - superargv.argv ()); + return instance_->parse_args_i (superargv.argc (), + superargv.argv ()); } /* parse_args_i () */ @@ -181,25 +181,25 @@ ACE_Service_Config::open_i (const ACE_TCHAR program_name[], ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("ACE (%P|%t) SC::open_i - this=%@, opened=%d, ") ACE_TEXT ("loadstatics=%d\n"), - this, this->is_opened_, this->no_static_svcs_)); + this, instance_->is_opened_, instance_->no_static_svcs_)); // Guard against reentrant processing. For example, // if the singleton gestalt (ubergestalt) was already open, // do not open it again... // The base class open_i increments this and we are // forwarding to it, so we don't have to increment here. - if (this->is_opened_ != 0) - return ACE_Service_Gestalt::open_i (program_name, - logger_key, - ignore_static_svcs, - ignore_default_svc_conf_file, - ignore_debug_flag); + if (instance_->is_opened_ != 0) + return instance_->open_i (program_name, + logger_key, + ignore_static_svcs, + ignore_default_svc_conf_file, + ignore_debug_flag); // Check for things we need to do on a per-process basis and which // may not be safe, or wise to do an a per instance basis // Override any defaults, if required - this->no_static_svcs_ = ignore_static_svcs; + instance_->no_static_svcs_ = ignore_static_svcs; // Become a daemon before doing anything else. if (this->be_a_daemon_) @@ -232,7 +232,7 @@ ACE_Service_Config::open_i (const ACE_TCHAR program_name[], // Only use the static <logger_key_> if the caller doesn't // override it in the parameter list or if the key supplied is // equal to the default static logger key. - key = this->logger_key_; + key = instance_->logger_key_; else ACE_SET_BITS (flags, ACE_Log_Msg::LOGGER); @@ -248,7 +248,7 @@ ACE_Service_Config::open_i (const ACE_TCHAR program_name[], // Initialize the Service Repository (this will still work if // user forgets to define an object of type ACE_Service_Config). - ACE_Service_Repository::instance (ACE_Service_Config::MAX_SERVICES); + ACE_Service_Repository::instance (ACE_Service_Gestalt::MAX_SERVICES); // Initialize the ACE_Reactor (the ACE_Reactor should be the // same size as the ACE_Service_Repository). @@ -275,7 +275,7 @@ ACE_Service_Config::open_i (const ACE_TCHAR program_name[], if (result == -1) return -1; - if (this->init_svc_conf_file_queue () == -1) + if (instance_->init_svc_conf_file_queue () == -1) return -1; // Check if the default file exists before attempting to queue it @@ -290,11 +290,11 @@ ACE_Service_Config::open_i (const ACE_TCHAR program_name[], } if (!ignore_default_svc_conf_file - && this->svc_conf_file_queue_->is_empty ()) + && instance_->svc_conf_file_queue_->is_empty ()) { // Load the default "svc.conf" entry here if there weren't // overriding -f arguments in <parse_args>. - if (this->svc_conf_file_queue_->enqueue_tail + if (instance_->svc_conf_file_queue_->enqueue_tail (ACE_TString (ACE_DEFAULT_SVC_CONF)) == -1) { ACE_ERROR_RETURN ((LM_ERROR, @@ -306,31 +306,17 @@ ACE_Service_Config::open_i (const ACE_TCHAR program_name[], } } - return ACE_Service_Gestalt::open_i (program_name, - logger_key, - ignore_static_svcs, - ignore_default_svc_conf_file, - ignore_debug_flag); -} - -// 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 -// the existing source code can keep using -// ACE_Service_Config::static_svcs(), however now it is not necessary -// to expose the repository storage *and* it is much easier to debug -// service registration problems. - -ACE_Service_Gestalt * -ACE_Service_Config::static_svcs (void) -{ - return ACE_Service_Config::instance (); + return instance_->open_i (program_name, + logger_key, + ignore_static_svcs, + ignore_default_svc_conf_file, + ignore_debug_flag); } /// Return the global configuration instance. Always returns the same /// instance -ACE_Service_Config * -ACE_Service_Config::global (void) +ACE_Service_Config* +ACE_Service_Config::singleton (void) { return ACE_SERVICE_CONFIG_SINGLETON::instance (); } @@ -378,17 +364,60 @@ ACE_Service_Config::resume (const ACE_TCHAR svc_name[]) ACE_Service_Config::ACE_Service_Config (bool ignore_static_svcs, size_t size, int signum) - : ACE_Service_Gestalt (size, false, ignore_static_svcs) { ACE_TRACE ("ACE_Service_Config::ACE_Service_Config"); + #if defined (ACE_HAS_TSS_EMULATION) ACE_Object_Manager::init_tss (); #endif - this->tss_.ts_object (this); + + // IJ: Need to find a better way of instantiating the gestalt ... + ACE_Service_Gestalt* tmp = 0; + ACE_NEW_NORETURN (tmp, + ACE_Service_Gestalt (size, false, ignore_static_svcs)); + + //ACE_Service_Gestalt::intrusive_add_ref (tmp); + this->tss_.ts_object (tmp); + + this->instance_ = tmp; + ACE_Service_Config::signum_ = signum; } + +ACE_Service_Config::ACE_Service_Config (const ACE_TCHAR program_name[], + const ACE_TCHAR *logger_key) +{ + ACE_TRACE ("ACE_Service_Config::ACE_Service_Config"); + +#if defined (ACE_HAS_TSS_EMULATION) + ACE_Object_Manager::init_tss (); +#endif + + // IJ: Need to find a better way of instantiating the gestalt ... + ACE_Service_Gestalt* tmp = 0; + ACE_NEW_NORETURN (tmp, + ACE_Service_Gestalt (ACE_Service_Repository::DEFAULT_SIZE, false)); + + //ACE_Service_Gestalt::intrusive_add_ref (tmp); + this->tss_.ts_object (tmp); + + this->instance_ = tmp; + + if (this->open (program_name, + logger_key) == -1 && errno != ENOENT) + { + + // Only print out an error if it wasn't the svc.conf file that was + // missing. + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) SC failed to open: %p\n"), + program_name)); + } +} + + #if (ACE_USES_CLASSIC_SVC_CONF == 0) ACE_Service_Type * ACE_Service_Config::create_service_type (const ACE_TCHAR *n, @@ -446,27 +475,6 @@ ACE_Service_Config::create_service_type_impl (const ACE_TCHAR *name, } -ACE_Service_Config::ACE_Service_Config (const ACE_TCHAR program_name[], - const ACE_TCHAR *logger_key) - : ACE_Service_Gestalt (ACE_Service_Repository::DEFAULT_SIZE, false) -{ - ACE_TRACE ("ACE_Service_Config::ACE_Service_Config"); -#if defined (ACE_HAS_TSS_EMULATION) - ACE_Object_Manager::init_tss (); -#endif - this->tss_.ts_object (this); - if (this->open (program_name, - logger_key) == -1 && errno != ENOENT) - { - - // Only print out an error if it wasn't the svc.conf file that was - // missing. - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("(%P|%t) SC failed to open: %p\n"), - program_name)); - } -} - // Signal handling API to trigger dynamic reconfiguration. void @@ -512,27 +520,25 @@ ACE_Service_Config::reconfigure (void) int ACE_Service_Config::close (void) { - int const result1 = ACE_Service_Config::instance ()->close (); + ACE_Service_Gestalt_Auto_Ptr ginst (ACE_Service_Config::instance ()); + + int result1 = 0; + if (ginst != 0) + result1 = ginst->close (); // Delete the service repository. All the objects inside the // service repository should already have been finalized. - int const result2 = ACE_Service_Config::close_svcs (); + ACE_Service_Repository::close_singleton (); + + // ACE_Service_Config::current (global ()); + ACE_Service_Config::current (0); - // Do away with the Singleton + // Do away with the singleton ACE_Service_Config (calls dtor) ACE_SERVICE_CONFIG_SINGLETON::close (); - return (result1 | result2); + return result1; } -int -ACE_Service_Config::close_svcs (void) -{ - ACE_TRACE ("ACE_Service_Config::close_svcs"); - - ACE_Service_Repository::close_singleton (); - ACE_Service_Config::current (global ()); - return 0; -} int ACE_Service_Config::fini_svcs (void) @@ -553,15 +559,22 @@ ACE_Service_Config::fini_svcs (void) return result; } + +template<> void +ACE_TSS <ACE_Service_Gestalt>::cleanup (void* p) +{ + // Just decrement the reference count. This eliminates dependency + // and ordering problems between TSS rundown and ACE::fini() + ACE_Service_Gestalt::intrusive_remove_ref (reinterpret_cast<ACE_Service_Gestalt*> (p)); +} + + + // Perform user-specified close activities and remove dynamic memory. ACE_Service_Config::~ACE_Service_Config (void) { ACE_TRACE ("ACE_Service_Config::~ACE_Service_Config"); - - // We do not want ~ACE_TSS<> to delete this again (single-thread - // builds) - this->tss_.ts_object (0); } // ************************************************************ diff --git a/ACE/ace/Service_Config.h b/ACE/ace/Service_Config.h index 1c1c147af8f..ea20db3c5c8 100644 --- a/ACE/ace/Service_Config.h +++ b/ACE/ace/Service_Config.h @@ -19,6 +19,7 @@ #include "ace/Default_Constants.h" #include "ace/Service_Gestalt.h" #include "ace/TSS_T.h" +#include "ace/Intrusive_Auto_Ptr.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once @@ -133,8 +134,19 @@ public: bool operator!= (ACE_Static_Svc_Descriptor &) const; }; + #define ACE_Component_Config ACE_Service_Config +typedef ACE_Intrusive_Auto_Ptr<ACE_Service_Gestalt> ACE_Service_Gestalt_Auto_Ptr; + +/// A partial specialization for ACE_TSS::cleanup() which uses a +/// reference-counted auto pointer to ensure safe deletion of the root +/// SG from either the thread run-down, or the SC dtor (called from +/// ACE::fini()) + +template<> void +ACE_TSS <ACE_Service_Gestalt>::cleanup (void*); + /** * @class ACE_Service_Config * @@ -166,9 +178,14 @@ public: * not eliminated, by _not_ #defining * ACE_HAS_NONSTATIC_OBJECT_MANAGER. */ -class ACE_Export ACE_Service_Config: public ACE_Service_Gestalt +class ACE_Export ACE_Service_Config { + // The Instance, or the global (default) configuration context. + // The monostate would forward the calls to that instance. The TSS + // will point here + ACE_Service_Gestalt_Auto_Ptr instance_; + public: // = Initialization and termination methods. @@ -225,14 +242,20 @@ protected: * 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. + * instead of through the global singleton. + * When a thread is loading (a cascade of) DLLs that need to register + * services in a different gestalt instance, this mechanism ensures + * said gestalt will be used as the global one, on that thread. */ ACE_TSS <ACE_Service_Gestalt> tss_; /// = Static interfaces + /** + * Returns the process-wide global singleton instance. It would + * have been created and will be managed by the Object Manager. + */ + static ACE_Service_Config* singleton (void); + public: /** @@ -242,19 +265,10 @@ public: * 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_Config* global (void); + static ACE_Service_Gestalt_Auto_Ptr current (ACE_Service_Gestalt_Auto_Ptr); /// Accessor for the "current" service gestalt - static ACE_Service_Gestalt* current (void); + static ACE_Service_Gestalt_Auto_Ptr current (void); /** * This is what the static service initializators are hard-wired to @@ -265,7 +279,16 @@ public: * dynamic services, which can contain their own static services and * static initializers. */ - static ACE_Service_Gestalt* instance (void); + static ACE_Service_Gestalt_Auto_Ptr instance (void); + + /** + * 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_Auto_Ptr global (void); /** * Performs an open without parsing command-line arguments. The @@ -352,13 +375,6 @@ public: /// configured services in the <Service_Repository>. static int fini_svcs (void); - /** - * Perform user-specified close hooks on all of the configured - * services in the Service_Repository, then delete the - * Service_Repository itself. Returns 0. - */ - static int close_svcs (void); - /// True if reconfiguration occurred. static int reconfig_occurred (void); @@ -388,7 +404,7 @@ public: /// idiom for registering static services: /// /// ACE_Service_Config::static_svcs ()->insert (...); - static ACE_Service_Gestalt *static_svcs (void); + static ACE_Service_Gestalt_Auto_Ptr static_svcs (void); /// Insert a static service descriptor for processing on open_i(). The /// corresponding ACE_STATIC_SVC_* macros were chaged to use this method @@ -585,7 +601,7 @@ private: class ACE_Export ACE_Service_Config_Guard { public: - ACE_Service_Config_Guard (ACE_Service_Gestalt * psg); + ACE_Service_Config_Guard (ACE_Service_Gestalt_Auto_Ptr psg); ~ACE_Service_Config_Guard (void); private: @@ -594,7 +610,8 @@ private: ACE_Service_Config_Guard& operator= (const ACE_Service_Config_Guard&); private: - ACE_Service_Gestalt* saved_; + ACE_Service_Gestalt_Auto_Ptr saved_; + }; diff --git a/ACE/ace/Service_Config.inl b/ACE/ace/Service_Config.inl index 1cc6e35fe1d..6969fe65e1e 100644 --- a/ACE/ace/Service_Config.inl +++ b/ACE/ace/Service_Config.inl @@ -51,15 +51,37 @@ 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_Auto_Ptr +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) +ACE_INLINE ACE_Service_Gestalt_Auto_Ptr +ACE_Service_Config::current (void) { - return ACE_Service_Config::global ()->tss_; + // Make an intrusive auto ptr, without changing the reference count + ACE_Service_Gestalt* g = ACE_Service_Config::singleton ()->tss_.ts_object(); + return ACE_Service_Gestalt_Auto_Ptr (g); +} + +/// A mutator to set the "current" (TSS) gestalt instance. +ACE_INLINE ACE_Service_Gestalt_Auto_Ptr +ACE_Service_Config::current (ACE_Service_Gestalt_Auto_Ptr newcurrent) +{ + // return ACE_Service_Gestalt_Auto_Ptr (ACE_Service_Config::singleton ()->tss_.ts_object(newcurrent.get())); + ACE_Service_Gestalt* g = newcurrent.get (); + if (g != 0) ACE_Service_Gestalt::intrusive_add_ref (g); + + ACE_Service_Gestalt* old = ACE_Service_Config::singleton ()->tss_.ts_object(g); + return ACE_Service_Gestalt_Auto_Ptr (old, false); } /// Return the configuration instance, considered "global" in the @@ -67,20 +89,26 @@ ACE_Service_Config::instance (void) /// 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) +ACE_INLINE ACE_Service_Gestalt_Auto_Ptr +ACE_Service_Config::instance (void) { - return ACE_Service_Config::global ()->tss_; + return ACE_Service_Config::current (); } -/// A mutator to set the "current" (TSS) gestalt instance. -ACE_INLINE ACE_Service_Gestalt* -ACE_Service_Config::current (ACE_Service_Gestalt *newcurrent) +// 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 +// the existing source code can keep using +// ACE_Service_Config::static_svcs(), however now it is not necessary +// to expose the repository storage *and* it is much easier to debug +// service registration problems. + +ACE_INLINE ACE_Service_Gestalt_Auto_Ptr +ACE_Service_Config::static_svcs (void) { - return ACE_Service_Config::global ()->tss_.ts_object (newcurrent); + return ACE_Service_Config::current (); } - /// Compare two service descriptors for equality. ACE_INLINE bool ACE_Static_Svc_Descriptor::operator== (ACE_Static_Svc_Descriptor &d) const diff --git a/ACE/ace/Service_Gestalt.cpp b/ACE/ace/Service_Gestalt.cpp index c644ec6ef72..166fd841d4b 100644 --- a/ACE/ace/Service_Gestalt.cpp +++ b/ACE/ace/Service_Gestalt.cpp @@ -196,8 +196,33 @@ ACE_Service_Gestalt::Processed_Static_Svc::~Processed_Static_Svc (void) // ---------------------------------------- + +void +ACE_Service_Gestalt::intrusive_add_ref (ACE_Service_Gestalt* g) +{ + if (g != 0) + { + ++g->refcnt_; + printf ("//++refcnt=%ld\n", g->refcnt_.value ()); + } +} + +void +ACE_Service_Gestalt::intrusive_remove_ref (ACE_Service_Gestalt* g) +{ + if (g != 0) + { + printf ("//refcnt--=%ld\n", g->refcnt_.value()); + if (--g->refcnt_ == 0) + delete g; + } + +} + + ACE_Service_Gestalt::~ACE_Service_Gestalt (void) { + if (this->svc_repo_is_owned_) delete this->repo_; @@ -225,8 +250,14 @@ ACE_Service_Gestalt::~ACE_Service_Gestalt (void) delete *pss; } } + delete this->processed_static_svcs_; this->processed_static_svcs_ = 0; + + delete this->svc_conf_file_queue_; + this->svc_conf_file_queue_ = 0; + + ACE_DEBUG ((LM_STARTUP, "(%P|%t) ACE_Service_Gestalt::~ACE_Service_Gestalt\n")); } ACE_Service_Gestalt::ACE_Service_Gestalt (size_t size, @@ -243,6 +274,8 @@ ACE_Service_Gestalt::ACE_Service_Gestalt (size_t size, , static_svcs_ (0) , processed_static_svcs_ (0) { + ACE_DEBUG ((LM_STARTUP, "(%P|%t) ACE_Service_Gestalt::ACE_Service_Gestalt\n")); + (void)this->init_i (); #ifndef ACE_NLOGGING @@ -809,7 +842,9 @@ ACE_Service_Gestalt::process_directives_i (ACE_Svc_Conf_Param *param) // other static services registered. Thus this instance will own both the // DLL and those static services, which implies that their finalization // will be performed in the correct order, i.e. prior to finalizing the DLL - ACE_Service_Config_Guard guard (this); + ACE_Service_Gestalt_Auto_Ptr tmp (this); + ACE_Service_Config_Guard guard (tmp); + tmp.release(); #ifndef ACE_NLOGGING if (ACE::debug ()) @@ -990,7 +1025,6 @@ ACE_Service_Gestalt::init_svc_conf_file_queue (void) ACE_NEW_RETURN (tmp, ACE_SVC_QUEUE, -1); - delete this->svc_conf_file_queue_; this->svc_conf_file_queue_ = tmp; } diff --git a/ACE/ace/Service_Gestalt.h b/ACE/ace/Service_Gestalt.h index eee906f40c3..50ac3c16eff 100644 --- a/ACE/ace/Service_Gestalt.h +++ b/ACE/ace/Service_Gestalt.h @@ -29,6 +29,7 @@ #include "ace/Singleton.h" #include "ace/OS_NS_signal.h" #include "ace/Synch_Traits.h" +#include "ace/Atomic_Op.h" ACE_BEGIN_VERSIONED_NAMESPACE_DECL @@ -63,14 +64,14 @@ class ACE_Service_Gestalt; * may or may not be bounded by the lifetime of the gestalt, that owns * it. This feature is important for the derived classes and the * Service Config in particular. - + * */ class ACE_Export ACE_Service_Gestalt { private: - /** - * Not implemented to enforce no copying - */ + /// + /// Not implemented to enforce no copying + // ACE_UNIMPLEMENTED_FUNC (ACE_Service_Gestalt(const ACE_Service_Gestalt&)) ACE_UNIMPLEMENTED_FUNC (ACE_Service_Gestalt& operator=(const ACE_Service_Gestalt&)) @@ -401,6 +402,7 @@ protected: friend class ACE_Dynamic_Service_Base; friend class ACE_Service_Object; + friend class ACE_Service_Config; friend class ACE_Service_Config_Guard; protected: @@ -447,6 +449,13 @@ protected: /// the static_svcs_ list. ACE_PROCESSED_STATIC_SVCS* processed_static_svcs_; + /// Support for intrusive reference counting + ACE_Atomic_Op<ACE_SYNCH_MUTEX, long> refcnt_; + + public: + static void intrusive_add_ref (ACE_Service_Gestalt*); + static void intrusive_remove_ref (ACE_Service_Gestalt*); + }; /* class ACE_Service_Gestalt */ diff --git a/ACE/ace/Thread_Adapter.cpp b/ACE/ace/Thread_Adapter.cpp index d68dc6c8061..a6418ddddab 100644 --- a/ACE/ace/Thread_Adapter.cpp +++ b/ACE/ace/Thread_Adapter.cpp @@ -5,6 +5,7 @@ #include "ace/Thread_Exit.h" #include "ace/Thread_Hook.h" #include "ace/Object_Manager_Base.h" +#include "ace/Service_Config.h" ACE_RCSID (ace, Thread_Adapter, @@ -52,6 +53,10 @@ ACE_Thread_Adapter::invoke (void) // ACE_Log_Msg instance in thread-specific storage. this->inherit_log_msg (); + ACE_ASSERT (0 == ACE_Service_Config::current ()); + ACE_Intrusive_Auto_Ptr<ACE_Service_Gestalt> tmp (ACE_Service_Config::global()); + ACE_Service_Config::current (tmp); + #if !defined(ACE_USE_THREAD_MANAGER_ADAPTER) // NOTE: this preprocessor directive should match the one in above // ACE_Thread_Exit::instance (). With the Xavier Pthreads package, diff --git a/ACE/ace/ace.mpc b/ACE/ace/ace.mpc index a6053729a3d..e0b0388d47c 100644 --- a/ACE/ace/ace.mpc +++ b/ACE/ace/ace.mpc @@ -310,6 +310,8 @@ project(ACE) : acedefaults, install, other, codecs, token, svcconf, uuid, fileca Hash_Multi_Map_Manager_T.cpp Hash_Map_With_Allocator_T.cpp IOStream_T.cpp + + Intrusive_Auto_Ptr.cpp Intrusive_List.cpp Intrusive_List_Node.cpp LOCK_SOCK_Acceptor.cpp @@ -360,6 +362,7 @@ project(ACE) : acedefaults, install, other, codecs, token, svcconf, uuid, fileca Condition_T.inl Guard_T.inl Handle_Gobbler.inl + Intrusive_Auto_Ptr.inl Lock_Adapter_T.inl Refcounted_Auto_Ptr.inl Reverse_Lock_T.inl @@ -382,6 +385,7 @@ project(ACE) : acedefaults, install, other, codecs, token, svcconf, uuid, fileca Handle_Gobbler.h If_Then_Else.h IO_Cntl_Msg.h + Intrusive_Auto_Ptr.h Lock_Adapter_T.h Log_Priority.h Malloc_Base.h diff --git a/ACE/tests/Intrusive_Auto_Ptr_Test.cpp b/ACE/tests/Intrusive_Auto_Ptr_Test.cpp new file mode 100644 index 00000000000..a6e0d902c74 --- /dev/null +++ b/ACE/tests/Intrusive_Auto_Ptr_Test.cpp @@ -0,0 +1,104 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Intrusive_Auto_Ptr_Test +// +// = DESCRIPTION +// This test verifies the functionality of the <ACE_Intrusive_Auto_Ptr> +// implementation. +// +// = AUTHOR +// Iliyan Jeliazkov <iliyan@ociweb.com> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Intrusive_Auto_Ptr.h" +#include "ace/Thread_Manager.h" + +ACE_RCSID(tests, Intrusive_Auto_Ptr_Test, "$Id$") + +class One { + + static bool released; + + int m2; + int ref; + +public: + One (int refcount): ref(refcount) + { + released = false; + } + + ~One () + { + released = true; + } + + bool has_refs (int howmany) + { + return this->ref == howmany; + } + + static bool was_released (void) + { + return released; + } + + static void intrusive_add_ref (One *); + static void intrusive_remove_ref (One *); +}; + +bool One::released = true; + +void +One::intrusive_add_ref (One *one) { + one->ref++; +} + +void +One::intrusive_remove_ref (One *one) { + one->ref--; + if (one->ref == 0) + delete one; +} + + + +int run_main (int argc, ACE_TCHAR *argv[]) +{ + ACE_START_TEST (ACE_TEXT ("Intrusive_Auto_Ptr_Test")); + + + One *theone (new One(0)); + + { + ACE_ASSERT (theone->has_refs (0)); + ACE_ASSERT (!One::was_released ()); + + ACE_Intrusive_Auto_Ptr<One> ip2(theone); + + { + ACE_ASSERT (theone->has_refs (1)); + ACE_ASSERT (!One::was_released ()); + + ACE_Intrusive_Auto_Ptr<One> ip2(theone); + ACE_ASSERT (theone->has_refs (2)); + ACE_ASSERT (!One::was_released ()); + } + + ACE_ASSERT (theone->has_refs (1)); + ACE_ASSERT (!One::was_released ()); + } + + ACE_ASSERT (One::was_released()); + + ACE_END_TEST; + return 0; +} diff --git a/ACE/tests/Object_Manager_Flipping_Test.cpp b/ACE/tests/Object_Manager_Flipping_Test.cpp index e2dc4349d39..e731f92cd4d 100644 --- a/ACE/tests/Object_Manager_Flipping_Test.cpp +++ b/ACE/tests/Object_Manager_Flipping_Test.cpp @@ -54,9 +54,8 @@ int run_main (int, ACE_TCHAR *[]) // Causing the creation of a SC instance and the corresponding TSS // key. It is not registered with the Object Manager, but beware - // OM finalization will destroy it too. - ACE_Service_Gestalt *p0 = ACE_Service_Config::instance (); - - ACE_Service_Gestalt *p1 = 0; + ACE_Intrusive_Auto_Ptr<ACE_Service_Gestalt> p0 (ACE_Service_Config::instance ()); + ACE_Intrusive_Auto_Ptr<ACE_Service_Gestalt> p1; u_int errors = 0; // ... @@ -94,14 +93,12 @@ int run_main (int, ACE_TCHAR *[]) ACE::fini (); } - p1 = ACE_Service_Config::instance (); - // This is a legitimate test, but more importantly an // attemp to dereference p1 should succeed. If SC's TSS // was not cleaned correctly this will SEGV. As will the // following ACE::init, as it tries to use the SC instance. - if (p1->is_opened ()) + if (ACE_Service_Config::instance ()->is_opened ()) ++errors; // Not using ACE_ASSERT because ACE is not initialized yet. @@ -110,7 +107,7 @@ int run_main (int, ACE_TCHAR *[]) ACE::init(); ACE_START_TEST (ACE_TEXT ("Object_Manager_Flipping_Test")); - ACE_Service_Gestalt *p2 = ACE_Service_Config::instance (); + ACE_Service_Gestalt_Auto_Ptr p2 (ACE_Service_Config::instance ()); // ACE_ASSERT uses Log_Msg::instance() and needs to be done only // after ACE_START_TEST diff --git a/ACE/tests/tests.mpc b/ACE/tests/tests.mpc index b34f1987a54..a188089907a 100644 --- a/ACE/tests/tests.mpc +++ b/ACE/tests/tests.mpc @@ -487,6 +487,13 @@ project(Integer_Truncate Test) : acetest { } } +project(Intrusive Auto Ptr Test) : acetest { + exename = Intrusive_Auto_Ptr_Test + Source_Files { + Intrusive_Auto_Ptr_Test.cpp + } +} + project(IOStream Test) : acetest { exename = IOStream_Test Source_Files { |