Refcountable.cpp

Go to the documentation of this file.
00001 // Refcountable.cpp,v 1.15 2006/03/14 06:14:34 jtc Exp
00002 
00003 #include "orbsvcs/Notify/Refcountable.h"
00004 #include "tao/debug.h"
00005 #include "ace/Log_Msg.h"
00006 
00007 #include "ace/Guard_T.h"
00008 
00009 ACE_RCSID(Notify, TAO_Notify_Refcountable, "Refcountable.cpp,v 1.15 2006/03/14 06:14:34 jtc Exp")
00010 
00011 #if ( TAO_NOTIFY_REFCOUNT_DIAGNOSTICS != 0 )
00012 
00013 #include <map>
00014 #include <string>
00015 #include <typeinfo.h>
00016 
00017 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00018 
00019 /**
00020  * @class TAO_Notify_Tracker
00021  *
00022  * @brief A debugging tool to track the creation of TAO_Notify_Refcountable objects.
00023  *
00024  *        Usage:
00025  *        Set USE_TAO_NOTIFY_TRACKER defined above to 1
00026  *        At any significant point to check object usage
00027  *          TAO_Notify_Tracker::get_instance().dump();
00028  */
00029 class TAO_Notify_Tracker
00030 {
00031 public:
00032   struct Entry
00033   {
00034     TAO_Notify_Refcountable*  obj;
00035     std::string               class_name;
00036   };
00037 
00038   static TAO_Notify_Tracker& get_instance();
00039 
00040   void add( TAO_Notify_Refcountable* p );
00041 
00042   void remove( const TAO_Notify_Refcountable* p );
00043 
00044   Entry find( const TAO_Notify_Refcountable* p ) const;
00045 
00046   void dump( const char* title = 0 );
00047 
00048 private:
00049   TAO_Notify_Tracker();
00050   ~TAO_Notify_Tracker();
00051 
00052   friend class std::auto_ptr< TAO_Notify_Tracker >;
00053   static std::auto_ptr< TAO_Notify_Tracker > s_instance;
00054   mutable TAO_SYNCH_MUTEX lock_;
00055   typedef std::map<int, Entry> EntityMap;
00056   EntityMap map_;
00057   int id_counter_;
00058   int last_dump_count_;
00059 };
00060 
00061 void
00062 TAO_Notify_Refcountable::diagnostic_dump( const char* title )
00063 {
00064   TAO_Notify_Tracker::get_instance().dump( title );
00065 }
00066 
00067 #endif /* TAO_NOTIFY_REFCOUNT_DIAGNOSTICS */
00068 
00069 
00070 TAO_Notify_Refcountable::TAO_Notify_Refcountable (void)
00071 {
00072 }
00073 
00074 TAO_Notify_Refcountable::~TAO_Notify_Refcountable ()
00075 {
00076 #if ( TAO_NOTIFY_REFCOUNT_DIAGNOSTICS != 0 )
00077   TAO_Notify_Tracker::Entry e = TAO_Notify_Tracker::get_instance().find( this );
00078   if ( e.obj != 0 )
00079   {
00080     ACE_DEBUG ((LM_DEBUG,"object:%x %s(%d) with refcount:%d destroyed incorrectly.\n",
00081         e.obj, e.class_name, e.obj->ref_id_, e.obj->refcount_.value() ));
00082  
00083     if ( e.obj != this || e.obj->ref_id_ != this->ref_id_ )
00084     {
00085       ACE_DEBUG ((LM_DEBUG, "  with an ID mismatch %x->%d != %x->%d!\n",
00086         this, ref_id_, e.obj, e.obj->ref_id_));
00087     }
00088     TAO_Notify_Tracker::get_instance().remove( this );
00089   }
00090 #endif
00091   CORBA::ULong refcount = this->refcount_.value();
00092   ACE_ASSERT( refcount == 0 );
00093   ACE_UNUSED_ARG(refcount);
00094 }
00095 
00096 
00097 CORBA::ULong
00098 TAO_Notify_Refcountable::_incr_refcnt (void)
00099 {
00100   CORBA::Long refcount = ++this->refcount_;
00101   if (TAO_debug_level > 1 )
00102   {
00103     ACE_DEBUG ((LM_DEBUG,"object:%x incr refcount = %d\n", this, refcount ));
00104   }
00105 #if ( TAO_NOTIFY_REFCOUNT_DIAGNOSTICS != 0 )
00106   // Stack-instantiated-non-servants should never have _incr_refcnt called.
00107   // We do not care about stack-instances. Stack-instantiated servants break
00108   // the tracker.
00109   if ( refcount == 1 )
00110   {
00111     TAO_Notify_Tracker::get_instance().add( this );
00112   }
00113 #endif
00114   return refcount;
00115 }
00116 
00117 CORBA::ULong
00118 TAO_Notify_Refcountable::_decr_refcnt (void)
00119 {
00120   CORBA::Long refcount = --this->refcount_;
00121 
00122   if (TAO_debug_level > 1 )
00123   {
00124     ACE_DEBUG ((LM_DEBUG,"object:%x decr refcount = %d\n", this, refcount ));
00125   }
00126 
00127   ACE_ASSERT(refcount >= 0);
00128 
00129   if (refcount == 0)
00130   {
00131     #if ( USE_TAO_NOTIFY_TRACKER != 0 )
00132       TAO_Notify_Tracker::get_instance().remove( this );
00133     #endif
00134     this->release ();
00135   }
00136   return refcount;
00137 }
00138 
00139 #if ( TAO_NOTIFY_REFCOUNT_DIAGNOSTICS != 0 )
00140 
00141 std::auto_ptr< TAO_Notify_Tracker > TAO_Notify_Tracker::s_instance;
00142 
00143 TAO_Notify_Tracker::TAO_Notify_Tracker()
00144 : id_counter_(0)
00145 , last_dump_count_(0)
00146 {
00147 }
00148 
00149 
00150 TAO_Notify_Tracker::~TAO_Notify_Tracker()
00151 {
00152   dump( "destruction" );
00153 }
00154 
00155 
00156 void
00157 TAO_Notify_Tracker::dump( const char* title )
00158 {
00159   ACE_Guard<TAO_SYNCH_MUTEX> grd(this->lock_);
00160 
00161   ACE_DEBUG ((LM_DEBUG,"\nTAO_Notify_Tracker: %s\n", (title ? title : "dump")));
00162  
00163   EntityMap::const_iterator iter( map_.begin() );
00164   while ( iter != map_.end() )
00165   {
00166     ACE_DEBUG ((LM_DEBUG,"object:%x %s(%d) with refcount:%d.\n",
00167       iter->second.obj, iter->second.class_name, iter->first, iter->second.obj->refcount_.value() ));
00168     iter++;
00169   }
00170 
00171   EntityMap::size_type current_count = map_.size();
00172   int diff = ( current_count - last_dump_count_ );
00173   ACE_DEBUG ((LM_DEBUG,"Count: %u\nDifference: %+d\n", current_count, diff ));
00174   last_dump_count_ = current_count;
00175 }
00176 
00177 
00178 TAO_Notify_Tracker&
00179 TAO_Notify_Tracker::get_instance()
00180 {
00181   if ( s_instance.get() == 0 )
00182   {
00183     s_instance.reset( new TAO_Notify_Tracker );
00184   }
00185   return *s_instance;
00186 }
00187 
00188 
00189 void
00190 TAO_Notify_Tracker::add( TAO_Notify_Refcountable* p )
00191 {
00192   if ( p == 0 ) return;
00193 
00194   ACE_Guard<TAO_SYNCH_MUTEX> grd(this->lock_);
00195   int id = ++id_counter_;
00196  
00197   Entry e = { p, typeid(*p).name() };
00198   std::pair< EntityMap::iterator, bool > result =
00199     map_.insert( std::make_pair( id, e ) );
00200   EntityMap::iterator& it = result.first;
00201   if ( result.second == false )
00202   {
00203     ACE_DEBUG ((LM_DEBUG,"object:%x %s(%d) added twice.\n",
00204       it->second.obj, it->second.class_name.c_str(), it->first ));
00205   }
00206   else
00207   {
00208     p->ref_id_ = id;
00209   }
00210 }
00211 
00212 
00213 void
00214 TAO_Notify_Tracker::remove( const TAO_Notify_Refcountable* p )
00215 {
00216   if ( p == 0 ) return;
00217 
00218   ACE_Guard<TAO_SYNCH_MUTEX> grd(this->lock_);
00219   int ref_id = p->ref_id_;
00220   EntityMap::iterator iter( map_.find( ref_id ) );
00221   if ( iter == map_.end() )
00222   {
00223     const char* class_name = typeid(*iter->second.obj).name();
00224     ACE_DEBUG ((LM_DEBUG,"object:%x %s(%d) not found.\n",
00225       p, class_name, ref_id ));
00226   }
00227   else
00228   {
00229     map_.erase( iter );
00230   }
00231 }
00232 
00233 
00234 TAO_Notify_Tracker::Entry
00235 TAO_Notify_Tracker::find( const TAO_Notify_Refcountable* p ) const
00236 {
00237   Entry e = { 0, "" };
00238   if ( p == 0 ) return e;
00239 
00240   ACE_Guard<TAO_SYNCH_MUTEX> grd(this->lock_);
00241   int ref_id = p->ref_id_;
00242   EntityMap::const_iterator iter( map_.find( ref_id ) );
00243   if ( iter != map_.end() )
00244   {
00245     return iter->second;
00246   }
00247   return e;
00248 }
00249 
00250 TAO_END_VERSIONED_NAMESPACE_DECL
00251 
00252 #endif /* TAO_NOTIFY_REFCOUNT_DIAGNOSTICS */

Generated on Thu Nov 9 13:24:15 2006 for TAO_CosNotification by doxygen 1.3.6