65 RCPNodeInfo() : nodePtr(0) {}
67 : info(info_in), nodePtr(nodePtr_in)
74 typedef std::pair<const void*, RCPNodeInfo> VoidPtrNodeRCPInfoPair_t;
77 typedef std::multimap<const void*, RCPNodeInfo> rcp_node_list_t;
80 class RCPNodeInfoListPred {
82 bool operator()(
const rcp_node_list_t::value_type &v1,
83 const rcp_node_list_t::value_type &v2
87 return v1.second.nodePtr->insertion_number() < v2.second.nodePtr->insertion_number();
89 return v1.first < v2.first;
112 rcp_node_list_t*& rcp_node_list()
114 static rcp_node_list_t *s_rcp_node_list = 0;
122 return s_rcp_node_list;
126 bool& loc_isTracingActiveRCPNodes()
128 static bool s_loc_isTracingActiveRCPNodes =
129 #if defined(TEUCHOS_DEBUG) && defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 135 return s_loc_isTracingActiveRCPNodes;
142 return s_loc_rcpNodeStatistics;
146 bool& loc_printRCPNodeStatisticsOnExit()
148 static bool s_loc_printRCPNodeStatisticsOnExit =
false;
149 return s_loc_printRCPNodeStatisticsOnExit;
153 bool& loc_printActiveRcpNodesOnExit()
155 static bool s_loc_printActiveRcpNodesOnExit =
true;
156 return s_loc_printActiveRcpNodesOnExit;
175 const void* base_obj_map_key_void_ptr = rcp_node->get_base_obj_map_key_void_ptr();
176 if (base_obj_map_key_void_ptr)
177 return base_obj_map_key_void_ptr;
185 std::ostringstream oss;
187 <<
"RCPNode {address=" 190 <<
", base_obj_map_key_void_ptr=" << rcp_node->get_base_obj_map_key_void_ptr()
193 <<
", map_key_void_ptr=" << get_map_key_void_ptr(rcp_node)
196 <<
", insertionNumber="<< rcp_node->insertion_number()
215 const any &extra_data,
const std::string& name
223 const std::string type_and_name( extra_data.
typeName() + std::string(
":") + name );
228 ,
"Error, the type:name pair \'" << type_and_name
229 <<
"\' already exists and force_unique==true!" );
237 (*extra_data_map_)[type_and_name] =
248 ,
"Error, no extra data has been set yet!" );
253 const std::string type_and_name( type_name + std::string(
":") + name );
255 extra_data == NULL, std::invalid_argument
256 ,
"Error, the type:name pair \'" << type_and_name <<
"\' is not found!" );
264 const std::string& name )
267 const std::string type_and_name( type_name + std::string(
":") + name );
270 return &(*itr).second.extra_data;
283 extra_data_map_t::value_type &entry = *itr;
285 entry.second.extra_data =
any();
300 return loc_isTracingActiveRCPNodes();
304 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 305 void RCPNodeTracer::setTracingActiveRCPNodes(
bool tracingActiveNodes)
307 loc_isTracingActiveRCPNodes() = tracingActiveNodes;
316 return rcp_node_list()->size();
324 return loc_rcpNodeStatistics();
332 <<
"\n*** RCPNode Tracing statistics:" 342 bool printRCPNodeStatisticsOnExit)
344 loc_printRCPNodeStatisticsOnExit() = printRCPNodeStatisticsOnExit;
350 return loc_printRCPNodeStatisticsOnExit();
356 loc_printActiveRcpNodesOnExit() = printActiveRcpNodesOnExit;
362 return loc_printActiveRcpNodesOnExit();
368 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE 370 <<
"\nCalled printActiveRCPNodes() :" 371 <<
" rcp_node_list.size() = " << rcp_node_list().size() <<
"\n";
372 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE 373 if (loc_isTracingActiveRCPNodes()) {
375 if (rcp_node_list()->size() > 0) {
381 typedef std::vector<VoidPtrNodeRCPInfoPair_t> rcp_node_vec_t;
382 rcp_node_vec_t rcp_node_vec(rcp_node_list()->begin(), rcp_node_list()->end());
383 std::sort(rcp_node_vec.begin(), rcp_node_vec.end(), RCPNodeInfoListPred());
385 typedef rcp_node_vec_t::const_iterator itr_t;
387 for ( itr_t itr = rcp_node_vec.begin(); itr != rcp_node_vec.end(); ++itr ) {
388 const rcp_node_list_t::value_type &entry = *itr;
392 << std::setw(3) << std::right << i << std::left
393 <<
": RCPNode (map_key_void_ptr=" << entry.first <<
")\n" 394 <<
" Information = " << entry.second.info <<
"\n" 395 <<
" RCPNode address = " << entry.second.nodePtr <<
"\n" 397 <<
" insertionNumber = " << entry.second.nodePtr->insertion_number()
416 static int insertionNumber = 0;
421 rcp_node->set_insertion_number(insertionNumber);
424 if (loc_isTracingActiveRCPNodes()) {
428 #ifdef RCP_NODE_DEBUG_TRACE_PRINT 430 <<
"RCPNodeTracer::addNewRCPNode(...): Adding " 431 << convertRCPNodeToString(rcp_node) <<
" ...\n";
436 const void *
const map_key_void_ptr = get_map_key_void_ptr(rcp_node);
439 typedef rcp_node_list_t::iterator itr_t;
440 typedef std::pair<itr_t, itr_t> itr_itr_t;
441 const itr_itr_t itr_itr = rcp_node_list()->equal_range(map_key_void_ptr);
442 const bool rcp_node_already_exists = itr_itr.first != itr_itr.second;
443 RCPNode *previous_rcp_node = 0;
444 bool previous_rcp_node_has_ownership =
false;
445 for (itr_t itr = itr_itr.first; itr != itr_itr.second; ++itr) {
446 previous_rcp_node = itr->second.nodePtr;
448 previous_rcp_node_has_ownership =
true;
453 rcp_node_already_exists && rcp_node->
has_ownership() && previous_rcp_node_has_ownership,
455 "RCPNodeTracer::addNewRCPNode(rcp_node): Error, the client is trying to create a new\n" 456 "RCPNode object to an existing managed object in another RCPNode:\n" 458 " New " << convertRCPNodeToString(rcp_node) <<
"\n" 460 " Existing " << convertRCPNodeToString(previous_rcp_node) <<
"\n" 462 " Number current nodes = " << rcp_node_list()->size() <<
"\n" 464 "This may indicate that the user might be trying to create a weak RCP to an existing\n" 465 "object but forgot make it non-ownning. Perhaps they meant to use rcpFromRef(...)\n" 466 "or an equivalent function?\n" 477 (*rcp_node_list()).
insert(
479 std::make_pair(map_key_void_ptr, RCPNodeInfo(info, rcp_node))
488 ++loc_rcpNodeStatistics().totalNumRCPNodeAllocations;
489 loc_rcpNodeStatistics().maxNumRCPNodes =
495 #define TEUCHOS_RCPNODE_REMOVE_RCPNODE(CONDITION, RCPNODE) \ 496 TEUCHOS_TEST_FOR_EXCEPTION((CONDITION), \ 498 "RCPNodeTracer::removeRCPNode(node_ptr): Error, the " \ 499 << convertRCPNodeToString(RCPNODE) << " is not found in the list of" \ 500 " active RCP nodes being traced even though all nodes should be traced." \ 501 " This should not be possible and can only be an internal programming error!") 517 typedef rcp_node_list_t::iterator itr_t;
518 typedef std::pair<itr_t, itr_t> itr_itr_t;
520 const itr_itr_t itr_itr =
521 rcp_node_list()->equal_range(get_map_key_void_ptr(rcp_node));
522 const bool rcp_node_exists = itr_itr.first != itr_itr.second;
524 #ifdef HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING 537 if (rcp_node_exists) {
538 #ifdef RCP_NODE_DEBUG_TRACE_PRINT 540 <<
"RCPNodeTracer::removeRCPNode(...): Removing " 541 << convertRCPNodeToString(rcp_node) <<
" ...\n";
543 bool foundRCPNode =
false;
544 for(itr_t itr = itr_itr.first; itr != itr_itr.second; ++itr) {
545 if (itr->second.nodePtr == rcp_node) {
546 rcp_node_list()->erase(itr);
547 ++loc_rcpNodeStatistics().totalNumRCPNodeDeletions;
561 typedef rcp_node_list_t::iterator itr_t;
562 typedef std::pair<itr_t, itr_t> itr_itr_t;
565 const itr_itr_t itr_itr = rcp_node_list()->equal_range(p);
566 for (itr_t itr = itr_itr.first; itr != itr_itr.second; ++itr) {
567 RCPNode* rcpNode = itr->second.nodePtr;
582 "\n*** Warning! The following Teuchos::RCPNode objects were created but have" 583 "\n*** not been destroyed yet. A memory checking tool may complain that these" 584 "\n*** objects are not destroyed correctly." 586 "\n*** There can be many possible reasons that this might occur including:" 588 "\n*** a) The program called abort() or exit() before main() was finished." 589 "\n*** All of the objects that would have been freed through destructors" 590 "\n*** are not freed but some compilers (e.g. GCC) will still call the" 591 "\n*** destructors on static objects (which is what causes this message" 592 "\n*** to be printed)." 594 "\n*** b) The program is using raw new/delete to manage some objects and" 595 "\n*** delete was not called correctly and the objects not deleted hold" 596 "\n*** other objects through reference-counted pointers." 598 "\n*** c) This may be an indication that these objects may be involved in" 599 "\n*** a circular dependency of reference-counted managed objects." 608 "NOTE: To debug issues, open a debugger, and set a break point in the function where\n" 609 "the RCPNode object is first created to determine the context where the object first\n" 610 "gets created. Each RCPNode object is given a unique insertionNumber to allow setting\n" 611 "breakpoints in the code. For example, in GDB one can perform:\n" 613 "1) Open the debugger (GDB) and run the program again to get updated object addresses\n" 615 "2) Set a breakpoint in the RCPNode insertion routine when the desired RCPNode is first\n" 616 "inserted. In GDB, to break when the RCPNode with insertionNumber==3 is added, do:\n" 618 " (gdb) b 'Teuchos::RCPNodeTracer::addNewRCPNode( [TAB] ' [ENTER]\n" 619 " (gdb) cond 1 insertionNumber==3 [ENTER]\n" 621 "3) Run the program in the debugger. In GDB, do:\n" 623 " (gdb) run [ENTER]\n" 625 "4) Examine the call stack when the program breaks in the function addNewRCPNode(...)\n" 637 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE 638 std::cerr <<
"\nCalled ActiveRCPNodesSetup::ActiveRCPNodesSetup() : count = " <<
count_ <<
"\n";
639 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE 640 if (!rcp_node_list())
641 rcp_node_list() =
new rcp_node_list_t;
648 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE 649 std::cerr <<
"\nCalled ActiveRCPNodesSetup::~ActiveRCPNodesSetup() : count = " <<
count_ <<
"\n";
650 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE 652 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE 653 std::cerr <<
"\nPrint active nodes!\n";
654 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE 655 std::cout << std::flush;
667 delete rcp_node_list();
706 local_activeRCPNodesSetup.foo();
736 void Teuchos::throw_null_ptr_error(
const std::string &type_name )
739 true, NullReferenceError,
740 type_name <<
" : You can not call operator->() or operator*()" 741 <<
" if getRawPtr()==0!" );
static void printRCPNodeStatistics(const RCPNodeStatistics &rcpNodeStatistics, std::ostream &out)
Print the RCPNode allocation statistics.
void impl_pre_delete_extra_data()
static bool isTracingActiveRCPNodes()
Return if we are tracing active nodes or not.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
int deincr_count(const ERCPStrength strength)
static void setPrintRCPNodeStatisticsOnExit(bool printRCPNodeStatisticsOnExit)
Set if RCPNode usage statistics will be printed when the program ends or not.
void set_extra_data(const any &extra_data, const std::string &name, EPrePostDestruction destroy_when, bool force_unique)
static RCPNodeStatistics getRCPNodeStatistics()
Return the statistics on RCPNode allocations.
Modified boost::any class, which is a container for a templated value.
long int totalNumRCPNodeAllocations
any & get_extra_data(const std::string &type_name, const std::string &name)
void has_ownership(bool has_ownership_in)
static std::string getCommonDebugNotesString()
Common error message string on how to debug RCPNode problems.
static bool getPrintRCPNodeStatisticsOnExit()
Return if RCPNode usage statistics will be printed when the program ends or not.
Node class to keep track of address and the reference count for a reference-counted utility class and...
static RCPNode * getExistingRCPNodeGivenLookupKey(const void *lookupKey)
Return a raw pointer to an existing owning RCPNode given its lookup key.
static bool getPrintActiveRcpNodesOnExit()
Return if printActiveRCPNodes() is called on exit from the program.
#define TEUCHOS_MAX(x, y)
virtual const std::string get_base_obj_type_name() const =0
ERCPStrength strength() const
The strength of this handle.
#define TEUCHOS_RCPNODE_REMOVE_RCPNODE(CONDITION, RCPNODE)
EPrePostDestruction
Used to specify a pre or post destruction of extra data.
virtual void delete_obj()=0
dependentList insert(myDepList.getEntryRCP(dependent1))
std::string typeName() const
Return the name of the type.
any * get_optional_extra_data(const std::string &type_name, const std::string &name)
static void removeRCPNode(RCPNode *rcp_node)
Remove an RCPNode from global list.
extra_data_map_t * extra_data_map_
#define TEUCHOS_ASSERT(assertion_test)
This macro is throws when an assert fails.
Teuchos::map< std::string, extra_data_entry_t > extra_data_map_t
long int totalNumRCPNodeDeletions
Reference-counted pointer node classes.
Thrown if a duplicate owning RCP is creatd the the same object.
static std::string getActiveRCPNodeHeaderString()
Header string used in printActiveRCPNodes().
static int numActiveRCPNodes()
Print the number of active RCPNode objects currently being tracked.
static void addNewRCPNode(RCPNode *rcp_node, const std::string &info)
Add new RCPNode to the global list.
#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...
static void printActiveRCPNodes(std::ostream &out)
Print the list of currently active RCP nodes.
static void setPrintActiveRcpNodesOnExit(bool printActiveRcpNodesOnExit)
Set if printActiveRCPNodes() is called on exit from the program.