11#include "Teuchos_Assert.hpp" 
   12#include "Teuchos_Exceptions.hpp" 
   16#include "Teuchos_StandardCatchMacros.hpp" 
   27#if defined(TEUCHOS_DEBUG) && defined(HAVE_TEUCHOSCORE_CXX11) && defined(HAVE_TEUCHOS_THREAD_SAFE) 
   29#define USE_MUTEX_TO_PROTECT_NODE_TRACING 
   41  RCPNodeInfo() = 
delete;
 
   43    : info(info_in), nodePtr(nodePtr_in)
 
   50typedef std::pair<const void*, RCPNodeInfo> VoidPtrNodeRCPInfoPair_t;
 
   53typedef std::multimap<const void*, RCPNodeInfo> rcp_node_list_t;
 
   72rcp_node_list_t*& rcp_node_list()
 
   74  static rcp_node_list_t *s_rcp_node_list = 0;
 
   82  return s_rcp_node_list;
 
   85#ifdef USE_MUTEX_TO_PROTECT_NODE_TRACING 
   86std::mutex *& rcp_node_list_mutex()
 
   88  static std::mutex * s_rcp_node_list_mutex = 0;
 
   91  return s_rcp_node_list_mutex;
 
   95bool& loc_isTracingActiveRCPNodes()
 
   97  static bool s_loc_isTracingActiveRCPNodes =
 
   98#if defined(TEUCHOS_DEBUG) && defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 
  104  return s_loc_isTracingActiveRCPNodes;
 
  111  return s_loc_rcpNodeStatistics;
 
  115bool& loc_printRCPNodeStatisticsOnExit()
 
  117  static bool s_loc_printRCPNodeStatisticsOnExit = 
false;
 
  118  return s_loc_printRCPNodeStatisticsOnExit;
 
  122bool& loc_printActiveRcpNodesOnExit()
 
  124  static bool s_loc_printActiveRcpNodesOnExit = 
true;
 
  125  return s_loc_printActiveRcpNodesOnExit;
 
  144  const void* base_obj_map_key_void_ptr = rcp_node->get_base_obj_map_key_void_ptr();
 
  145  if (base_obj_map_key_void_ptr)
 
  146    return base_obj_map_key_void_ptr;
 
  154  std::ostringstream oss;
 
  156    << 
"RCPNode {address=" 
  159    << 
", base_obj_map_key_void_ptr=" << rcp_node->get_base_obj_map_key_void_ptr()
 
  162    << 
", map_key_void_ptr=" << get_map_key_void_ptr(rcp_node)
 
  165    << 
", insertionNumber="<< rcp_node->insertion_number()
 
  184  const any &extra_data, 
const std::string& name
 
  190  if(extra_data_map_==
NULL) {
 
  191    extra_data_map_ = 
new extra_data_map_t;
 
  199    << 
"\' already exists and force_unique==true!" );
 
  201  if (
itr != extra_data_map_->end()) {
 
  203    itr->second = extra_data_entry_t(extra_data,destroy_when);
 
  208      extra_data_entry_t(extra_data,destroy_when);
 
 
  217    extra_data_map_==
NULL, std::invalid_argument
 
  218    ,
"Error, no extra data has been set yet!" );
 
  225      extra_data == 
NULL, std::invalid_argument
 
  226      ,
"Error, the type:name pair \'" << 
type_and_name << 
"\' is not found!" );
 
 
  234  const std::string& name )
 
  236  if( extra_data_map_ == 
NULL ) 
return NULL;
 
  239  if(
itr != extra_data_map_->end())
 
  240    return &(*itr).second.extra_data;
 
 
  245void RCPNode::impl_pre_delete_extra_data()
 
  248    extra_data_map_t::iterator 
itr = extra_data_map_->begin();
 
  249    itr != extra_data_map_->end();
 
  253    extra_data_map_t::value_type &entry = *
itr;
 
  254    if(entry.second.destroy_when == PRE_DESTROY)
 
  255      entry.second.extra_data = 
any();
 
  274#if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 
  301    << 
"\n*** RCPNode Tracing statistics:" 
  304    << 
"\n    totalNumRCPNodeAllocations = "<<
rcpNodeStatistics.totalNumRCPNodeAllocations
 
 
  337#ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE 
  339    << 
"\nCalled printActiveRCPNodes() :" 
  340    << 
" rcp_node_list.size() = " << 
rcp_node_list().size() << 
"\n";
 
  353          [] (
const rcp_node_list_t::value_type &
v1, 
const rcp_node_list_t::value_type &
v2)
 
  356            return v1.second.nodePtr->insertion_number() < v2.second.nodePtr->insertion_number();
 
  358            return v1.first < v2.first;
 
  363      typedef rcp_node_vec_t::const_iterator 
itr_t;
 
  366        const rcp_node_list_t::value_type &entry = *
itr;
 
  370          << std::setw(3) << std::right << 
i << std::left
 
  371          << 
": RCPNode (map_key_void_ptr=" << entry.first << 
")\n" 
  372          << 
"       Information = " << entry.second.info << 
"\n" 
  373          << 
"       RCPNode address = " << entry.second.nodePtr << 
"\n" 
  375          << 
"       insertionNumber = " << entry.second.nodePtr->insertion_number()
 
 
  392#ifdef USE_MUTEX_TO_PROTECT_NODE_TRACING 
  410#ifdef RCP_NODE_DEBUG_TRACE_PRINT 
  412      << 
"RCPNodeTracer::addNewRCPNode(...): Adding " 
  421    typedef rcp_node_list_t::iterator 
itr_t;
 
  422    typedef std::pair<itr_t, itr_t> 
itr_itr_t;
 
  437      "RCPNodeTracer::addNewRCPNode(rcp_node): Error, the client is trying to create a new\n" 
  438      "RCPNode object to an existing managed object in another RCPNode:\n" 
  444      "  Number current nodes = " << 
rcp_node_list()->size() << 
"\n" 
  446      "This may indicate that the user might be trying to create a weak RCP to an existing\n" 
  447      "object but forgot make it non-ownning.  Perhaps they meant to use rcpFromRef(...)\n" 
  448      "or an equivalent function?\n" 
 
  477#define TEUCHOS_RCPNODE_REMOVE_RCPNODE(CONDITION, RCPNODE) \ 
  478  TEUCHOS_TEST_FOR_EXCEPTION((CONDITION), \ 
  480    "RCPNodeTracer::removeRCPNode(node_ptr): Error, the " \ 
  481    << convertRCPNodeToString(RCPNODE) << " is not found in the list of" \ 
  482    " active RCP nodes being traced even though all nodes should be traced." \ 
  483    "  This should not be possible and can only be an internal programming error!") 
  498#ifdef USE_MUTEX_TO_PROTECT_NODE_TRACING 
  505  typedef rcp_node_list_t::iterator 
itr_t;
 
  506  typedef std::pair<itr_t, itr_t> 
itr_itr_t;
 
  512#ifdef HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING 
  526#ifdef RCP_NODE_DEBUG_TRACE_PRINT 
  528      << 
"RCPNodeTracer::removeRCPNode(...): Removing " 
 
  549  typedef rcp_node_list_t::iterator 
itr_t;
 
  550  typedef std::pair<itr_t, itr_t> 
itr_itr_t;
 
  554#ifdef USE_MUTEX_TO_PROTECT_NODE_TRACING 
 
  576    "\n*** Warning! The following Teuchos::RCPNode objects were created but have" 
  577    "\n*** not been destroyed yet.  A memory checking tool may complain that these" 
  578    "\n*** objects are not destroyed correctly." 
  580    "\n*** There can be many possible reasons that this might occur including:" 
  582    "\n***   a) The program called abort() or exit() before main() was finished." 
  583    "\n***      All of the objects that would have been freed through destructors" 
  584    "\n***      are not freed but some compilers (e.g. GCC) will still call the" 
  585    "\n***      destructors on static objects (which is what causes this message" 
  586    "\n***      to be printed)." 
  588    "\n***   b) The program is using raw new/delete to manage some objects and" 
  589    "\n***      delete was not called correctly and the objects not deleted hold" 
  590    "\n***      other objects through reference-counted pointers." 
  592    "\n***   c) This may be an indication that these objects may be involved in" 
  593    "\n***      a circular dependency of reference-counted managed objects." 
 
  602    "NOTE: To debug issues, open a debugger, and set a break point in the function where\n" 
  603    "the RCPNode object is first created to determine the context where the object first\n" 
  604    "gets created.  Each RCPNode object is given a unique insertionNumber to allow setting\n" 
  605    "breakpoints in the code.  For example, in GDB one can perform:\n" 
  607    "1) Open the debugger (GDB) and run the program again to get updated object addresses\n" 
  609    "2) Set a breakpoint in the RCPNode insertion routine when the desired RCPNode is first\n" 
  610    "inserted.  In GDB, to break when the RCPNode with insertionNumber==3 is added, do:\n" 
  612    "  (gdb) b 'Teuchos::RCPNodeTracer::addNewRCPNode( [TAB] ' [ENTER]\n" 
  613    "  (gdb) cond 1 insertionNumber==3 [ENTER]\n" 
  615    "3) Run the program in the debugger.  In GDB, do:\n" 
  617    "  (gdb) run [ENTER]\n" 
  619    "4) Examine the call stack when the program breaks in the function addNewRCPNode(...)\n" 
 
  631#ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE 
  632  std::cerr << 
"\nCalled ActiveRCPNodesSetup::ActiveRCPNodesSetup() : count = " << count_ << 
"\n";
 
  637#ifdef USE_MUTEX_TO_PROTECT_NODE_TRACING 
 
  648#ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE 
  649  std::cerr << 
"\nCalled ActiveRCPNodesSetup::~ActiveRCPNodesSetup() : count = " << count_ << 
"\n";
 
  651  if( --count_ == 0 ) {
 
  652#ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE 
  653    std::cerr << 
"\nPrint active nodes!\n";
 
  655    std::cout << std::flush;
 
  670#ifdef USE_MUTEX_TO_PROTECT_NODE_TRACING 
 
  685int Teuchos::ActiveRCPNodesSetup::count_ = 0;
 
  692void RCPNodeHandle::unbindOneStrong()
 
  702void RCPNodeHandle::unbindOneTotal()
 
  716void Teuchos::throw_null_ptr_error( 
const std::string &type_name )
 
  719    true, NullReferenceError,
 
  720    type_name << 
" : You can not call operator->() or operator*()" 
  721    <<
" if getRawPtr()==0!" );
 
  729#define TEUCHOS_IMPLEMENT_ABORT(excpt)                                         \ 
  730  bool success = false;                                                        \ 
  731  try { throw excpt; }                                                         \ 
  732  TEUCHOS_STANDARD_CATCH_STATEMENTS(true,std::cerr,success);                   \ 
  733  if(!success) std::cerr << "PROGRAM ABORTING\n";                              \ 
  734  GlobalMPISession::abort(); 
  737  TEUCHOS_IMPLEMENT_ABORT(exception);
 
  740  TEUCHOS_IMPLEMENT_ABORT(code);
 
  743  TEUCHOS_IMPLEMENT_ABORT(std::logic_error(
 
  744    "Caught unknown exception from destructor of RCPNode. Aborting."););
 
Reference-counted pointer node classes.
 
Thrown if a duplicate owning RCP is creatd the the same object.
 
static bool getPrintRCPNodeStatisticsOnExit()
Return if RCPNode usage statistics will be printed when the program ends or not.
 
static std::string getCommonDebugNotesString()
Common error message string on how to debug RCPNode problems.
 
static void printRCPNodeStatistics(const RCPNodeStatistics &rcpNodeStatistics, std::ostream &out)
Print the RCPNode allocation statistics.
 
static RCPNodeStatistics getRCPNodeStatistics()
Return the statistics on RCPNode allocations.
 
static void setPrintRCPNodeStatisticsOnExit(bool printRCPNodeStatisticsOnExit)
Set if RCPNode usage statistics will be printed when the program ends or not.
 
static int numActiveRCPNodes()
Print the number of active RCPNode objects currently being tracked.
 
static RCPNode * getExistingRCPNodeGivenLookupKey(const void *lookupKey)
Return a raw pointer to an existing owning RCPNode given its lookup key.
 
static void setPrintActiveRcpNodesOnExit(bool printActiveRcpNodesOnExit)
Set if printActiveRCPNodes() is called on exit from the program.
 
static std::string getActiveRCPNodeHeaderString()
Header string used in printActiveRCPNodes().
 
static bool isTracingActiveRCPNodes()
Return if we are tracing active nodes or not.
 
static void removeRCPNode(RCPNode *rcp_node)
Remove an RCPNode from global list.
 
static void printActiveRCPNodes(std::ostream &out)
Print the list of currently active RCP nodes.
 
static bool getPrintActiveRcpNodesOnExit()
Return if printActiveRCPNodes() is called on exit from the program.
 
static void addNewRCPNode(RCPNode *rcp_node, const std::string &info)
Add new RCPNode to the global list.
 
Node class to keep track of address and the reference count for a reference-counted utility class and...
 
any & get_extra_data(const std::string &type_name, const std::string &name)
 
virtual const std::string get_base_obj_type_name() const =0
 
virtual void delete_obj()=0
 
void set_extra_data(const any &extra_data, const std::string &name, EPrePostDestruction destroy_when, bool force_unique)
 
any * get_optional_extra_data(const std::string &type_name, const std::string &name)
 
void has_ownership(bool has_ownership_in)
 
Smart reference counting pointer class for automatic garbage collection.
 
bool has_ownership() const
Returns true if this has ownership of object pointed to by this->get() in order to delete it.
 
Modified boost::any class, which is a container for a templated value.
 
std::string typeName() const
Return the name of the type.
 
#define TEUCHOS_ASSERT(assertion_test)
This macro is throws when an assert fails.
 
#define TEUCHOS_TEST_FOR_TERMINATION(terminate_test, msg)
This macro is to be used instead of TEUCHOS_TEST_FOR_EXCEPTION() to report an error in situations whe...
 
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
This macro is designed to be a short version of TEUCHOS_TEST_FOR_EXCEPTION() that is easier to call.
 
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
 
EPrePostDestruction
Used to specify a pre or post destruction of extra data.
 
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...