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)
300 typedef Teuchos::map<std::string,extra_data_entry_t> extra_data_map_t;
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