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 
  157     : has_ownership_(has_ownership_in), extra_data_map_(NULL)
 
  159     ,insertion_number_(-1)
 
  162       count_[RCP_STRONG] = 0;
 
  163       count_[RCP_WEAK] = 0;
 
  169         delete extra_data_map_;
 
  178       int strong_count_non_atomic = count_[RCP_STRONG];
 
  180         if (strong_count_non_atomic == 0) {
 
  183         if (std::atomic_compare_exchange_weak( &count_[RCP_STRONG],
 
  184           &strong_count_non_atomic, strong_count_non_atomic + 1)) {
 
  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];
 
  235       has_ownership_ = has_ownership_in;
 
  240       return has_ownership_;
 
  244     const any &extra_data, 
const std::string& name,
 
  247   any& get_extra_data( 
const std::string& type_name,
 
  248     const std::string& name );
 
  251     const std::string& name
 
  254       return const_cast<RCPNode*
>(
this)->get_extra_data(type_name, 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);
 
  267   virtual bool is_valid_ptr() 
const = 0;
 
  269   virtual void delete_obj() = 0;
 
  271   virtual void throw_invalid_obj_exception(
 
  272     const std::string& rcp_type_name,
 
  275     const void* rcp_obj_ptr
 
  278   virtual const std::string get_base_obj_type_name() 
const = 0;
 
  281   virtual const void* get_base_obj_map_key_void_ptr() 
const = 0;
 
  288         impl_pre_delete_extra_data();
 
  291   struct extra_data_entry_t {
 
  292     extra_data_entry_t() : destroy_when(POST_DESTROY) {}
 
  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_;
 
  326 #endif // TEUCHOS_DEBUG 
  334 TEUCHOSCORE_LIB_DLL_EXPORT 
void throw_null_ptr_error( 
const std::string &type_name );
 
  340   TEUCHOSCORE_LIB_DLL_EXPORT 
void abort_for_exception_in_destructor(
const std::exception &);
 
  342   TEUCHOSCORE_LIB_DLL_EXPORT 
void abort_for_exception_in_destructor(
const int &);
 
  344   TEUCHOSCORE_LIB_DLL_EXPORT 
void abort_for_exception_in_destructor();
 
  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) 
  415   static void setTracingActiveRCPNodes(
bool tracingActiveNodes);
 
  421   static int numActiveRCPNodes();
 
  427   static void printRCPNodeStatistics(
 
  433   static void setPrintRCPNodeStatisticsOnExit(
 
  434     bool printRCPNodeStatisticsOnExit);
 
  439   static bool getPrintRCPNodeStatisticsOnExit();
 
  444   static void setPrintActiveRcpNodesOnExit(
bool printActiveRcpNodesOnExit);
 
  449   static bool getPrintActiveRcpNodesOnExit();
 
  466   static void printActiveRCPNodes(std::ostream &out);
 
  479   static void addNewRCPNode(
RCPNode* rcp_node,
 
  480     const std::string &info );
 
  487   static void removeRCPNode( 
RCPNode* rcp_node );
 
  500 #ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR 
  501       return getBaseObjVoidPtr(p);
 
  508       return static_cast<const void*
>(p);
 
  518   static RCPNode* getExistingRCPNodeGivenLookupKey(
 
  519     const void* lookupKey);
 
  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() 
  557 template<
class T, 
class Dealloc_T>
 
  562     : 
RCPNode(has_ownership_in), ptr_(p),
 
  564       base_obj_map_key_void_ptr_(
RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p)),
 
  571     : 
RCPNode(has_ownership_in), ptr_(p),
 
  573       base_obj_map_key_void_ptr_(0),
 
  589         "Error, the underlying object must be explicitly deleted before deleting" 
  590         " the node object!" );
 
  607         deleted_ptr_ = tmp_ptr;
 
  614             dealloc_.free(tmp_ptr);
 
  617           TEUCHOS_CATCH_AND_ABORT
 
  624     const std::string& rcp_type_name,
 
  627     const void* rcp_obj_ptr
 
  631       const T* deleted_ptr =
 
  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" 
  646         "  RCP type:             " << rcp_type_name << 
"\n" 
  647         "  RCP address:          " << rcp_ptr << 
"\n" 
  648         "  RCPNode type:         " << 
typeName(*
this) << 
"\n" 
  649         "  RCPNode address:      " << rcp_node_ptr << 
"\n" 
  650         TEUCHOS_RCP_INSERION_NUMBER_STR()
 
  651         "  RCP ptr address:      " << rcp_obj_ptr << 
"\n" 
  652         "  Concrete ptr address: " << deleted_ptr << 
"\n" 
  671       return "UnknownType";
 
  676   const void* get_base_obj_map_key_void_ptr()
 const 
  678       return base_obj_map_key_void_ptr_;
 
  684   const void *base_obj_map_key_void_ptr_;
 
  690   RCPNodeTmpl(
const RCPNodeTmpl&);
 
  691   RCPNodeTmpl& operator=(
const RCPNodeTmpl&);
 
  752     : node_ (0), strength_ (RCP_STRONG)
 
  761     : node_ (node), strength_ (strength_in)
 
  765 #endif // TEUCHOS_DEBUG 
  774       std::ostringstream os;
 
  775       os << 
"{T=Unknown, ConcreteT=Unknown, p=Unknown," 
  776          << 
" has_ownership="<<node_->has_ownership()<<
"}";
 
  781 #endif // TEUCHOS_DEBUG 
  788                  const std::string &ConcreteT_name,
 
  789                  const bool has_ownership_in,
 
  791     : node_ (node), strength_ (strength_in)
 
  797       std::ostringstream os;
 
  798       os << 
"{T="<<T_name<<
", ConcreteT="<< ConcreteT_name
 
  799          <<
", p="<<
static_cast<const void*
>(p)
 
  800          <<
", has_ownership="<<has_ownership_in<<
"}";
 
  804 #endif // TEUCHOS_DEBUG 
  808     : node_ (node_ref.node_), strength_ (node_ref.strength_)
 
  815     : node_ (node_ref.node_), strength_ (node_ref.strength_)
 
  818     node_ref.strength_ = RCP_STRONG;
 
  823     std::swap (node_ref.node_, node_);
 
  824     std::swap (node_ref.strength_, strength_);
 
  837     strength_ = RCP_STRONG;
 
  850     node_ = node_ref.node_;
 
  851     strength_ = node_ref.strength_;
 
  865     node_ = node_ref.node_;
 
  866     strength_ = node_ref.strength_;
 
  868     node_ref.strength_ = RCP_STRONG;
 
  882     if (possibleStrongNode.attemptConvertWeakToStrong()) {
 
  883       return possibleStrongNode; 
 
  915       return node_->is_valid_ptr();
 
  922     return node_ == node2.node_;
 
  927       return node_->strong_count();
 
  934       return node_->weak_count(); 
 
  941       return node_->strong_count() + node_->weak_count(); 
 
  948       return node_->strong_count();
 
  960         node_->has_ownership(has_ownership_in);
 
  966         return node_->has_ownership();
 
  971     const any &extra_data, 
const std::string& name,
 
  975       debug_assert_not_null();
 
  976       node_->set_extra_data(extra_data, name, destroy_when, force_unique);
 
  980     const std::string& name
 
  983       debug_assert_not_null();
 
  984       return node_->get_extra_data(type_name, name);
 
  988     const std::string& name
 
  991       return const_cast<RCPNodeHandle*
>(
this)->get_extra_data(type_name, name);
 
  995     const std::string& type_name, 
const std::string& name
 
  998       debug_assert_not_null();
 
  999       return node_->get_optional_extra_data(type_name, name);
 
 1003     const std::string& type_name, 
const std::string& name
 
 1006       return const_cast<RCPNodeHandle*
>(
this)->get_optional_extra_data(type_name, name);
 
 1011 #ifdef TEUCHOS_DEBUG 
 1013         throw_null_ptr_error(
typeName(*
this));
 
 1017   template<
class RCPType>
 
 1022       if (!is_valid_ptr()) {
 
 1023         node_->throw_invalid_obj_exception( 
typeName(rcp_obj),
 
 1024           this, node_, rcp_obj.access_private_ptr() );
 
 1028   template<
class RCPType>
 
 1031 #ifdef TEUCHOS_DEBUG 
 1032       assert_valid_ptr(rcp_obj);
 
 1035 #ifdef TEUCHOS_DEBUG 
 1036   const void* get_base_obj_map_key_void_ptr()
 const 
 1039         return node_->get_base_obj_map_key_void_ptr();
 
 1048   bool attemptConvertWeakToStrong() {
 
 1049     if (node_->attemptIncrementStrongCountFromNonZeroValue()) {
 
 1051       node_->deincr_count(RCP_WEAK);
 
 1053       strength_ = RCP_STRONG;
 
 1061         node_->incr_count(strength_);
 
 1063   inline void unbind()
 
 1066         if(strength_ == RCP_STRONG) {
 
 1068           if (node_->deincr_count(RCP_STRONG) == 0) {
 
 1072             if( node_->deincr_count(RCP_WEAK) == 0) {
 
 1077         else if(node_->deincr_count(RCP_WEAK) == 0) {  
 
 1082   void unbindOneStrong();
 
 1083   void unbindOneTotal();
 
 1131         node_->has_ownership(
false); 
 
 1132         node_->delete_obj(); 
 
 1159 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 
 1161 class SetTracingActiveNodesStack {
 
 1163   SetTracingActiveNodesStack()
 
 1164     {RCPNodeTracer::setTracingActiveRCPNodes(
true);}
 
 1165   ~SetTracingActiveNodesStack()
 
 1166     {RCPNodeTracer::setTracingActiveRCPNodes(
false);}
 
 1169 #  define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack; 
 1173 #  define SET_RCPNODE_TRACING() (void)0 
 1175 #endif // defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 
 1181 #endif // TEUCHOS_RCP_NODE_HPP 
Dangling reference error exception class. 
 
const Dealloc_T & get_dealloc() const 
 
bool has_ownership() const 
 
int weak_count() const 
The weak count for this RCPNode, or 0 if the node is NULL. 
 
Modified boost::any class for holding a templated value. 
 
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 
 
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)
 
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. 
 
void debug_assert_valid_ptr(const RCPType &rcp_obj) const 
 
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. 
 
ENull
Used to initialize a RCP object to NULL using an implicit conversion! 
 
const std::string get_base_obj_type_name() const 
 
std::ostream & operator<<(std::ostream &out, const RCPNodeHandle &node)
Ouput stream operator for RCPNodeHandle. 
 
bool has_ownership() const 
 
Modified boost::any class, which is a container for a templated value. 
 
RCPNodeHandle(const RCPNodeHandle &node_ref)
Copy constructor. 
 
RCPNodeHandle(RCPNode *node, ERCPStrength strength_in=RCP_STRONG, bool newNode=true)
Constructor that takes a pointer to an RCPNode. 
 
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. 
 
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 . 
 
RCPNodeHandle create_strong_lock() const 
Return a strong handle if possible using thread safe atomics. 
 
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...
 
void assert_valid_ptr(const RCPType &rcp_obj) const 
 
void debugAssertStrength(ERCPStrength strength)
 
RCPNodeHandle create_strong() const 
Return a strong handle. 
 
ERCPStrength strength() const 
The strength of this handle. 
 
const any * get_optional_extra_data(const std::string &type_name, const std::string &name) const 
 
ERCPStrength
Used to specify if the pointer is weak or strong. 
 
RCPNodeThrowDeleter(RCPNode *node)
 
const any & get_extra_data(const std::string &type_name, const std::string &name) const 
 
RCPNode(bool has_ownership_in)
 
void set_extra_data(const any &extra_data, const std::string &name, EPrePostDestruction destroy_when, bool force_unique)
 
static RCPNode * getExistingRCPNode(T *p)
Return a raw pointer to an existing owning RCPNode given the address to the underlying object if it e...
 
void debug_assert_not_null() const 
 
Provides std::map class for deficient platforms. 
 
RCPNodeHandle(RCPNodeHandle &&node_ref)
Move constructor. 
 
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. 
 
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. 
 
int total_count() const 
The sum of the weak and string counts. 
 
EPrePostDestruction
Used to specify a pre or post destruction of extra data. 
 
bool is_valid_ptr() const 
Whether the underlying pointer is valid. 
 
RCPNodeTmpl(T *p, Dealloc_T dealloc, bool has_ownership_in)
For defined types. 
 
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. 
 
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. ...
 
bool is_node_null() const 
Whether the underlying RCPNode is NULL. 
 
#define TEUCHOS_ASSERT(assertion_test)
This macro is throws when an assert fails. 
 
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. 
 
Default traits class for converting objects into strings. 
 
RCPNodeHandle create_weak() const 
Return a weak handle. 
 
virtual bool is_valid_ptr() const 
 
int count() const 
The strong count; retained for backwards compatibility. 
 
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. 
 
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.