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()
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>
568 "Error, the underlying object must be explicitly deleted before deleting"
569 " the node object!" );
621 return "UnknownType";
634 const void *base_obj_map_key_void_ptr_;
640 RCPNodeTmpl(
const RCPNodeTmpl&);
641 RCPNodeTmpl& operator=(
const RCPNodeTmpl&);
702 : node_ (0), strength_ (RCP_STRONG)
723 if (RCPNodeTracer::isTracingActiveRCPNodes() &&
newNode) {
724 std::ostringstream os;
725 os <<
"{T=Unknown, ConcreteT=Unknown, p=Unknown,"
726 <<
" has_ownership="<<node_->has_ownership()<<
"}";
727 RCPNodeTracer::addNewRCPNode(node_, os.str());
746 if (RCPNodeTracer::isTracingActiveRCPNodes()) {
747 std::ostringstream os;
749 <<
", p="<<
static_cast<const void*
>(
p)
751 RCPNodeTracer::addNewRCPNode(node_, os.str());
774 std::swap (
node_ref.strength_, strength_);
787 strength_ = RCP_STRONG;
872 return node_ ==
node2.node_;
914 const any &extra_data,
const std::string& name,
918 debug_assert_not_null();
919 node_->set_extra_data(extra_data, name, destroy_when,
force_unique);
923 const std::string& name
926 debug_assert_not_null();
927 return node_->get_extra_data(
type_name, name);
931 const std::string& name
938 const std::string&
type_name,
const std::string& name
941 debug_assert_not_null();
942 return node_->get_optional_extra_data(
type_name, name);
946 const std::string&
type_name,
const std::string& name
956 throw_null_ptr_error(
typeName(*
this));
960 template<
class RCPType>
965 if (!is_valid_ptr()) {
967 this, node_,
rcp_obj.access_private_ptr() );
971 template<
class RCPType>
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();
1045 out <<
node.node_ptr ();
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.
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-...
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()
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
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 RCPNode * getExistingRCPNode(T *p)
Return a raw pointer to an existing owning RCPNode given the address to the underlying object if it e...
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)