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"
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 <<
").");
162 count_[RCP_STRONG] = 0;
163 count_[RCP_WEAK] = 0;
169 delete extra_data_map_;
183 if (std::atomic_compare_exchange_weak( &count_[RCP_STRONG],
192 if (count_[RCP_STRONG] == 0) {
196 ++count_[RCP_STRONG];
204 return count_[RCP_STRONG];
209 return count_[RCP_WEAK] - (count_[RCP_STRONG] ? 1 : 0 );
215 if (++count_[strength] == 1) {
216 if (strength == RCP_STRONG) {
225#ifdef BREAK_THREAD_SAFETY_OF_DEINCR_COUNT
227 return count_[strength];
229 return --count_[strength];
244 const any &extra_data,
const std::string& name,
248 const std::string& name );
251 const std::string& 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);
288 impl_pre_delete_extra_data();
291 struct extra_data_entry_t {
292 extra_data_entry_t() : destroy_when(POST_DESTROY) {}
293 extra_data_entry_t(
const any &_extra_data, EPrePostDestruction _destroy_when )
294 : extra_data(_extra_data), destroy_when(_destroy_when)
301 TEUCHOS_RCP_DECL_ATOMIC(count_[2],
int);
302 TEUCHOS_RCP_DECL_ATOMIC(has_ownership_,
bool);
304 extra_data_map_t *extra_data_map_;
309 void impl_pre_delete_extra_data();
312 RCPNode(
const RCPNode&);
313 RCPNode& operator=(
const RCPNode&);
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_;
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)
380 long int maxNumRCPNodes;
381 long int totalNumRCPNodeAllocations;
382 long int totalNumRCPNodeDeletions;
395 static bool isTracingActiveRCPNodes();
397#if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
421 static int numActiveRCPNodes();
427 static void printRCPNodeStatistics(
433 static void setPrintRCPNodeStatisticsOnExit(
439 static bool getPrintRCPNodeStatisticsOnExit();
449 static bool getPrintActiveRcpNodesOnExit();
466 static void printActiveRCPNodes(std::ostream &out);
480 const std::string &info );
500#ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR
508 return static_cast<const void*
>(
p);
518 static RCPNode* getExistingRCPNodeGivenLookupKey(
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()
557template<
class T,
class Dealloc_T>
589 "Error, the underlying object must be explicitly deleted before deleting"
590 " the node object!" );
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"
647 " RCP address: " <<
rcp_ptr <<
"\n"
648 " RCPNode type: " <<
typeName(*
this) <<
"\n"
650 TEUCHOS_RCP_INSERION_NUMBER_STR()
671 return "UnknownType";
684 const void *base_obj_map_key_void_ptr_;
690 RCPNodeTmpl(
const RCPNodeTmpl&);
691 RCPNodeTmpl& operator=(
const RCPNodeTmpl&);
752 : node_ (0), strength_ (RCP_STRONG)
773 if (RCPNodeTracer::isTracingActiveRCPNodes() &&
newNode) {
774 std::ostringstream os;
775 os <<
"{T=Unknown, ConcreteT=Unknown, p=Unknown,"
776 <<
" has_ownership="<<node_->has_ownership()<<
"}";
777 RCPNodeTracer::addNewRCPNode(node_, os.str());
796 if (RCPNodeTracer::isTracingActiveRCPNodes()) {
797 std::ostringstream os;
799 <<
", p="<<
static_cast<const void*
>(
p)
801 RCPNodeTracer::addNewRCPNode(node_, os.str());
824 std::swap (
node_ref.strength_, strength_);
837 strength_ = RCP_STRONG;
922 return node_ ==
node2.node_;
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
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
1006 throw_null_ptr_error(
typeName(*
this));
1010 template<
class RCPType>
1015 if (!is_valid_ptr()) {
1017 this, node_,
rcp_obj.access_private_ptr() );
1021 template<
class RCPType>
1032 return node_->get_base_obj_map_key_void_ptr();
1038 ERCPStrength strength_;
1041 bool attemptConvertWeakToStrong() {
1042 if (node_->attemptIncrementStrongCountFromNonZeroValue()) {
1044 node_->deincr_count(RCP_WEAK);
1046 strength_ = RCP_STRONG;
1054 node_->incr_count(strength_);
1056 inline void unbind()
1059 if(strength_ == RCP_STRONG) {
1061 if (node_->deincr_count(RCP_STRONG) == 0) {
1065 if( node_->deincr_count(RCP_WEAK) == 0) {
1070 else if(node_->deincr_count(RCP_WEAK) == 0) {
1075 void unbindOneStrong();
1076 void unbindOneTotal();
1095 out <<
node.node_ptr ();
1124 node_->has_ownership(
false);
1125 node_->delete_obj();
1152#if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1154class SetTracingActiveNodesStack {
1157 {RCPNodeTracer::setTracingActiveRCPNodes(
true);}
1159 {RCPNodeTracer::setTracingActiveRCPNodes(
false);}
1162# define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack;
1166# define SET_RCPNODE_TRACING() (void)0
Teuchos header file which uses auto-configuration information to include necessary C++ headers.
Defines basic traits returning the name of a type in a portable and readable way.
Modified boost::any class for holding a templated value.
Provides std::map class for deficient platforms.
Sets up node tracing and prints remaining RCPNodes on destruction.
Dangling reference error exception class.
Handle class that manages the RCPNode's reference counting.
any * get_optional_extra_data(const std::string &type_name, const std::string &name)
RCPNodeHandle create_strong() const
Return a strong handle.
void set_extra_data(const any &extra_data, const std::string &name, EPrePostDestruction destroy_when, bool force_unique)
RCPNodeHandle(RCPNode *node, ERCPStrength strength_in=RCP_STRONG, bool newNode=true)
Constructor that takes a pointer to an RCPNode.
RCPNodeHandle create_weak() const
Return a weak handle.
int total_count() const
The sum of the weak and string counts.
RCPNode * node_ptr() const
Return a pointer to the underlying RCPNode.
any & get_extra_data(const std::string &type_name, const std::string &name)
void debug_assert_not_null() const
RCPNodeHandle(ENull null_arg=null)
Default constructor.
RCPNodeHandle create_strong_lock() const
Return a strong handle if possible using thread safe atomics.
RCPNodeHandle(const RCPNodeHandle &node_ref)
Copy constructor.
~RCPNodeHandle()
Destructor.
bool is_node_null() const
Whether the underlying RCPNode is NULL.
std::ostream & operator<<(std::ostream &out, const RCPNodeHandle &node)
Ouput stream operator for RCPNodeHandle.
void debug_assert_valid_ptr(const RCPType &rcp_obj) const
void assert_valid_ptr(const RCPType &rcp_obj) const
const any & get_extra_data(const std::string &type_name, const std::string &name) const
ERCPStrength strength() const
The strength of this handle.
const any * get_optional_extra_data(const std::string &type_name, const std::string &name) const
void swap(RCPNodeHandle &node_ref)
Swap the contents of node_ref with *this.
int weak_count() const
The weak count for this RCPNode, or 0 if the node is NULL.
RCPNodeHandle(RCPNodeHandle &&node_ref)
Move constructor.
void has_ownership(bool has_ownership_in)
bool has_ownership() const
bool is_valid_ptr() const
Whether the underlying pointer is valid.
int strong_count() const
The strong count for this RCPNode, or 0 if the node is NULL.
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.
RCPNodeThrowDeleter(RCPNode *node)
void release()
Releaes the RCPNode pointer before the destructor is called.
~RCPNodeThrowDeleter()
Called with node_!=0 when an exception is thrown.
Templated implementation class of RCPNode that has the responsibility for deleting the reference-coun...
RCPNodeTmpl(T *p, Dealloc_T dealloc, bool has_ownership_in, ENull)
For undefined types .
virtual void delete_obj()
Delete the underlying object. Will abort if an exception is detected in the destructor.
const Dealloc_T & get_dealloc() const
const std::string get_base_obj_type_name() const
virtual bool is_valid_ptr() const
RCPNodeTmpl(T *p, Dealloc_T dealloc, bool has_ownership_in)
For defined types.
Dealloc_T & get_nonconst_dealloc()
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
Debug-mode RCPNode tracing class.
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 std::string getCommonDebugNotesString()
Common error message string on how to debug RCPNode problems.
static RCPNode * getExistingRCPNode(T *p)
Return a raw pointer to an existing owning RCPNode given the address to the underlying object if it e...
Node class to keep track of address and the reference count for a reference-counted utility class and...
bool has_ownership() const
const any & get_extra_data(const std::string &type_name, const std::string &name) const
void pre_delete_extra_data()
virtual const std::string get_base_obj_type_name() const =0
void incr_count(const ERCPStrength strength)
RCPNode(bool has_ownership_in)
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 =0
int deincr_count(const ERCPStrength strength)
virtual void delete_obj()=0
bool attemptIncrementStrongCountFromNonZeroValue()
attemptIncrementStrongCountFromNonZeroValue() supports weak to strong conversion but this is forward ...
void has_ownership(bool has_ownership_in)
const any * get_optional_extra_data(const std::string &type_name, const std::string &name) const
TEUCHOSCORE_LIB_DLL_EXPORT void throw_null_ptr_error(const std::string &type_name)
Throw that a pointer passed into an RCP object is null.
virtual bool is_valid_ptr() const =0
Smart reference counting pointer class for automatic garbage collection.
RCP(ENull null_arg=null)
Initialize RCP<T> to NULL.
bool is_valid_ptr() const
Return if the underlying object pointer is still valid or not.
bool has_ownership() const
Returns true if this has ownership of object pointed to by this->get() in order to delete it.
int weak_count() const
Return the number of active RCP<> objects that have a "weak" reference to the underlying reference-co...
int strong_count() const
Return the number of active RCP<> objects that have a "strong" reference to the underlying reference-...
Default traits class for converting objects into strings.
static std::string name()
Modified boost::any class, which is a container for a templated value.
#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_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 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.
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
ERCPStrength
Used to specify if the pointer is weak or strong.
ERCPNodeLookup
Used to determine if RCPNode lookup is performed or not.
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,...
void debugAssertStrength(ERCPStrength strength)