Teuchos - Trilinos Tools Package Version of the Day
Loading...
Searching...
No Matches
Teuchos_RCPNode.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Teuchos: Common Tools Package
4//
5// Copyright 2004 NTESS and the Teuchos contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef TEUCHOS_RCP_NODE_HPP
11#define TEUCHOS_RCP_NODE_HPP
12
13
21#include "Teuchos_any.hpp"
22#include "Teuchos_map.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"
29
30#if defined(HAVE_TEUCHOSCORE_CXX11) && defined(HAVE_TEUCHOS_THREAD_SAFE) && !defined(DISABLE_ATOMIC_COUNTERS)
31#include <atomic>
32#define USING_ATOMICS
33#endif
34
35namespace Teuchos {
36
37#ifdef USING_ATOMICS
38# define TEUCHOS_RCP_DECL_ATOMIC(VAR, T) std::atomic<T> VAR
39#else
40# define TEUCHOS_RCP_DECL_ATOMIC(VAR, T) T VAR
41#endif
42
47enum EPrePostDestruction { PRE_DESTROY, POST_DESTROY };
48
53enum ERCPStrength { RCP_STRONG=0, RCP_WEAK=1 };
54
59enum ERCPNodeLookup { RCP_ENABLE_NODE_LOOKUP, RCP_DISABLE_NODE_LOOKUP };
60
62inline void debugAssertStrength(ERCPStrength strength)
63{
64#ifdef TEUCHOS_DEBUG
65 switch (strength) {
66 case RCP_STRONG:
67 // fall through
68 case RCP_WEAK:
69 return; // Fine
70 default:
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 << ").");
75 }
76#else
77 (void) strength; // Silence "unused variable" compiler warning.
78#endif // TEUCHOS_DEBUG
79}
80
86template<>
87class TEUCHOSCORE_LIB_DLL_EXPORT ToStringTraits<ERCPStrength> {
88public:
89 static std::string toString( const ERCPStrength &t )
90 {
91 switch (t) {
92 case RCP_STRONG:
93 return "RCP_STRONG";
94 case RCP_WEAK:
95 return "RCP_WEAK";
96 default:
97 // Should never get here but fall through ...
98 break;
99 }
100 // Should never get here!
101#ifdef TEUCHOS_DEBUG
103#else
104 return "";
105#endif
106 }
107};
108
109
121class TEUCHOSCORE_LIB_DLL_EXPORT RCPNode {
122public:
125 : has_ownership_(has_ownership_in), extra_data_map_(NULL)
128#endif // TEUCHOS_DEBUG
129 {
130 count_[RCP_STRONG] = 0;
131 count_[RCP_WEAK] = 0;
132 }
134 virtual ~RCPNode()
135 {
136 if(extra_data_map_)
137 delete extra_data_map_;
138 }
143 {
144#ifdef USING_ATOMICS
145 // this code follows the boost method
146 int strong_count_non_atomic = count_[RCP_STRONG];
147 for( ;; ) {
148 if (strong_count_non_atomic == 0) {
149 return false;
150 }
151 if (std::atomic_compare_exchange_weak( &count_[RCP_STRONG],
153 return true;
154 }
155 }
156#else
157 // the non-thread safe version - this fails with threads because
158 // strong_count_ can become 0 after the check if it is 0 and we would
159 // return true with no valid object
160 if (count_[RCP_STRONG] == 0) {
161 return false;
162 }
163 else {
164 ++count_[RCP_STRONG];
165 return true;
166 }
167#endif
168 }
170 int strong_count() const
171 {
172 return count_[RCP_STRONG];
173 }
175 int weak_count() const // not atomically safe
176 {
177 return count_[RCP_WEAK] - (count_[RCP_STRONG] ? 1 : 0 ); // weak is +1 when strong > 0
178 }
180 void incr_count( const ERCPStrength strength )
181 {
182 debugAssertStrength(strength);
183 if (++count_[strength] == 1) {
184 if (strength == RCP_STRONG) {
185 ++count_[RCP_WEAK]; // this is the special condition - the first strong creates a weak
186 }
187 }
188 }
190 int deincr_count( const ERCPStrength strength )
191 {
192 debugAssertStrength(strength);
193#ifdef BREAK_THREAD_SAFETY_OF_DEINCR_COUNT
194 --count_[strength];
195 return count_[strength]; // not atomically valid
196#else
197 return --count_[strength];
198#endif
199 }
206 bool has_ownership() const
207 {
208 return has_ownership_;
209 }
211 void set_extra_data(
212 const any &extra_data, const std::string& name,
213 EPrePostDestruction destroy_when, bool force_unique );
215 any& get_extra_data( const std::string& type_name,
216 const std::string& name );
218 const any& get_extra_data( const std::string& type_name,
219 const std::string& name
220 ) const
221 {
222 return const_cast<RCPNode*>(this)->get_extra_data(type_name, name);
223 }
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
230 ) const
231 {
232 return const_cast<RCPNode*>(this)->get_optional_extra_data(type_name, name);
233 }
235 virtual bool is_valid_ptr() const = 0;
237 virtual void delete_obj() = 0;
240 const std::string& rcp_type_name,
241 const void* rcp_ptr,
242 const RCPNode* rcp_node_ptr,
243 const void* rcp_obj_ptr
244 ) const = 0;
246 virtual const std::string get_base_obj_type_name() const = 0;
247#ifdef TEUCHOS_DEBUG
249 virtual const void* get_base_obj_map_key_void_ptr() const = 0;
250#endif
251protected:
254 {
255 if(extra_data_map_)
256 impl_pre_delete_extra_data();
257 }
258private:
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)
263 {}
264 any extra_data;
265 EPrePostDestruction destroy_when;
266 };
267 typedef Teuchos::map<std::string,extra_data_entry_t> extra_data_map_t;
268
269 TEUCHOS_RCP_DECL_ATOMIC(count_[2], int);
270 TEUCHOS_RCP_DECL_ATOMIC(has_ownership_, bool);
271
272 extra_data_map_t *extra_data_map_;
273 // Above is made a pointer to reduce overhead for the general case when this
274 // is not used. However, this adds just a little bit to the overhead when
275 // it is used.
276 // Provides the "basic" guarantee!
277 void impl_pre_delete_extra_data();
278 // Not defined and not to be called
279 RCPNode();
280 RCPNode(const RCPNode&);
281 RCPNode& operator=(const RCPNode&);
282#ifdef TEUCHOS_DEBUG
283 // removed atomic because mutex handles it - atomic would be redundant
284 int insertion_number_;
285public:
286 void set_insertion_number(int insertion_number_in)
287 {
288 insertion_number_ = insertion_number_in;
289 }
290 int insertion_number() const
291 {
292 return insertion_number_;
293 }
294#endif // TEUCHOS_DEBUG
295};
296
297
302TEUCHOSCORE_LIB_DLL_EXPORT void throw_null_ptr_error( const std::string &type_name );
303
304
305#ifdef TEUCHOS_DEBUG
306 // to fully implement abort for TEUCHOS_STANDARD_CATCH_STATEMENTS in the cpp
308 TEUCHOSCORE_LIB_DLL_EXPORT void abort_for_exception_in_destructor(const std::exception &);
310 TEUCHOSCORE_LIB_DLL_EXPORT void abort_for_exception_in_destructor(const int &);
312 TEUCHOSCORE_LIB_DLL_EXPORT void abort_for_exception_in_destructor();
313 // called when RCPNode detects any exception in a destructor
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(); }
318#endif
319
336class TEUCHOSCORE_LIB_DLL_EXPORT RCPNodeTracer {
337public:
338
341
345 : maxNumRCPNodes(0), totalNumRCPNodeAllocations(0),
346 totalNumRCPNodeDeletions(0)
347 {}
348 long int maxNumRCPNodes;
349 long int totalNumRCPNodeAllocations;
350 long int totalNumRCPNodeDeletions;
351 };
352
354
357
363 static bool isTracingActiveRCPNodes();
364
365#if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
384#endif
385
389 static int numActiveRCPNodes();
390
392 static RCPNodeStatistics getRCPNodeStatistics() ;
393
395 static void printRCPNodeStatistics(
396 const RCPNodeStatistics& rcpNodeStatistics, std::ostream &out);
397
401 static void setPrintRCPNodeStatisticsOnExit(
403
407 static bool getPrintRCPNodeStatisticsOnExit();
408
412 static void setPrintActiveRcpNodesOnExit(bool printActiveRcpNodesOnExit);
413
417 static bool getPrintActiveRcpNodesOnExit();
418
434 static void printActiveRCPNodes(std::ostream &out);
435
437
442
447 static void addNewRCPNode(RCPNode* rcp_node,
448 const std::string &info );
449
455 static void removeRCPNode( RCPNode* rcp_node );
456
465 template<class T>
466 static const void* getRCPNodeBaseObjMapKeyVoidPtr(T *p)
467 {
468#ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR
469 return getBaseObjVoidPtr(p);
470#else
471 // This will not return the base address for polymorphic types if
472 // multiple inheritance and/or virtual bases are used but returning the
473 // static_cast should be okay in how it is used. It is just that the
474 // RCPNode tracing support will not always be able to figure out if two
475 // pointers of different type are pointing to the same object or not.
476 return static_cast<const void*>(p);
477#endif
478 }
479
486 static RCPNode* getExistingRCPNodeGivenLookupKey(
487 const void* lookupKey);
488
495 template<class T>
497 {
498 return getExistingRCPNodeGivenLookupKey(getRCPNodeBaseObjMapKeyVoidPtr(p));
499 }
500
502 static std::string getActiveRCPNodeHeaderString();
503
505 static std::string getCommonDebugNotesString();
506
508
509};
510
511
512#ifdef TEUCHOS_DEBUG
513# define TEUCHOS_RCP_INSERION_NUMBER_STR() \
514 " insertionNumber: " << rcp_node_ptr->insertion_number() << "\n"
515#else
516# define TEUCHOS_RCP_INSERION_NUMBER_STR()
517#endif
518
519
520void throw_invalid_obj_exception_free_fun(const std::string& rcp_type_name,
521 const void* rcp_ptr,
522 const RCPNode* rcp_node_ptr,
523 const void* rcp_obj_ptr,
524 const void *ptr_,
525#ifdef TEUCHOS_DEBUG
526 const void *deleted_ptr_,
527#endif
528 const std::string& type_name);
529
530
536template<class T, class Dealloc_T>
537class RCPNodeTmpl : public RCPNode {
538public:
541 : RCPNode(has_ownership_in), ptr_(p),
543 base_obj_map_key_void_ptr_(RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p)),
544 deleted_ptr_(0),
545#endif
546 dealloc_(dealloc)
547 {}
559 { return dealloc_; }
561 const Dealloc_T& get_dealloc() const
562 { return dealloc_; }
565 {
566#ifdef TEUCHOS_DEBUG
568 "Error, the underlying object must be explicitly deleted before deleting"
569 " the node object!" );
570#endif
571 }
573 virtual bool is_valid_ptr() const
574 {
575 return ptr_ != 0;
576 }
580 virtual void delete_obj()
581 {
582 if (ptr_!= 0) {
583 this->pre_delete_extra_data(); // Should not throw!
584 T* tmp_ptr = ptr_;
585#ifdef TEUCHOS_DEBUG
587#endif
588 ptr_ = 0;
589 if (has_ownership()) {
590#ifdef TEUCHOS_DEBUG
591 try {
592#endif
593 dealloc_.free(tmp_ptr);
594#ifdef TEUCHOS_DEBUG
595 }
597#endif
598 }
599 }
600 }
603 const std::string& rcp_type_name,
604 const void* rcp_ptr,
605 const RCPNode* rcp_node_ptr,
606 const void* rcp_obj_ptr
607 ) const
608 {
609 throw_invalid_obj_exception_free_fun(rcp_type_name, rcp_ptr, rcp_node_ptr, rcp_obj_ptr, ptr_,
612#endif
613 typeName(*this));
614 }
616 const std::string get_base_obj_type_name() const
617 {
618#ifdef TEUCHOS_DEBUG
620#else
621 return "UnknownType";
622#endif
623 }
624#ifdef TEUCHOS_DEBUG
626 const void* get_base_obj_map_key_void_ptr() const
627 {
629 }
630#endif
631private:
632 T *ptr_;
633#ifdef TEUCHOS_DEBUG
634 const void *base_obj_map_key_void_ptr_;
635 T *deleted_ptr_;
636#endif
637 Dealloc_T dealloc_;
638 // not defined and not to be called
639 RCPNodeTmpl();
640 RCPNodeTmpl(const RCPNodeTmpl&);
641 RCPNodeTmpl& operator=(const RCPNodeTmpl&);
642
643}; // end class RCPNodeTmpl<T>
644
645
653class TEUCHOSCORE_LIB_DLL_EXPORT ActiveRCPNodesSetup {
654public:
660 void foo();
661private:
662 static int count_;
663};
664
665
666} // namespace Teuchos
667
668
669namespace {
670// This static variable is declared before all other static variables that
671// depend on RCP or other classes. Therefore, this static variable will be
672// deleted *after* all of these other static variables that depend on RCP or
673// created classes go away! This ensures that the node tracing machinery is
674// setup and torn down correctly (this is the same trick used by the standard
675// stream objects in many compiler implementations).
676Teuchos::ActiveRCPNodesSetup local_activeRCPNodesSetup;
677} // namespace (anonymous)
678
679
680namespace Teuchos {
681
698class TEUCHOSCORE_LIB_DLL_EXPORT RCPNodeHandle {
699public:
701 RCPNodeHandle (ENull null_arg = null)
702 : node_ (0), strength_ (RCP_STRONG)
703 {
704 (void) null_arg; // Silence "unused variable" compiler warning.
705 }
706
709 ERCPStrength strength_in = RCP_STRONG,
710 bool newNode = true)
711 : node_ (node), strength_ (strength_in)
712 {
713#ifdef TEUCHOS_DEBUG
715#endif // TEUCHOS_DEBUG
716
717 bind();
718
719#ifdef TEUCHOS_DEBUG
720 // Add the node if this is the first RCPNodeHandle to get it. We have
721 // to add it because unbind() will call the remove_RCPNode(...) function
722 // and it needs to match when node tracing is on from the beginning.
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());
728 }
729#else
730 (void) newNode; // Silence "unused variable" compiler warning.
731#endif // TEUCHOS_DEBUG
732 }
733
734#ifdef TEUCHOS_DEBUG
736 template<typename T>
737 RCPNodeHandle (RCPNode* node, T *p, const std::string &T_name,
738 const std::string &ConcreteT_name,
739 const bool has_ownership_in,
740 ERCPStrength strength_in = RCP_STRONG)
741 : node_ (node), strength_ (strength_in)
742 {
743 TEUCHOS_ASSERT(strength_in == RCP_STRONG); // Can't handle weak yet!
744 TEUCHOS_ASSERT(node_);
745 bind();
746 if (RCPNodeTracer::isTracingActiveRCPNodes()) {
747 std::ostringstream os;
748 os << "{T="<<T_name<<", ConcreteT="<< ConcreteT_name
749 <<", p="<<static_cast<const void*>(p)
750 <<", has_ownership="<<has_ownership_in<<"}";
751 RCPNodeTracer::addNewRCPNode(node_, os.str());
752 }
753 }
754#endif // TEUCHOS_DEBUG
755
758 : node_ (node_ref.node_), strength_ (node_ref.strength_)
759 {
760 bind();
761 }
762
765 : node_ (node_ref.node_), strength_ (node_ref.strength_)
766 {
767 node_ref.node_ = 0;
768 node_ref.strength_ = RCP_STRONG;
769 }
770
773 std::swap (node_ref.node_, node_);
774 std::swap (node_ref.strength_, strength_);
775 }
776
777
778
785 unbind(); // May throw in some cases
786 node_ = 0;
787 strength_ = RCP_STRONG;
788 return *this;
789 }
790
797 // NOTE: Don't need to check assignment to self since user-facing classes
798 // do that!
799 unbind(); // May throw in some cases
800 node_ = node_ref.node_;
801 strength_ = node_ref.strength_;
802 bind();
803 return *this;
804 }
805
812 // NOTE: Don't need to check assignment to self since user-facing classes
813 // do that!
814 unbind(); // May throw in some cases
815 node_ = node_ref.node_;
816 strength_ = node_ref.strength_;
817 node_ref.node_ = 0;
818 node_ref.strength_ = RCP_STRONG;
819 return *this;
820 }
821
824 unbind();
825 }
826
828 // otherwise return a null handle
830 // make weak handle
831 RCPNodeHandle possibleStrongNode(node_, RCP_WEAK, false);
832 if (possibleStrongNode.attemptConvertWeakToStrong()) {
833 return possibleStrongNode; // success - we have a good strong handle
834 }
835 return RCPNodeHandle(); // failure - return an empty handle
836 }
837
840 if (node_) {
841 return RCPNodeHandle(node_, RCP_WEAK, false);
842 }
843 return RCPNodeHandle();
844 }
847 if (node_) {
848 return RCPNodeHandle(node_, RCP_STRONG, false);
849 }
850 return RCPNodeHandle();
851 }
853 RCPNode* node_ptr() const {
854 return node_;
855 }
857 bool is_node_null() const {
858 return node_==0;
859 }
863 bool is_valid_ptr() const {
864 if (node_) {
865 return node_->is_valid_ptr();
866 }
867 return true; // Null is a valid ptr!
868 }
871 bool same_node(const RCPNodeHandle &node2) const {
872 return node_ == node2.node_;
873 }
875 int strong_count() const {
876 if (node_) {
877 return node_->strong_count();
878 }
879 return 0;
880 }
882 int weak_count() const {
883 if (node_) {
884 return node_->weak_count(); // Not atomically safe
885 }
886 return 0;
887 }
889 int total_count() const {
890 if (node_) {
891 return node_->strong_count() + node_->weak_count(); // not atomically safe
892 }
893 return 0;
894 }
897 return strength_;
898 }
901 {
902 if (node_)
904 }
906 bool has_ownership() const
907 {
908 if (node_)
909 return node_->has_ownership();
910 return false;
911 }
914 const any &extra_data, const std::string& name,
915 EPrePostDestruction destroy_when, bool force_unique
916 )
917 {
918 debug_assert_not_null();
919 node_->set_extra_data(extra_data, name, destroy_when, force_unique);
920 }
922 any& get_extra_data( const std::string& type_name,
923 const std::string& name
924 )
925 {
926 debug_assert_not_null();
927 return node_->get_extra_data(type_name, name);
928 }
930 const any& get_extra_data( const std::string& type_name,
931 const std::string& name
932 ) const
933 {
934 return const_cast<RCPNodeHandle*>(this)->get_extra_data(type_name, name);
935 }
938 const std::string& type_name, const std::string& name
939 )
940 {
941 debug_assert_not_null();
942 return node_->get_optional_extra_data(type_name, name);
943 }
946 const std::string& type_name, const std::string& name
947 ) const
948 {
949 return const_cast<RCPNodeHandle*>(this)->get_optional_extra_data(type_name, name);
950 }
953 {
954#ifdef TEUCHOS_DEBUG
955 if (!node_)
956 throw_null_ptr_error(typeName(*this));
957#endif
958 }
960 template<class RCPType>
962 {
963 if (!node_)
964 return; // Null is a valid pointer!
965 if (!is_valid_ptr()) {
966 node_->throw_invalid_obj_exception( typeName(rcp_obj),
967 this, node_, rcp_obj.access_private_ptr() );
968 }
969 }
971 template<class RCPType>
973 {
974#ifdef TEUCHOS_DEBUG
975 assert_valid_ptr(rcp_obj);
976#endif
977 }
978#ifdef TEUCHOS_DEBUG
979 const void* get_base_obj_map_key_void_ptr() const
980 {
981 if (node_)
982 return node_->get_base_obj_map_key_void_ptr();
983 return 0;
984 }
985#endif
986private:
987 RCPNode *node_;
988 ERCPStrength strength_;
989 // atomically safe conversion of a weak handle to a strong handle if
990 // possible - if not possible nothing changes
991 bool attemptConvertWeakToStrong() {
992 if (node_->attemptIncrementStrongCountFromNonZeroValue()) {
993 // because we converted strong + 1 we account for this by doing weak - 1
994 node_->deincr_count(RCP_WEAK);
995 // we have successfully incremented the strong count by one
996 strength_ = RCP_STRONG;
997 return true;
998 }
999 return false;
1000 }
1001 inline void bind()
1002 {
1003 if (node_)
1004 node_->incr_count(strength_);
1005 }
1006 inline void unbind()
1007 {
1008 if (node_) {
1009 if(strength_ == RCP_STRONG) {
1010 // only strong checks for --strong == 0
1011 if (node_->deincr_count(RCP_STRONG) == 0) {
1012 unbindOneStrong();
1013 // but if strong hits 0 it also decrements weak_count_plus which
1014 // is weak + (strong != 0)
1015 if( node_->deincr_count(RCP_WEAK) == 0) {
1016 unbindOneTotal();
1017 }
1018 }
1019 }
1020 else if(node_->deincr_count(RCP_WEAK) == 0) { // weak checks here
1021 unbindOneTotal();
1022 }
1023 }
1024 }
1025 void unbindOneStrong();
1026 void unbindOneTotal();
1027};
1028
1029
1034inline
1035std::ostream& operator<<(std::ostream& out, const RCPNodeHandle& node)
1036{
1037 // mfh 15 Sep 2015: Make sure that NULL pointers print consistently.
1038 // Clang 3.5 likes to print an empty string in that case, while GCC
1039 // prints 0. Thus, we test if the pointer is NULL and print 0 in
1040 // that case. This is important for MueLu tests, which compare
1041 // string print-outs.
1042 if (node.node_ptr () == NULL) {
1043 out << "0";
1044 } else {
1045 out << node.node_ptr ();
1046 }
1047 return out;
1048}
1049
1050
1060class TEUCHOSCORE_LIB_DLL_EXPORT RCPNodeThrowDeleter {
1061public:
1064 : node_(node)
1065 {}
1072 {
1073 if (node_) {
1074 node_->has_ownership(false); // Avoid actually deleting ptr_
1075 node_->delete_obj(); // Sets the pointer ptr_=0 to allow RCPNode delete
1076 delete node_;
1077 }
1078 }
1080 RCPNode* get() const
1081 {
1082 return node_;
1083 }
1085 void release()
1086 {
1087 node_ = 0;
1088 }
1089private:
1090 RCPNode *node_;
1091 RCPNodeThrowDeleter(); // Not defined
1092 RCPNodeThrowDeleter(const RCPNodeThrowDeleter&); // Not defined
1093 RCPNodeThrowDeleter& operator=(const RCPNodeThrowDeleter&); // Not defined
1094};
1095
1096
1097//
1098// Unit testing support
1099//
1100
1101
1102#if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1103
1104class SetTracingActiveNodesStack {
1105public:
1106 SetTracingActiveNodesStack()
1107 {RCPNodeTracer::setTracingActiveRCPNodes(true);}
1108 ~SetTracingActiveNodesStack()
1109 {RCPNodeTracer::setTracingActiveRCPNodes(false);}
1110};
1111
1112# define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack;
1113
1114#else
1115
1116# define SET_RCPNODE_TRACING() (void)0
1117
1118#endif // defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1119
1120
1121} // end namespace Teuchos
1122
1123
1124#endif // TEUCHOS_RCP_NODE_HPP
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)
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.
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 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
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.
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.
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)