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 <<
").");
125 : has_ownership_(has_ownership_in), extra_data_map_(NULL)
127 ,insertion_number_(-1)
130 count_[RCP_STRONG] = 0;
131 count_[RCP_WEAK] = 0;
137 delete extra_data_map_;
146 int strong_count_non_atomic = count_[RCP_STRONG];
148 if (strong_count_non_atomic == 0) {
151 if (std::atomic_compare_exchange_weak( &count_[RCP_STRONG],
152 &strong_count_non_atomic, strong_count_non_atomic + 1)) {
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];
203 has_ownership_ = has_ownership_in;
208 return has_ownership_;
212 const any &extra_data,
const std::string& name,
216 const std::string& name );
219 const std::string& name
226 const std::string& name );
229 const std::string& type_name,
const std::string& name
240 const std::string& rcp_type_name,
243 const void* rcp_obj_ptr
249 virtual const void* get_base_obj_map_key_void_ptr()
const = 0;
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)
267 typedef Teuchos::map<std::string,extra_data_entry_t> extra_data_map_t;
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_;
308 TEUCHOSCORE_LIB_DLL_EXPORT
void abort_for_exception_in_destructor(
const std::exception &);
310 TEUCHOSCORE_LIB_DLL_EXPORT
void abort_for_exception_in_destructor(
const int &);
312 TEUCHOSCORE_LIB_DLL_EXPORT
void abort_for_exception_in_destructor();
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(); }
343 struct RCPNodeStatistics {
345 : maxNumRCPNodes(0), totalNumRCPNodeAllocations(0),
346 totalNumRCPNodeDeletions(0)
348 long int maxNumRCPNodes;
349 long int totalNumRCPNodeAllocations;
350 long int totalNumRCPNodeDeletions;
365#if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
383 static void setTracingActiveRCPNodes(
bool tracingActiveNodes);
402 bool printRCPNodeStatisticsOnExit);
448 const std::string &info );
468#ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR
469 return getBaseObjVoidPtr(p);
476 return static_cast<const void*
>(p);
486 static RCPNode* getExistingRCPNodeGivenLookupKey(
487 const void* lookupKey);
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()
520void throw_invalid_obj_exception_free_fun(
const std::string& rcp_type_name,
522 const RCPNode* rcp_node_ptr,
523 const void* rcp_obj_ptr,
526 const void *deleted_ptr_,
528 const std::string& type_name);
536template<
class T,
class Dealloc_T>
541 :
RCPNode(has_ownership_in), ptr_(p),
543 base_obj_map_key_void_ptr_(
RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p)),
549 RCPNodeTmpl(T* p, Dealloc_T dealloc,
bool has_ownership_in, ENull)
550 :
RCPNode(has_ownership_in), ptr_(p),
552 base_obj_map_key_void_ptr_(0),
568 "Error, the underlying object must be explicitly deleted before deleting"
569 " the node object!" );
586 deleted_ptr_ = tmp_ptr;
593 dealloc_.free(tmp_ptr);
596 TEUCHOS_CATCH_AND_ABORT
603 const std::string& rcp_type_name,
606 const void* rcp_obj_ptr
609 throw_invalid_obj_exception_free_fun(rcp_type_name, rcp_ptr, rcp_node_ptr, rcp_obj_ptr, ptr_,
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)
724 std::ostringstream os;
725 os <<
"{T=Unknown, ConcreteT=Unknown, p=Unknown,"
726 <<
" has_ownership="<<node_->has_ownership()<<
"}";
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<<
"}";
758 : node_ (node_ref.node_), strength_ (node_ref.strength_)
765 : node_ (node_ref.node_), strength_ (node_ref.strength_)
768 node_ref.strength_ = RCP_STRONG;
773 std::swap (node_ref.node_, node_);
774 std::swap (node_ref.strength_, strength_);
787 strength_ = RCP_STRONG;
800 node_ = node_ref.node_;
801 strength_ = node_ref.strength_;
815 node_ = node_ref.node_;
816 strength_ = node_ref.strength_;
818 node_ref.strength_ = RCP_STRONG;
832 if (possibleStrongNode.attemptConvertWeakToStrong()) {
833 return possibleStrongNode;
865 return node_->is_valid_ptr();
872 return node_ == node2.node_;
877 return node_->strong_count();
884 return node_->weak_count();
891 return node_->strong_count() + node_->weak_count();
903 node_->has_ownership(has_ownership_in);
909 return node_->has_ownership();
914 const any &extra_data,
const std::string& name,
919 node_->set_extra_data(extra_data, name, destroy_when, force_unique);
923 const std::string& name
927 return node_->get_extra_data(type_name, name);
931 const std::string& name
938 const std::string& type_name,
const std::string& name
942 return node_->get_optional_extra_data(type_name, name);
946 const std::string& type_name,
const std::string& name
960 template<
class RCPType>
966 node_->throw_invalid_obj_exception(
typeName(rcp_obj),
967 this, node_, rcp_obj.access_private_ptr() );
971 template<
class RCPType>
979 const void* get_base_obj_map_key_void_ptr()
const
982 return node_->get_base_obj_map_key_void_ptr();
988 ERCPStrength strength_;
991 bool attemptConvertWeakToStrong() {
992 if (node_->attemptIncrementStrongCountFromNonZeroValue()) {
994 node_->deincr_count(RCP_WEAK);
996 strength_ = RCP_STRONG;
1004 node_->incr_count(strength_);
1006 inline void unbind()
1009 if(strength_ == RCP_STRONG) {
1011 if (node_->deincr_count(RCP_STRONG) == 0) {
1015 if( node_->deincr_count(RCP_WEAK) == 0) {
1020 else if(node_->deincr_count(RCP_WEAK) == 0) {
1025 void unbindOneStrong();
1026 void unbindOneTotal();
1074 node_->has_ownership(
false);
1075 node_->delete_obj();
1102#if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1104class SetTracingActiveNodesStack {
1106 SetTracingActiveNodesStack()
1107 {RCPNodeTracer::setTracingActiveRCPNodes(
true);}
1108 ~SetTracingActiveNodesStack()
1109 {RCPNodeTracer::setTracingActiveRCPNodes(
false);}
1112# define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack;
1116# 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.
T1 * get_optional_extra_data(ArrayRCP< T2 > &p, const std::string &name)
Get a pointer to non-const extra data (if it exists) associated with a ArrayRCP object.
T1 & get_extra_data(ArrayRCP< T2 > &p, const std::string &name)
Get a non-const reference to extra data associated with a ArrayRCP object.
void set_extra_data(const T1 &extra_data, const std::string &name, const Ptr< ArrayRCP< T2 > > &p, EPrePostDestruction destroy_when=POST_DESTROY, bool force_unique=true)
Set extra data associated with a ArrayRCP object.
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.
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()
any & get_extra_data(const std::string &type_name, const std::string &name)
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 ...
any * get_optional_extra_data(const std::string &type_name, const std::string &name)
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
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.
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 bool getPrintRCPNodeStatisticsOnExit()
Return if RCPNode usage statistics will be printed when the program ends or not.
static void printRCPNodeStatistics(const RCPNodeStatistics &rcpNodeStatistics, std::ostream &out)
Print the RCPNode allocation statistics.
static RCPNode * getExistingRCPNode(T *p)
Return a raw pointer to an existing owning RCPNode given the address to the underlying object if it e...
static RCPNodeStatistics getRCPNodeStatistics()
Return the statistics on RCPNode allocations.
static void setPrintRCPNodeStatisticsOnExit(bool printRCPNodeStatisticsOnExit)
Set if RCPNode usage statistics will be printed when the program ends or not.
static int numActiveRCPNodes()
Print the number of active RCPNode objects currently being tracked.
static RCPNode * getExistingRCPNodeGivenLookupKey(const void *lookupKey)
Return a raw pointer to an existing owning RCPNode given its lookup key.
static void setPrintActiveRcpNodesOnExit(bool printActiveRcpNodesOnExit)
Set if printActiveRCPNodes() is called on exit from the program.
static bool isTracingActiveRCPNodes()
Return if we are tracing active nodes or not.
static void removeRCPNode(RCPNode *rcp_node)
Remove an RCPNode from global list.
static void printActiveRCPNodes(std::ostream &out)
Print the list of currently active RCP nodes.
static bool getPrintActiveRcpNodesOnExit()
Return if printActiveRCPNodes() is called on exit from the program.
static void addNewRCPNode(RCPNode *rcp_node, const std::string &info)
Add new RCPNode to the global list.
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(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)