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 <<
").");
110 #endif // TEUCHOS_DEBUG 158 : has_ownership_(has_ownership_in), extra_data_map_(NULL)
160 ,insertion_number_(-1)
163 count_[RCP_STRONG] = 0;
164 count_[RCP_WEAK] = 0;
170 delete extra_data_map_;
179 int strong_count_non_atomic = count_[RCP_STRONG];
181 if (strong_count_non_atomic == 0) {
184 if (std::atomic_compare_exchange_weak( &count_[RCP_STRONG],
185 &strong_count_non_atomic, strong_count_non_atomic + 1)) {
193 if (count_[RCP_STRONG] == 0) {
197 ++count_[RCP_STRONG];
205 return count_[RCP_STRONG];
210 return count_[RCP_WEAK] - (count_[RCP_STRONG] ? 1 : 0 );
216 if (++count_[strength] == 1) {
217 if (strength == RCP_STRONG) {
226 #ifdef BREAK_THREAD_SAFETY_OF_DEINCR_COUNT 228 return count_[strength];
230 return --count_[strength];
236 has_ownership_ = has_ownership_in;
241 return has_ownership_;
245 const any &extra_data,
const std::string& name,
248 any& get_extra_data(
const std::string& type_name,
249 const std::string& name );
252 const std::string& name
255 return const_cast<RCPNode*
>(
this)->get_extra_data(type_name, name);
258 any* get_optional_extra_data(
const std::string& type_name,
259 const std::string& name );
262 const std::string& type_name,
const std::string& name
265 return const_cast<RCPNode*
>(
this)->get_optional_extra_data(type_name, name);
268 virtual bool is_valid_ptr()
const = 0;
270 virtual void delete_obj() = 0;
272 virtual void throw_invalid_obj_exception(
273 const std::string& rcp_type_name,
276 const void* rcp_obj_ptr
279 virtual const std::string get_base_obj_type_name()
const = 0;
282 virtual const void* get_base_obj_map_key_void_ptr()
const = 0;
289 impl_pre_delete_extra_data();
292 struct extra_data_entry_t {
293 extra_data_entry_t() : destroy_when(POST_DESTROY) {}
295 : extra_data(_extra_data), destroy_when(_destroy_when)
302 TEUCHOS_RCP_DECL_ATOMIC(count_[2],
int);
303 TEUCHOS_RCP_DECL_ATOMIC(has_ownership_,
bool);
305 extra_data_map_t *extra_data_map_;
310 void impl_pre_delete_extra_data();
313 RCPNode(
const RCPNode&);
314 RCPNode& operator=(
const RCPNode&);
317 int insertion_number_;
319 void set_insertion_number(
int insertion_number_in)
321 insertion_number_ = insertion_number_in;
323 int insertion_number()
const 325 return insertion_number_;
327 #endif // TEUCHOS_DEBUG 335 TEUCHOSCORE_LIB_DLL_EXPORT
void throw_null_ptr_error(
const std::string &type_name );
341 TEUCHOSCORE_LIB_DLL_EXPORT
void abort_for_exception_in_destructor(
const std::exception &);
343 TEUCHOSCORE_LIB_DLL_EXPORT
void abort_for_exception_in_destructor(
const int &);
345 TEUCHOSCORE_LIB_DLL_EXPORT
void abort_for_exception_in_destructor();
347 #define TEUCHOS_CATCH_AND_ABORT \ 348 catch(const std::exception &excpt) { abort_for_exception_in_destructor(excpt); } \ 349 catch(const int &excpt_code) { abort_for_exception_in_destructor(excpt_code); } \ 350 catch(...) { abort_for_exception_in_destructor(); } 378 : maxNumRCPNodes(0), totalNumRCPNodeAllocations(0),
379 totalNumRCPNodeDeletions(0)
381 long int maxNumRCPNodes;
382 long int totalNumRCPNodeAllocations;
383 long int totalNumRCPNodeDeletions;
396 static bool isTracingActiveRCPNodes();
398 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 416 static void setTracingActiveRCPNodes(
bool tracingActiveNodes);
422 static int numActiveRCPNodes();
428 static void printRCPNodeStatistics(
434 static void setPrintRCPNodeStatisticsOnExit(
435 bool printRCPNodeStatisticsOnExit);
440 static bool getPrintRCPNodeStatisticsOnExit();
445 static void setPrintActiveRcpNodesOnExit(
bool printActiveRcpNodesOnExit);
450 static bool getPrintActiveRcpNodesOnExit();
467 static void printActiveRCPNodes(std::ostream &out);
480 static void addNewRCPNode(
RCPNode* rcp_node,
481 const std::string &info );
488 static void removeRCPNode(
RCPNode* rcp_node );
501 #ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR 502 return getBaseObjVoidPtr(p);
509 return static_cast<const void*
>(p);
519 static RCPNode* getExistingRCPNodeGivenLookupKey(
520 const void* lookupKey);
531 return getExistingRCPNodeGivenLookupKey(getRCPNodeBaseObjMapKeyVoidPtr(p));
535 static std::string getActiveRCPNodeHeaderString();
538 static std::string getCommonDebugNotesString();
546 # define TEUCHOS_RCP_INSERION_NUMBER_STR() \ 547 " insertionNumber: " << rcp_node_ptr->insertion_number() << "\n" 549 # define TEUCHOS_RCP_INSERION_NUMBER_STR() 558 template<
class T,
class Dealloc_T>
563 :
RCPNode(has_ownership_in), ptr_(p),
565 base_obj_map_key_void_ptr_(
RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p)),
571 RCPNodeTmpl(T* p, Dealloc_T dealloc,
bool has_ownership_in, ENull)
572 :
RCPNode(has_ownership_in), ptr_(p),
574 base_obj_map_key_void_ptr_(0),
590 "Error, the underlying object must be explicitly deleted before deleting" 591 " the node object!" );
608 deleted_ptr_ = tmp_ptr;
615 dealloc_.free(tmp_ptr);
618 TEUCHOS_CATCH_AND_ABORT
625 const std::string& rcp_type_name,
628 const void* rcp_obj_ptr
632 const T* deleted_ptr =
641 "Error, an attempt has been made to dereference the underlying object\n" 642 "from a weak smart pointer object where the underling object has already\n" 643 "been deleted since the strong count has already gone to zero.\n" 645 "Context information:\n" 647 " RCP type: " << rcp_type_name <<
"\n" 648 " RCP address: " << rcp_ptr <<
"\n" 649 " RCPNode type: " <<
typeName(*
this) <<
"\n" 650 " RCPNode address: " << rcp_node_ptr <<
"\n" 651 TEUCHOS_RCP_INSERION_NUMBER_STR()
652 " RCP ptr address: " << rcp_obj_ptr <<
"\n" 653 " Concrete ptr address: " << deleted_ptr <<
"\n" 672 return "UnknownType";
677 const void* get_base_obj_map_key_void_ptr()
const 679 return base_obj_map_key_void_ptr_;
685 const void *base_obj_map_key_void_ptr_;
691 RCPNodeTmpl(
const RCPNodeTmpl&);
692 RCPNodeTmpl& operator=(
const RCPNodeTmpl&);
753 : node_ (0), strength_ (RCP_STRONG)
762 : node_ (node), strength_ (strength_in)
766 #endif // TEUCHOS_DEBUG 775 std::ostringstream os;
776 os <<
"{T=Unknown, ConcreteT=Unknown, p=Unknown," 777 <<
" has_ownership="<<node_->has_ownership()<<
"}";
782 #endif // TEUCHOS_DEBUG 789 const std::string &ConcreteT_name,
790 const bool has_ownership_in,
792 : node_ (node), strength_ (strength_in)
798 std::ostringstream os;
799 os <<
"{T="<<T_name<<
", ConcreteT="<< ConcreteT_name
800 <<
", p="<<
static_cast<const void*
>(p)
801 <<
", has_ownership="<<has_ownership_in<<
"}";
805 #endif // TEUCHOS_DEBUG 809 : node_ (node_ref.node_), strength_ (node_ref.strength_)
816 std::swap (node_ref.node_, node_);
817 std::swap (node_ref.strength_, strength_);
832 node_ = node_ref.node_;
833 strength_ = node_ref.strength_;
849 if (possibleStrongNode.attemptConvertWeakToStrong()) {
850 return possibleStrongNode;
882 return node_->is_valid_ptr();
889 return node_ == node2.node_;
894 return node_->strong_count();
901 return node_->weak_count();
908 return node_->strong_count() + node_->weak_count();
915 return node_->strong_count();
927 node_->has_ownership(has_ownership_in);
933 return node_->has_ownership();
938 const any &extra_data,
const std::string& name,
942 debug_assert_not_null();
943 node_->set_extra_data(extra_data, name, destroy_when, force_unique);
947 const std::string& name
950 debug_assert_not_null();
951 return node_->get_extra_data(type_name, name);
955 const std::string& name
958 return const_cast<RCPNodeHandle*
>(
this)->get_extra_data(type_name, name);
962 const std::string& type_name,
const std::string& name
965 debug_assert_not_null();
966 return node_->get_optional_extra_data(type_name, name);
970 const std::string& type_name,
const std::string& name
973 return const_cast<RCPNodeHandle*
>(
this)->get_optional_extra_data(type_name, name);
980 throw_null_ptr_error(
typeName(*
this));
984 template<
class RCPType>
989 if (!is_valid_ptr()) {
990 node_->throw_invalid_obj_exception(
typeName(rcp_obj),
991 this, node_, rcp_obj.access_private_ptr() );
995 template<
class RCPType>
999 assert_valid_ptr(rcp_obj);
1002 #ifdef TEUCHOS_DEBUG 1003 const void* get_base_obj_map_key_void_ptr()
const 1006 return node_->get_base_obj_map_key_void_ptr();
1015 bool attemptConvertWeakToStrong() {
1016 if (node_->attemptIncrementStrongCountFromNonZeroValue()) {
1018 node_->deincr_count(RCP_WEAK);
1020 strength_ = RCP_STRONG;
1028 node_->incr_count(strength_);
1030 inline void unbind()
1033 if(strength_ == RCP_STRONG) {
1035 if (node_->deincr_count(RCP_STRONG) == 0) {
1039 if( node_->deincr_count(RCP_WEAK) == 0) {
1044 else if(node_->deincr_count(RCP_WEAK) == 0) {
1050 void unbindOneStrong();
1051 void unbindOneTotal();
1099 node_->has_ownership(
false);
1100 node_->delete_obj();
1127 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 1129 class SetTracingActiveNodesStack {
1131 SetTracingActiveNodesStack()
1132 {RCPNodeTracer::setTracingActiveRCPNodes(
true);}
1133 ~SetTracingActiveNodesStack()
1134 {RCPNodeTracer::setTracingActiveRCPNodes(
false);}
1137 # define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack; 1141 # define SET_RCPNODE_TRACING() (void)0 1143 #endif // defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 1149 #endif // TEUCHOS_RCP_NODE_HPP Dangling reference error exception class.
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
Modified boost::any class for holding a templated value.
void assert_valid_ptr(const RCPType &rcp_obj) 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.
#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)
const any & get_extra_data(const std::string &type_name, const std::string &name) const
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.
int count() const
The strong count; retained for backwards compatibility.
void pre_delete_extra_data()
any * get_optional_extra_data(const std::string &type_name, const std::string &name)
void release()
Releaes the RCPNode pointer before the destructor is called.
std::ostream & operator<<(std::ostream &out, const RCPNodeHandle &node)
Ouput stream operator for RCPNodeHandle.
void debug_assert_not_null() const
Modified boost::any class, which is a container for a templated value.
RCPNodeHandle(const RCPNodeHandle &node_ref)
Copy constructor.
RCPNodeHandle create_strong() const
Return a strong handle.
RCPNodeHandle(RCPNode *node, ERCPStrength strength_in=RCP_STRONG, bool newNode=true)
Constructor that takes a pointer to an RCPNode.
RCPNodeHandle create_strong_lock() const
Return a strong handle if possible using thread safe atomics.
bool has_ownership() const
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.
void debug_assert_valid_ptr(const RCPType &rcp_obj) const
Debug-mode RCPNode tracing class.
virtual void delete_obj()
Delete the underlying object. Will abort if an exception is detected in the destructor.
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 .
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...
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...
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.
void debugAssertStrength(ERCPStrength strength)
bool is_node_null() const
Whether the underlying RCPNode is NULL.
ERCPStrength
Used to specify if the pointer is weak or strong.
RCPNodeThrowDeleter(RCPNode *node)
RCPNode(bool has_ownership_in)
void set_extra_data(const any &extra_data, const std::string &name, EPrePostDestruction destroy_when, bool force_unique)
int weak_count() const
The weak count for this RCPNode, or 0 if the node is NULL.
static RCPNode * getExistingRCPNode(T *p)
Return a raw pointer to an existing owning RCPNode given the address to the underlying object if it e...
const any * get_optional_extra_data(const std::string &type_name, const std::string &name) const
Provides std::map class for deficient platforms.
virtual bool is_valid_ptr() const
ERCPStrength strength() const
The strength of this handle.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos, as well as a number of utility routines.
bool is_valid_ptr() const
Whether the underlying pointer is valid.
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.
const std::string get_base_obj_type_name() const
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...
ERCPNodeLookup
Used to determine if RCPNode lookup is performed or not.
~RCPNodeThrowDeleter()
Called with node_!=0 when an exception is thrown.
~RCPNodeHandle()
Destructor.
EPrePostDestruction
Used to specify a pre or post destruction of extra data.
RCPNodeHandle create_weak() const
Return a weak handle.
RCPNodeTmpl(T *p, Dealloc_T dealloc, bool has_ownership_in)
For defined types.
bool has_ownership() const
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.
Deletes a (non-owning) RCPNode but not it's underlying object in case of a throw. ...
#define TEUCHOS_ASSERT(assertion_test)
This macro is throws when an assert fails.
Default traits class for converting objects into strings.
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.
int total_count() const
The sum of the weak and string counts.
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()
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
const Dealloc_T & get_dealloc() const