summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriliyan <iliyan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2007-12-16 21:25:31 +0000
committeriliyan <iliyan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2007-12-16 21:25:31 +0000
commit6ece019eb2e50991446d80f5e4f0639291fb3007 (patch)
tree4bce73c64877e8cf2a696fc7c6f16b1fbfd640e6
parent2b88b9c32377192ecc2f56fbaac2800e45b1fc42 (diff)
downloadATCD-6ece019eb2e50991446d80f5e4f0639291fb3007.tar.gz
ChangeLogTag: Sun Dec 16 20:48:39 UTC 2007 Iliyan Jeliazkov <iliyan@ociweb.com>
-rw-r--r--ACE/ChangeLog.iliyan-gestalt42
-rw-r--r--ACE/ace/Dynamic_Service.cpp4
-rw-r--r--ACE/ace/Dynamic_Service.h8
-rw-r--r--ACE/ace/Dynamic_Service.inl4
-rw-r--r--ACE/ace/Dynamic_Service_Base.cpp6
-rw-r--r--ACE/ace/Dynamic_Service_Base.h5
-rw-r--r--ACE/ace/Dynamic_Service_Dependency.cpp2
-rw-r--r--ACE/ace/Intrusive_Auto_Ptr.cpp19
-rw-r--r--ACE/ace/Intrusive_Auto_Ptr.h160
-rw-r--r--ACE/ace/Intrusive_Auto_Ptr.inl149
-rw-r--r--ACE/ace/Refcounted_Auto_Ptr.h23
-rw-r--r--ACE/ace/Refcounted_Auto_Ptr.inl21
-rw-r--r--ACE/ace/Service_Config.cpp171
-rw-r--r--ACE/ace/Service_Config.h71
-rw-r--r--ACE/ace/Service_Config.inl50
-rw-r--r--ACE/ace/Service_Gestalt.cpp38
-rw-r--r--ACE/ace/Service_Gestalt.h17
-rw-r--r--ACE/ace/Thread_Adapter.cpp5
-rw-r--r--ACE/ace/ace.mpc4
-rw-r--r--ACE/tests/Intrusive_Auto_Ptr_Test.cpp104
-rw-r--r--ACE/tests/Object_Manager_Flipping_Test.cpp11
-rw-r--r--ACE/tests/tests.mpc7
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 {