summaryrefslogtreecommitdiff
path: root/TAO/orbsvcs/orbsvcs/Notify/Refcountable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/orbsvcs/orbsvcs/Notify/Refcountable.cpp')
-rw-r--r--TAO/orbsvcs/orbsvcs/Notify/Refcountable.cpp252
1 files changed, 252 insertions, 0 deletions
diff --git a/TAO/orbsvcs/orbsvcs/Notify/Refcountable.cpp b/TAO/orbsvcs/orbsvcs/Notify/Refcountable.cpp
new file mode 100644
index 00000000000..0d06a3c0e05
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/Notify/Refcountable.cpp
@@ -0,0 +1,252 @@
+// $Id$
+
+#include "orbsvcs/Notify/Refcountable.h"
+#include "tao/debug.h"
+#include "ace/Log_Msg.h"
+
+#include "ace/Guard_T.h"
+
+ACE_RCSID(Notify, TAO_Notify_Refcountable, "$Id$")
+
+#if ( TAO_NOTIFY_REFCOUNT_DIAGNOSTICS != 0 )
+
+#include <map>
+#include <string>
+#include <typeinfo.h>
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class TAO_Notify_Tracker
+ *
+ * @brief A debugging tool to track the creation of TAO_Notify_Refcountable objects.
+ *
+ * Usage:
+ * Set USE_TAO_NOTIFY_TRACKER defined above to 1
+ * At any significant point to check object usage
+ * TAO_Notify_Tracker::get_instance().dump();
+ */
+class TAO_Notify_Tracker
+{
+public:
+ struct Entry
+ {
+ TAO_Notify_Refcountable* obj;
+ std::string class_name;
+ };
+
+ static TAO_Notify_Tracker& get_instance();
+
+ void add( TAO_Notify_Refcountable* p );
+
+ void remove( const TAO_Notify_Refcountable* p );
+
+ Entry find( const TAO_Notify_Refcountable* p ) const;
+
+ void dump( const char* title = 0 );
+
+private:
+ TAO_Notify_Tracker();
+ ~TAO_Notify_Tracker();
+
+ friend class std::auto_ptr< TAO_Notify_Tracker >;
+ static std::auto_ptr< TAO_Notify_Tracker > s_instance;
+ mutable TAO_SYNCH_MUTEX lock_;
+ typedef std::map<int, Entry> EntityMap;
+ EntityMap map_;
+ int id_counter_;
+ int last_dump_count_;
+};
+
+void
+TAO_Notify_Refcountable::diagnostic_dump( const char* title )
+{
+ TAO_Notify_Tracker::get_instance().dump( title );
+}
+
+#endif /* TAO_NOTIFY_REFCOUNT_DIAGNOSTICS */
+
+
+TAO_Notify_Refcountable::TAO_Notify_Refcountable (void)
+{
+}
+
+TAO_Notify_Refcountable::~TAO_Notify_Refcountable ()
+{
+#if ( TAO_NOTIFY_REFCOUNT_DIAGNOSTICS != 0 )
+ TAO_Notify_Tracker::Entry e = TAO_Notify_Tracker::get_instance().find( this );
+ if ( e.obj != 0 )
+ {
+ ACE_DEBUG ((LM_DEBUG,"object:%x %s(%d) with refcount:%d destroyed incorrectly.\n",
+ e.obj, e.class_name, e.obj->ref_id_, e.obj->refcount_.value() ));
+
+ if ( e.obj != this || e.obj->ref_id_ != this->ref_id_ )
+ {
+ ACE_DEBUG ((LM_DEBUG, " with an ID mismatch %x->%d != %x->%d!\n",
+ this, ref_id_, e.obj, e.obj->ref_id_));
+ }
+ TAO_Notify_Tracker::get_instance().remove( this );
+ }
+#endif
+ CORBA::ULong refcount = this->refcount_.value();
+ ACE_ASSERT( refcount == 0 );
+ ACE_UNUSED_ARG(refcount);
+}
+
+
+CORBA::ULong
+TAO_Notify_Refcountable::_incr_refcnt (void)
+{
+ CORBA::Long refcount = ++this->refcount_;
+ if (TAO_debug_level > 1 )
+ {
+ ACE_DEBUG ((LM_DEBUG,"object:%x incr refcount = %d\n", this, refcount ));
+ }
+#if ( TAO_NOTIFY_REFCOUNT_DIAGNOSTICS != 0 )
+ // Stack-instantiated-non-servants should never have _incr_refcnt called.
+ // We do not care about stack-instances. Stack-instantiated servants break
+ // the tracker.
+ if ( refcount == 1 )
+ {
+ TAO_Notify_Tracker::get_instance().add( this );
+ }
+#endif
+ return refcount;
+}
+
+CORBA::ULong
+TAO_Notify_Refcountable::_decr_refcnt (void)
+{
+ CORBA::Long refcount = --this->refcount_;
+
+ if (TAO_debug_level > 1 )
+ {
+ ACE_DEBUG ((LM_DEBUG,"object:%x decr refcount = %d\n", this, refcount ));
+ }
+
+ ACE_ASSERT(refcount >= 0);
+
+ if (refcount == 0)
+ {
+ #if ( USE_TAO_NOTIFY_TRACKER != 0 )
+ TAO_Notify_Tracker::get_instance().remove( this );
+ #endif
+ this->release ();
+ }
+ return refcount;
+}
+
+#if ( TAO_NOTIFY_REFCOUNT_DIAGNOSTICS != 0 )
+
+std::auto_ptr< TAO_Notify_Tracker > TAO_Notify_Tracker::s_instance;
+
+TAO_Notify_Tracker::TAO_Notify_Tracker()
+: id_counter_(0)
+, last_dump_count_(0)
+{
+}
+
+
+TAO_Notify_Tracker::~TAO_Notify_Tracker()
+{
+ dump( "destruction" );
+}
+
+
+void
+TAO_Notify_Tracker::dump( const char* title )
+{
+ ACE_Guard<TAO_SYNCH_MUTEX> grd(this->lock_);
+
+ ACE_DEBUG ((LM_DEBUG,"\nTAO_Notify_Tracker: %s\n", (title ? title : "dump")));
+
+ EntityMap::const_iterator iter( map_.begin() );
+ while ( iter != map_.end() )
+ {
+ ACE_DEBUG ((LM_DEBUG,"object:%x %s(%d) with refcount:%d.\n",
+ iter->second.obj, iter->second.class_name, iter->first, iter->second.obj->refcount_.value() ));
+ iter++;
+ }
+
+ EntityMap::size_type current_count = map_.size();
+ int diff = ( current_count - last_dump_count_ );
+ ACE_DEBUG ((LM_DEBUG,"Count: %u\nDifference: %+d\n", current_count, diff ));
+ last_dump_count_ = current_count;
+}
+
+
+TAO_Notify_Tracker&
+TAO_Notify_Tracker::get_instance()
+{
+ if ( s_instance.get() == 0 )
+ {
+ s_instance.reset( new TAO_Notify_Tracker );
+ }
+ return *s_instance;
+}
+
+
+void
+TAO_Notify_Tracker::add( TAO_Notify_Refcountable* p )
+{
+ if ( p == 0 ) return;
+
+ ACE_Guard<TAO_SYNCH_MUTEX> grd(this->lock_);
+ int id = ++id_counter_;
+
+ Entry e = { p, typeid(*p).name() };
+ std::pair< EntityMap::iterator, bool > result =
+ map_.insert( std::make_pair( id, e ) );
+ EntityMap::iterator& it = result.first;
+ if ( result.second == false )
+ {
+ ACE_DEBUG ((LM_DEBUG,"object:%x %s(%d) added twice.\n",
+ it->second.obj, it->second.class_name.c_str(), it->first ));
+ }
+ else
+ {
+ p->ref_id_ = id;
+ }
+}
+
+
+void
+TAO_Notify_Tracker::remove( const TAO_Notify_Refcountable* p )
+{
+ if ( p == 0 ) return;
+
+ ACE_Guard<TAO_SYNCH_MUTEX> grd(this->lock_);
+ int ref_id = p->ref_id_;
+ EntityMap::iterator iter( map_.find( ref_id ) );
+ if ( iter == map_.end() )
+ {
+ const char* class_name = typeid(*iter->second.obj).name();
+ ACE_DEBUG ((LM_DEBUG,"object:%x %s(%d) not found.\n",
+ p, class_name, ref_id ));
+ }
+ else
+ {
+ map_.erase( iter );
+ }
+}
+
+
+TAO_Notify_Tracker::Entry
+TAO_Notify_Tracker::find( const TAO_Notify_Refcountable* p ) const
+{
+ Entry e = { 0, "" };
+ if ( p == 0 ) return e;
+
+ ACE_Guard<TAO_SYNCH_MUTEX> grd(this->lock_);
+ int ref_id = p->ref_id_;
+ EntityMap::const_iterator iter( map_.find( ref_id ) );
+ if ( iter != map_.end() )
+ {
+ return iter->second;
+ }
+ return e;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* TAO_NOTIFY_REFCOUNT_DIAGNOSTICS */