42 #ifndef TEUCHOS_RCP_NODE_HPP 43 #define TEUCHOS_RCP_NODE_HPP 55 #include "Teuchos_ENull.hpp" 56 #include "Teuchos_Assert.hpp" 57 #include "Teuchos_Exceptions.hpp" 59 #include "Teuchos_toString.hpp" 60 #include "Teuchos_getBaseObjVoidPtr.hpp" 95 true, std::logic_error,
"Teuchos::RCPNode: ERCPStrength enum value " 96 << strength <<
" is invalid (neither RCP_STRONG = " << RCP_STRONG
97 <<
" nor RCP_WEAK = " << RCP_WEAK <<
").");
101 #endif // TEUCHOS_DEBUG 148 : has_ownership_(has_ownership_in), extra_data_map_(NULL)
150 ,insertion_number_(-1)
153 count_[RCP_STRONG] = 0;
154 count_[RCP_WEAK] = 0;
160 delete extra_data_map_;
165 return count_[RCP_STRONG];
170 return count_[RCP_WEAK];
176 return ++count_[strength];
182 return --count_[strength];
187 has_ownership_ = has_ownership_in;
192 return has_ownership_;
196 const any &extra_data,
const std::string& name,
199 any& get_extra_data(
const std::string& type_name,
200 const std::string& name );
203 const std::string& name
206 return const_cast<RCPNode*
>(
this)->get_extra_data(type_name, name);
209 any* get_optional_extra_data(
const std::string& type_name,
210 const std::string& name );
213 const std::string& type_name,
const std::string& name
216 return const_cast<RCPNode*
>(
this)->get_optional_extra_data(type_name, name);
219 virtual bool is_valid_ptr()
const = 0;
221 virtual void delete_obj() = 0;
223 virtual void throw_invalid_obj_exception(
224 const std::string& rcp_type_name,
227 const void* rcp_obj_ptr
230 virtual const std::string get_base_obj_type_name()
const = 0;
233 virtual const void* get_base_obj_map_key_void_ptr()
const = 0;
240 impl_pre_delete_extra_data();
243 struct extra_data_entry_t {
244 extra_data_entry_t() : destroy_when(POST_DESTROY) {}
246 : extra_data(_extra_data), destroy_when(_destroy_when)
251 typedef Teuchos::map<std::string,extra_data_entry_t> extra_data_map_t;
254 extra_data_map_t *extra_data_map_;
259 void impl_pre_delete_extra_data();
265 int insertion_number_;
267 void set_insertion_number(
int insertion_number_in)
269 insertion_number_ = insertion_number_in;
271 int insertion_number()
const 273 return insertion_number_;
275 #endif // TEUCHOS_DEBUG 283 TEUCHOSCORE_LIB_DLL_EXPORT
void throw_null_ptr_error(
const std::string &type_name );
311 : maxNumRCPNodes(0), totalNumRCPNodeAllocations(0),
312 totalNumRCPNodeDeletions(0)
314 long int maxNumRCPNodes;
315 long int totalNumRCPNodeAllocations;
316 long int totalNumRCPNodeDeletions;
329 static bool isTracingActiveRCPNodes();
331 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 349 static void setTracingActiveRCPNodes(
bool tracingActiveNodes);
355 static int numActiveRCPNodes();
361 static void printRCPNodeStatistics(
367 static void setPrintRCPNodeStatisticsOnExit(
368 bool printRCPNodeStatisticsOnExit);
373 static bool getPrintRCPNodeStatisticsOnExit();
378 static void setPrintActiveRcpNodesOnExit(
bool printActiveRcpNodesOnExit);
383 static bool getPrintActiveRcpNodesOnExit();
400 static void printActiveRCPNodes(std::ostream &out);
413 static void addNewRCPNode(
RCPNode* rcp_node,
414 const std::string &info );
421 static void removeRCPNode(
RCPNode* rcp_node );
434 #ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR 435 return getBaseObjVoidPtr(p);
442 return static_cast<const void*
>(p);
452 static RCPNode* getExistingRCPNodeGivenLookupKey(
453 const void* lookupKey);
464 return getExistingRCPNodeGivenLookupKey(getRCPNodeBaseObjMapKeyVoidPtr(p));
468 static std::string getActiveRCPNodeHeaderString();
471 static std::string getCommonDebugNotesString();
479 # define TEUCHOS_RCP_INSERION_NUMBER_STR() \ 480 " insertionNumber: " << rcp_node_ptr->insertion_number() << "\n" 482 # define TEUCHOS_RCP_INSERION_NUMBER_STR() 491 template<
class T,
class Dealloc_T>
496 :
RCPNode(has_ownership_in), ptr_(p),
498 base_obj_map_key_void_ptr_(
RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p)),
504 RCPNodeTmpl(T* p, Dealloc_T dealloc,
bool has_ownership_in, ENull)
505 :
RCPNode(has_ownership_in), ptr_(p),
507 base_obj_map_key_void_ptr_(0),
523 "Error, the underlying object must be explicitly deleted before deleting" 524 " the node object!" );
540 this->pre_delete_extra_data();
543 deleted_ptr_ = tmp_ptr;
546 if (has_ownership()) {
550 dealloc_.free(tmp_ptr);
574 const std::string& rcp_type_name,
577 const void* rcp_obj_ptr
581 const T* deleted_ptr =
590 "Error, an attempt has been made to dereference the underlying object\n" 591 "from a weak smart pointer object where the underling object has already\n" 592 "been deleted since the strong count has already gone to zero.\n" 594 "Context information:\n" 596 " RCP type: " << rcp_type_name <<
"\n" 597 " RCP address: " << rcp_ptr <<
"\n" 598 " RCPNode type: " <<
typeName(*
this) <<
"\n" 599 " RCPNode address: " << rcp_node_ptr <<
"\n" 600 TEUCHOS_RCP_INSERION_NUMBER_STR()
601 " RCP ptr address: " << rcp_obj_ptr <<
"\n" 602 " Concrete ptr address: " << deleted_ptr <<
"\n" 621 return "UnknownType";
626 const void* get_base_obj_map_key_void_ptr()
const 628 return base_obj_map_key_void_ptr_;
634 const void *base_obj_map_key_void_ptr_;
702 : node_ (0), strength_ (RCP_STRONG)
711 : node_ (node), strength_ (strength_in)
715 #endif // TEUCHOS_DEBUG 724 std::ostringstream os;
725 os <<
"{T=Unknown, ConcreteT=Unknown, p=Unknown," 726 <<
" has_ownership="<<node_->has_ownership()<<
"}";
731 #endif // TEUCHOS_DEBUG 738 const std::string &ConcreteT_name,
739 const bool has_ownership_in,
741 : node_ (node), strength_ (strength_in)
747 std::ostringstream os;
748 os <<
"{T="<<T_name<<
", ConcreteT="<< ConcreteT_name
749 <<
", p="<<
static_cast<const void*
>(p)
750 <<
", has_ownership="<<has_ownership_in<<
"}";
754 #endif // TEUCHOS_DEBUG 758 : node_ (node_ref.node_), strength_ (node_ref.strength_)
764 void swap (RCPNodeHandle& node_ref) {
765 std::swap (node_ref.node_, node_);
766 std::swap (node_ref.strength_, strength_);
774 RCPNodeHandle& operator= (
const RCPNodeHandle& node_ref) {
781 node_ = node_ref.node_;
782 strength_ = node_ref.strength_;
796 return RCPNodeHandle(node_, RCP_WEAK,
false);
798 return RCPNodeHandle();
803 return RCPNodeHandle(node_, RCP_STRONG,
false);
805 return RCPNodeHandle();
820 return node_->is_valid_ptr();
827 return node_ == node2.node_;
832 return node_->strong_count();
839 return node_->weak_count();
846 return node_->strong_count() + node_->weak_count();
853 return node_->strong_count();
865 node_->has_ownership(has_ownership_in);
871 return node_->has_ownership();
876 const any &extra_data,
const std::string& name,
880 debug_assert_not_null();
881 node_->set_extra_data(extra_data, name, destroy_when, force_unique);
885 const std::string& name
888 debug_assert_not_null();
889 return node_->get_extra_data(type_name, name);
893 const std::string& name
896 return const_cast<RCPNodeHandle*
>(
this)->get_extra_data(type_name, name);
900 const std::string& type_name,
const std::string& name
903 debug_assert_not_null();
904 return node_->get_optional_extra_data(type_name, name);
908 const std::string& type_name,
const std::string& name
911 return const_cast<RCPNodeHandle*
>(
this)->get_optional_extra_data(type_name, name);
918 throw_null_ptr_error(
typeName(*
this));
922 template<
class RCPType>
927 if (!is_valid_ptr()) {
928 node_->throw_invalid_obj_exception(
typeName(rcp_obj),
929 this, node_, rcp_obj.access_private_ptr() );
933 template<
class RCPType>
937 assert_valid_ptr(rcp_obj);
941 const void* get_base_obj_map_key_void_ptr()
const 944 return node_->get_base_obj_map_key_void_ptr();
1019 node_->has_ownership(
false);
1020 node_->delete_obj();
1047 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 1049 class SetTracingActiveNodesStack {
1051 SetTracingActiveNodesStack()
1052 {RCPNodeTracer::setTracingActiveRCPNodes(
true);}
1053 ~SetTracingActiveNodesStack()
1054 {RCPNodeTracer::setTracingActiveRCPNodes(
false);}
1057 # define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack; 1061 # define SET_RCPNODE_TRACING() (void)0 1063 #endif // defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 1069 #endif // TEUCHOS_RCP_NODE_HPP Dangling reference error exception class.
const Dealloc_T & get_dealloc() const
bool has_ownership() const
int weak_count() const
The weak count for this RCPNode, or 0 if the node is NULL.
Modified boost::any class for holding a templated value.
const any * get_optional_extra_data(const std::string &type_name, const std::string &name) const
virtual void throw_invalid_obj_exception(const std::string &rcp_type_name, const void *rcp_ptr, const RCPNode *rcp_node_ptr, const void *rcp_obj_ptr) const
static const void * getRCPNodeBaseObjMapKeyVoidPtr(T *p)
Get a const void* address to be used as the lookup key for an RCPNode given its embedded object's typ...
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.
Dealloc_T & get_nonconst_dealloc()
int deincr_count(const ERCPStrength strength)
any & get_extra_data(const std::string &type_name, const std::string &name)
Teuchos header file which uses auto-configuration information to include necessary C++ headers...
RCPNodeHandle(ENull null_arg=null)
Default constructor.
void debug_assert_valid_ptr(const RCPType &rcp_obj) const
void pre_delete_extra_data()
any * get_optional_extra_data(const std::string &type_name, const std::string &name)
void release()
Releaes the RCPNode pointer before the destructor is called.
const std::string get_base_obj_type_name() const
std::ostream & operator<<(std::ostream &out, const RCPNodeHandle &node)
Ouput stream operator for RCPNodeHandle.
bool has_ownership() const
Modified boost::any class, which is a container for a templated value.
RCPNodeHandle(const RCPNodeHandle &node_ref)
Copy constructor.
RCPNodeHandle(RCPNode *node, ERCPStrength strength_in=RCP_STRONG, bool newNode=true)
Constructor that takes a pointer to an RCPNode.
Sets up node tracing and prints remaining RCPNodes on destruction.
void has_ownership(bool has_ownership_in)
static std::string getCommonDebugNotesString()
Common error message string on how to debug RCPNode problems.
Debug-mode RCPNode tracing class.
virtual void delete_obj()
Delete the underlying object.
Node class to keep track of address and the reference count for a reference-counted utility class and...
RCPNodeTmpl(T *p, Dealloc_T dealloc, bool has_ownership_in, ENull)
For undefined types .
Templated implementation class of RCPNode that has the responsibility for deleting the reference-coun...
#define TEUCHOS_TEST_FOR_EXCEPT_MSG(throw_exception_test, msg)
This macro is designed to be a short version of TEUCHOS_TEST_FOR_EXCEPTION() that is easier to call...
void assert_valid_ptr(const RCPType &rcp_obj) const
void debugAssertStrength(ERCPStrength strength)
int incr_count(const ERCPStrength strength)
RCPNodeHandle create_strong() const
Return a strong handle.
ERCPStrength strength() const
The strength of this handle.
const any * get_optional_extra_data(const std::string &type_name, const std::string &name) const
ERCPStrength
Used to specify if the pointer is weak or strong.
RCPNodeThrowDeleter(RCPNode *node)
const any & get_extra_data(const std::string &type_name, const std::string &name) const
RCPNode(bool has_ownership_in)
void set_extra_data(const any &extra_data, const std::string &name, EPrePostDestruction destroy_when, bool force_unique)
static RCPNode * getExistingRCPNode(T *p)
Return a raw pointer to an existing owning RCPNode given the address to the underlying object if it e...
void debug_assert_not_null() const
Provides std::map class for deficient platforms.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos, as well as a number of utility routines.
Handle class that manages the RCPNode's reference counting.
int strong_count() const
The strong count for this RCPNode, or 0 if the node is NULL.
void has_ownership(bool has_ownership_in)
ERCPNodeLookup
Used to determine if RCPNode lookup is performed or not.
~RCPNodeThrowDeleter()
Called with node_!=0 when an exception is thrown.
~RCPNodeHandle()
Destructor.
int total_count() const
The sum of the weak and string counts.
EPrePostDestruction
Used to specify a pre or post destruction of extra data.
bool is_valid_ptr() const
Whether the underlying pointer is valid.
RCPNodeTmpl(T *p, Dealloc_T dealloc, bool has_ownership_in)
For defined types.
bool same_node(const RCPNodeHandle &node2) const
Whether the RCPNode for which node2 is a handle is the same RCPNode as this object's RCPNode...
Deletes a (non-owning) RCPNode but not it's underlying object in case of a throw. ...
bool is_node_null() const
Whether the underlying RCPNode is NULL.
#define TEUCHOS_ASSERT(assertion_test)
This macro is throws when an assert fails.
const any & get_extra_data(const std::string &type_name, const std::string &name) const
RCPNode * node_ptr() const
Return a pointer to the underlying RCPNode.
Default traits class for converting objects into strings.
RCPNodeHandle create_weak() const
Return a weak handle.
virtual bool is_valid_ptr() const
int count() const
The strong count; retained for backwards compatibility.
Defines basic traits returning the name of a type in a portable and readable way. ...
void swap(RCPNodeHandle &node_ref)
Swap the contents of node_ref with *this.
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 std::string name()
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.