42 #ifndef TEUCHOS_RCP_NODE_HPP
43 #define TEUCHOS_RCP_NODE_HPP
62 #if defined(HAVE_TEUCHOSCORE_CXX11) && defined(HAVE_TEUCHOS_THREAD_SAFE) && !defined(DISABLE_ATOMIC_COUNTERS)
70 # define TEUCHOS_RCP_DECL_ATOMIC(VAR, T) std::atomic<T> VAR
72 # define TEUCHOS_RCP_DECL_ATOMIC(VAR, T) T VAR
104 true, std::logic_error,
"Teuchos::RCPNode: ERCPStrength enum value "
105 << strength <<
" is invalid (neither RCP_STRONG = " <<
RCP_STRONG
106 <<
" nor RCP_WEAK = " <<
RCP_WEAK <<
").");
110 #endif // TEUCHOS_DEBUG
157 : has_ownership_(has_ownership_in), extra_data_map_(NULL)
159 ,insertion_number_(-1)
169 delete extra_data_map_;
178 int strong_count_non_atomic = count_[
RCP_STRONG];
180 if (strong_count_non_atomic == 0) {
183 if (std::atomic_compare_exchange_weak( &count_[
RCP_STRONG],
184 &strong_count_non_atomic, strong_count_non_atomic + 1)) {
215 if (++count_[strength] == 1) {
225 #ifdef BREAK_THREAD_SAFETY_OF_DEINCR_COUNT
227 return count_[strength];
229 return --count_[strength];
235 has_ownership_ = has_ownership_in;
240 return has_ownership_;
244 const any &extra_data,
const std::string& name,
247 any& get_extra_data(
const std::string& type_name,
248 const std::string& name );
251 const std::string& name
254 return const_cast<RCPNode*
>(
this)->get_extra_data(type_name, name);
257 any* get_optional_extra_data(
const std::string& type_name,
258 const std::string& name );
261 const std::string& type_name,
const std::string& name
264 return const_cast<RCPNode*
>(
this)->get_optional_extra_data(type_name, name);
267 virtual bool is_valid_ptr()
const = 0;
269 virtual void delete_obj() = 0;
271 virtual void throw_invalid_obj_exception(
272 const std::string& rcp_type_name,
275 const void* rcp_obj_ptr
278 virtual const std::string get_base_obj_type_name()
const = 0;
281 virtual const void* get_base_obj_map_key_void_ptr()
const = 0;
288 impl_pre_delete_extra_data();
294 : extra_data(_extra_data), destroy_when(_destroy_when)
309 void impl_pre_delete_extra_data();
316 int insertion_number_;
318 void set_insertion_number(
int insertion_number_in)
320 insertion_number_ = insertion_number_in;
322 int insertion_number()
const
324 return insertion_number_;
326 #endif // TEUCHOS_DEBUG
346 #define TEUCHOS_CATCH_AND_ABORT \
347 catch(const std::exception &excpt) { abort_for_exception_in_destructor(excpt); } \
348 catch(const int &excpt_code) { abort_for_exception_in_destructor(excpt_code); } \
349 catch(...) { abort_for_exception_in_destructor(); }
377 : maxNumRCPNodes(0), totalNumRCPNodeAllocations(0),
378 totalNumRCPNodeDeletions(0)
395 static bool isTracingActiveRCPNodes();
397 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
415 static void setTracingActiveRCPNodes(
bool tracingActiveNodes);
421 static int numActiveRCPNodes();
427 static void printRCPNodeStatistics(
433 static void setPrintRCPNodeStatisticsOnExit(
434 bool printRCPNodeStatisticsOnExit);
439 static bool getPrintRCPNodeStatisticsOnExit();
444 static void setPrintActiveRcpNodesOnExit(
bool printActiveRcpNodesOnExit);
449 static bool getPrintActiveRcpNodesOnExit();
466 static void printActiveRCPNodes(std::ostream &out);
479 static void addNewRCPNode(
RCPNode* rcp_node,
480 const std::string &info );
487 static void removeRCPNode(
RCPNode* rcp_node );
500 #ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR
501 return getBaseObjVoidPtr(p);
508 return static_cast<const void*
>(p);
518 static RCPNode* getExistingRCPNodeGivenLookupKey(
519 const void* lookupKey);
530 return getExistingRCPNodeGivenLookupKey(getRCPNodeBaseObjMapKeyVoidPtr(p));
534 static std::string getActiveRCPNodeHeaderString();
537 static std::string getCommonDebugNotesString();
545 # define TEUCHOS_RCP_INSERION_NUMBER_STR() \
546 " insertionNumber: " << rcp_node_ptr->insertion_number() << "\n"
548 # define TEUCHOS_RCP_INSERION_NUMBER_STR()
557 template<
class T,
class Dealloc_T>
564 base_obj_map_key_void_ptr_(
RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p)),
573 base_obj_map_key_void_ptr_(0),
589 "Error, the underlying object must be explicitly deleted before deleting"
590 " the node object!" );
607 deleted_ptr_ = tmp_ptr;
617 TEUCHOS_CATCH_AND_ABORT
624 const std::string& rcp_type_name,
627 const void* rcp_obj_ptr
631 const T* deleted_ptr =
640 "Error, an attempt has been made to dereference the underlying object\n"
641 "from a weak smart pointer object where the underling object has already\n"
642 "been deleted since the strong count has already gone to zero.\n"
644 "Context information:\n"
646 " RCP type: " << rcp_type_name <<
"\n"
647 " RCP address: " << rcp_ptr <<
"\n"
648 " RCPNode type: " <<
typeName(*
this) <<
"\n"
649 " RCPNode address: " << rcp_node_ptr <<
"\n"
651 " RCP ptr address: " << rcp_obj_ptr <<
"\n"
652 " Concrete ptr address: " << deleted_ptr <<
"\n"
671 return "UnknownType";
676 const void* get_base_obj_map_key_void_ptr()
const
678 return base_obj_map_key_void_ptr_;
684 const void *base_obj_map_key_void_ptr_;
761 : node_ (node), strength_ (strength_in)
765 #endif // TEUCHOS_DEBUG
774 std::ostringstream os;
775 os <<
"{T=Unknown, ConcreteT=Unknown, p=Unknown,"
776 <<
" has_ownership="<<node_->has_ownership()<<
"}";
781 #endif // TEUCHOS_DEBUG
788 const std::string &ConcreteT_name,
789 const bool has_ownership_in,
791 : node_ (node), strength_ (strength_in)
797 std::ostringstream os;
798 os <<
"{T="<<T_name<<
", ConcreteT="<< ConcreteT_name
799 <<
", p="<<
static_cast<const void*
>(p)
800 <<
", has_ownership="<<has_ownership_in<<
"}";
804 #endif // TEUCHOS_DEBUG
808 : node_ (node_ref.node_), strength_ (node_ref.strength_)
815 : node_ (node_ref.node_), strength_ (node_ref.strength_)
823 std::swap (node_ref.
node_, node_);
824 std::swap (node_ref.
strength_, strength_);
850 node_ = node_ref.
node_;
865 node_ = node_ref.node_;
866 strength_ = node_ref.strength_;
883 return possibleStrongNode;
915 return node_->is_valid_ptr();
922 return node_ == node2.
node_;
927 return node_->strong_count();
934 return node_->weak_count();
941 return node_->strong_count() + node_->weak_count();
953 node_->has_ownership(has_ownership_in);
959 return node_->has_ownership();
964 const any &extra_data,
const std::string& name,
968 debug_assert_not_null();
969 node_->set_extra_data(extra_data, name, destroy_when, force_unique);
973 const std::string& name
976 debug_assert_not_null();
977 return node_->get_extra_data(type_name, name);
981 const std::string& name
984 return const_cast<RCPNodeHandle*
>(
this)->get_extra_data(type_name, name);
988 const std::string& type_name,
const std::string& name
991 debug_assert_not_null();
992 return node_->get_optional_extra_data(type_name, name);
996 const std::string& type_name,
const std::string& name
999 return const_cast<RCPNodeHandle*
>(
this)->get_optional_extra_data(type_name, name);
1004 #ifdef TEUCHOS_DEBUG
1006 throw_null_ptr_error(
typeName(*
this));
1010 template<
class RCPType>
1015 if (!is_valid_ptr()) {
1016 node_->throw_invalid_obj_exception(
typeName(rcp_obj),
1017 this, node_, rcp_obj.access_private_ptr() );
1021 template<
class RCPType>
1024 #ifdef TEUCHOS_DEBUG
1025 assert_valid_ptr(rcp_obj);
1028 #ifdef TEUCHOS_DEBUG
1029 const void* get_base_obj_map_key_void_ptr()
const
1032 return node_->get_base_obj_map_key_void_ptr();
1042 if (node_->attemptIncrementStrongCountFromNonZeroValue()) {
1054 node_->incr_count(strength_);
1065 if( node_->deincr_count(
RCP_WEAK) == 0) {
1070 else if(node_->deincr_count(
RCP_WEAK) == 0) {
1075 void unbindOneStrong();
1076 void unbindOneTotal();
1124 node_->has_ownership(
false);
1125 node_->delete_obj();
1152 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1154 class SetTracingActiveNodesStack {
1156 SetTracingActiveNodesStack()
1157 {RCPNodeTracer::setTracingActiveRCPNodes(
true);}
1158 ~SetTracingActiveNodesStack()
1159 {RCPNodeTracer::setTracingActiveRCPNodes(
false);}
1162 # define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack;
1166 # define SET_RCPNODE_TRACING() (void)0
1168 #endif // defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1174 #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.
ERCPStrength
Used to specify if the pointer is weak or strong.
Modified boost::any class for holding a templated value.
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
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.
static std::string toString(const ERCPStrength &t)
#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)
void incr_count(const ERCPStrength strength)
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)
ERCPNodeLookup
Used to determine if RCPNode lookup is performed or not.
void release()
Releaes the RCPNode pointer before the destructor is called.
ENull
Used to initialize a RCP object to NULL using an implicit conversion!
const std::string get_base_obj_type_name() const
std::ostream & operator<<(std::ostream &out, const RCPNodeHandle &node)
Ouput stream operator for RCPNodeHandle.
bool attemptConvertWeakToStrong()
bool has_ownership() const
Modified boost::any class, which is a container for a templated value.
RCPNodeTmpl & operator=(const RCPNodeTmpl &)
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.
long int totalNumRCPNodeAllocations
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. Will abort if an exception is detected in the destructor.
#define TEUCHOS_RCP_DECL_ATOMIC(VAR, T)
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 .
RCPNodeHandle create_strong_lock() const
Return a strong handle if possible using thread safe atomics.
bool attemptIncrementStrongCountFromNonZeroValue()
attemptIncrementStrongCountFromNonZeroValue() supports weak to strong conversion but this is forward ...
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...
#define TEUCHOSCORE_LIB_DLL_EXPORT
void assert_valid_ptr(const RCPType &rcp_obj) const
void debugAssertStrength(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
RCPNodeThrowDeleter(RCPNode *node)
const any & get_extra_data(const std::string &type_name, const std::string &name) const
RCPNode(bool has_ownership_in)
#define TEUCHOS_RCP_INSERION_NUMBER_STR()
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.
RCPNodeHandle(RCPNodeHandle &&node_ref)
Move constructor.
EPrePostDestruction
Used to specify a pre or post destruction of extra data.
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)
#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...
~RCPNodeThrowDeleter()
Called with node_!=0 when an exception is thrown.
~RCPNodeHandle()
Destructor.
int total_count() const
The sum of the weak and string counts.
extra_data_map_t * extra_data_map_
bool is_valid_ptr() const
Whether the underlying pointer is valid.
RCPNodeTmpl(T *p, Dealloc_T dealloc, bool has_ownership_in)
For defined types.
This class creates a basic std::map object for platforms where the std::map is deficient, otherwise the std::map is injected into the Teuchos namespace.
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.
Teuchos::map< std::string, extra_data_entry_t > extra_data_map_t
long int totalNumRCPNodeDeletions
RCPNodeHandle create_weak() const
Return a weak handle.
virtual bool is_valid_ptr() const
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()