10#ifndef TEUCHOS_RCP_NODE_HPP
11#define TEUCHOS_RCP_NODE_HPP
23#include "Teuchos_ENull.hpp"
24#include "Teuchos_Assert.hpp"
25#include "Teuchos_Exceptions.hpp"
27#include "Teuchos_toString.hpp"
28#include "Teuchos_getBaseObjVoidPtr.hpp"
30#if defined(HAVE_TEUCHOSCORE_CXX11) && defined(HAVE_TEUCHOS_THREAD_SAFE) && !defined(DISABLE_ATOMIC_COUNTERS)
38# define TEUCHOS_RCP_DECL_ATOMIC(VAR, T) std::atomic<T> VAR
40# define TEUCHOS_RCP_DECL_ATOMIC(VAR, T) T VAR
72 true, std::logic_error,
"Teuchos::RCPNode: ERCPStrength enum value "
73 << strength <<
" is invalid (neither RCP_STRONG = " << RCP_STRONG
74 <<
" nor RCP_WEAK = " << RCP_WEAK <<
").");
130 count_[RCP_STRONG] = 0;
131 count_[RCP_WEAK] = 0;
137 delete extra_data_map_;
151 if (std::atomic_compare_exchange_weak( &count_[RCP_STRONG],
160 if (count_[RCP_STRONG] == 0) {
164 ++count_[RCP_STRONG];
172 return count_[RCP_STRONG];
177 return count_[RCP_WEAK] - (count_[RCP_STRONG] ? 1 : 0 );
183 if (++count_[strength] == 1) {
184 if (strength == RCP_STRONG) {
193#ifdef BREAK_THREAD_SAFETY_OF_DEINCR_COUNT
195 return count_[strength];
197 return --count_[strength];
212 const any &extra_data,
const std::string& name,
216 const std::string& name );
219 const std::string& name
225 any* get_optional_extra_data(
const std::string&
type_name,
226 const std::string& name );
229 const std::string&
type_name,
const std::string& name
232 return const_cast<RCPNode*
>(
this)->get_optional_extra_data(
type_name, name);
256 impl_pre_delete_extra_data();
259 struct extra_data_entry_t {
260 extra_data_entry_t() : destroy_when(POST_DESTROY) {}
261 extra_data_entry_t(
const any &_extra_data, EPrePostDestruction _destroy_when )
262 : extra_data(_extra_data), destroy_when(_destroy_when)
269 TEUCHOS_RCP_DECL_ATOMIC(count_[2],
int);
270 TEUCHOS_RCP_DECL_ATOMIC(has_ownership_,
bool);
272 extra_data_map_t *extra_data_map_;
277 void impl_pre_delete_extra_data();
280 RCPNode(
const RCPNode&);
281 RCPNode& operator=(
const RCPNode&);
284 int insertion_number_;
286 void set_insertion_number(
int insertion_number_in)
288 insertion_number_ = insertion_number_in;
290 int insertion_number()
const
292 return insertion_number_;
314 #define TEUCHOS_CATCH_AND_ABORT \
315 catch(const std::exception &excpt) { abort_for_exception_in_destructor(excpt); } \
316 catch(const int &excpt_code) { abort_for_exception_in_destructor(excpt_code); } \
317 catch(...) { abort_for_exception_in_destructor(); }
345 : maxNumRCPNodes(0), totalNumRCPNodeAllocations(0),
346 totalNumRCPNodeDeletions(0)
348 long int maxNumRCPNodes;
349 long int totalNumRCPNodeAllocations;
350 long int totalNumRCPNodeDeletions;
363 static bool isTracingActiveRCPNodes();
365#if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
389 static int numActiveRCPNodes();
395 static void printRCPNodeStatistics(
401 static void setPrintRCPNodeStatisticsOnExit(
407 static bool getPrintRCPNodeStatisticsOnExit();
417 static bool getPrintActiveRcpNodesOnExit();
434 static void printActiveRCPNodes(std::ostream &out);
448 const std::string &info );
468#ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR
476 return static_cast<const void*
>(
p);
486 static RCPNode* getExistingRCPNodeGivenLookupKey(
498 return getExistingRCPNodeGivenLookupKey(getRCPNodeBaseObjMapKeyVoidPtr(
p));
502 static std::string getActiveRCPNodeHeaderString();
505 static std::string getCommonDebugNotesString();
513# define TEUCHOS_RCP_INSERION_NUMBER_STR() \
514 " insertionNumber: " << rcp_node_ptr->insertion_number() << "\n"
516# define TEUCHOS_RCP_INSERION_NUMBER_STR()
525template<
class T,
class Dealloc_T>
557 "Error, the underlying object must be explicitly deleted before deleting"
558 " the node object!" );
608 "Error, an attempt has been made to dereference the underlying object\n"
609 "from a weak smart pointer object where the underling object has already\n"
610 "been deleted since the strong count has already gone to zero.\n"
612 "Context information:\n"
615 " RCP address: " <<
rcp_ptr <<
"\n"
616 " RCPNode type: " <<
typeName(*
this) <<
"\n"
618 TEUCHOS_RCP_INSERION_NUMBER_STR()
639 return "UnknownType";
652 const void *base_obj_map_key_void_ptr_;
658 RCPNodeTmpl(
const RCPNodeTmpl&);
659 RCPNodeTmpl& operator=(
const RCPNodeTmpl&);
720 : node_ (0), strength_ (RCP_STRONG)
741 if (RCPNodeTracer::isTracingActiveRCPNodes() &&
newNode) {
742 std::ostringstream os;
743 os <<
"{T=Unknown, ConcreteT=Unknown, p=Unknown,"
744 <<
" has_ownership="<<node_->has_ownership()<<
"}";
745 RCPNodeTracer::addNewRCPNode(node_, os.str());
764 if (RCPNodeTracer::isTracingActiveRCPNodes()) {
765 std::ostringstream os;
767 <<
", p="<<
static_cast<const void*
>(
p)
769 RCPNodeTracer::addNewRCPNode(node_, os.str());
792 std::swap (
node_ref.strength_, strength_);
805 strength_ = RCP_STRONG;
890 return node_ ==
node2.node_;
932 const any &extra_data,
const std::string& name,
936 debug_assert_not_null();
937 node_->set_extra_data(extra_data, name, destroy_when,
force_unique);
941 const std::string& name
944 debug_assert_not_null();
945 return node_->get_extra_data(
type_name, name);
949 const std::string& name
956 const std::string&
type_name,
const std::string& name
959 debug_assert_not_null();
960 return node_->get_optional_extra_data(
type_name, name);
964 const std::string&
type_name,
const std::string& name
974 throw_null_ptr_error(
typeName(*
this));
978 template<
class RCPType>
983 if (!is_valid_ptr()) {
985 this, node_,
rcp_obj.access_private_ptr() );
989 template<
class RCPType>
1000 return node_->get_base_obj_map_key_void_ptr();
1006 ERCPStrength strength_;
1009 bool attemptConvertWeakToStrong() {
1010 if (node_->attemptIncrementStrongCountFromNonZeroValue()) {
1012 node_->deincr_count(RCP_WEAK);
1014 strength_ = RCP_STRONG;
1022 node_->incr_count(strength_);
1024 inline void unbind()
1027 if(strength_ == RCP_STRONG) {
1029 if (node_->deincr_count(RCP_STRONG) == 0) {
1033 if( node_->deincr_count(RCP_WEAK) == 0) {
1038 else if(node_->deincr_count(RCP_WEAK) == 0) {
1043 void unbindOneStrong();
1044 void unbindOneTotal();
1063 out <<
node.node_ptr ();
1092 node_->has_ownership(
false);
1093 node_->delete_obj();
1120#if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1122class SetTracingActiveNodesStack {
1124 SetTracingActiveNodesStack()
1125 {RCPNodeTracer::setTracingActiveRCPNodes(
true);}
1126 ~SetTracingActiveNodesStack()
1127 {RCPNodeTracer::setTracingActiveRCPNodes(
false);}
1130# define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack;
1134# 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.
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)