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);
272 const std::string& rcp_type_name,
275 const void* rcp_obj_ptr
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)
299 typedef Teuchos::map<std::string,extra_data_entry_t> extra_data_map_t;
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
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)),
570 RCPNodeTmpl(T* p, Dealloc_T dealloc,
bool has_ownership_in, ENull)
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