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
525template<class T, class Dealloc_T>
526class RCPNodeTmpl : public RCPNode {
527public:
530 : RCPNode(has_ownership_in), ptr_(p),
532 base_obj_map_key_void_ptr_(RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p)),
533 deleted_ptr_(0),
534#endif
535 dealloc_(dealloc)
536 {}
548 { return dealloc_; }
550 const Dealloc_T& get_dealloc() const
551 { return dealloc_; }
554 {
555#ifdef TEUCHOS_DEBUG
557 "Error, the underlying object must be explicitly deleted before deleting"
558 " the node object!" );
559#endif
560 }
562 virtual bool is_valid_ptr() const
563 {
564 return ptr_ != 0;
565 }
569 virtual void delete_obj()
570 {
571 if (ptr_!= 0) {
572 this->pre_delete_extra_data(); // Should not throw!
573 T* tmp_ptr = ptr_;
574#ifdef TEUCHOS_DEBUG
576#endif
577 ptr_ = 0;
578 if (has_ownership()) {
579#ifdef TEUCHOS_DEBUG
580 try {
581#endif
582 dealloc_.free(tmp_ptr);
583#ifdef TEUCHOS_DEBUG
584 }
586#endif
587 }
588 }
589 }
592 const std::string& rcp_type_name,
593 const void* rcp_ptr,
594 const RCPNode* rcp_node_ptr,
595 const void* rcp_obj_ptr
596 ) const
597 {
598 TEUCHOS_TEST_FOR_EXCEPT_MSG( ptr_!=0, "Internal coding error!" );
599 const T* deleted_ptr =
600#ifdef TEUCHOS_DEBUG
602#else
603 0
604#endif
605 ;
608 "Error, an attempt has been made to dereference the underlying object\n"
609 "from a weak smart pointer object where the underling object has already\n"
610 "been deleted since the strong count has already gone to zero.\n"
611 "\n"
612 "Context information:\n"
613 "\n"
614 " RCP type: " << rcp_type_name << "\n"
615 " RCP address: " << rcp_ptr << "\n"
616 " RCPNode type: " << typeName(*this) << "\n"
617 " RCPNode address: " << rcp_node_ptr << "\n"
618 TEUCHOS_RCP_INSERION_NUMBER_STR()
619 " RCP ptr address: " << rcp_obj_ptr << "\n"
620 " Concrete ptr address: " << deleted_ptr << "\n"
621 "\n"
623 );
624 // 2008/09/22: rabartl: Above, we do not provide the concreate object
625 // type or the concrete object address. In the case of the concrete
626 // object address, in a non-debug build, we don't want to pay a price
627 // for extra storage that we strictly don't need. In the case of the
628 // concrete object type name, we don't want to force non-debug built
629 // code to have the require that types be fully defined in order to use
630 // the memory management software. This is related to bug 4016.
631
632 }
634 const std::string get_base_obj_type_name() const
635 {
636#ifdef TEUCHOS_DEBUG
638#else
639 return "UnknownType";
640#endif
641 }
642#ifdef TEUCHOS_DEBUG
644 const void* get_base_obj_map_key_void_ptr() const
645 {
647 }
648#endif
649private:
650 T *ptr_;
651#ifdef TEUCHOS_DEBUG
652 const void *base_obj_map_key_void_ptr_;
653 T *deleted_ptr_;
654#endif
655 Dealloc_T dealloc_;
656 // not defined and not to be called
657 RCPNodeTmpl();
658 RCPNodeTmpl(const RCPNodeTmpl&);
659 RCPNodeTmpl& operator=(const RCPNodeTmpl&);
660
661}; // end class RCPNodeTmpl<T>
662
663
671class TEUCHOSCORE_LIB_DLL_EXPORT ActiveRCPNodesSetup {
672public:
678 void foo();
679private:
680 static int count_;
681};
682
683
684} // namespace Teuchos
685
686
687namespace {
688// This static variable is declared before all other static variables that
689// depend on RCP or other classes. Therefore, this static variable will be
690// deleted *after* all of these other static variables that depend on RCP or
691// created classes go away! This ensures that the node tracing machinery is
692// setup and torn down correctly (this is the same trick used by the standard
693// stream objects in many compiler implementations).
694Teuchos::ActiveRCPNodesSetup local_activeRCPNodesSetup;
695} // namespace (anonymous)
696
697
698namespace Teuchos {
699
716class TEUCHOSCORE_LIB_DLL_EXPORT RCPNodeHandle {
717public:
719 RCPNodeHandle (ENull null_arg = null)
720 : node_ (0), strength_ (RCP_STRONG)
721 {
722 (void) null_arg; // Silence "unused variable" compiler warning.
723 }
724
727 ERCPStrength strength_in = RCP_STRONG,
728 bool newNode = true)
729 : node_ (node), strength_ (strength_in)
730 {
731#ifdef TEUCHOS_DEBUG
733#endif // TEUCHOS_DEBUG
734
735 bind();
736
737#ifdef TEUCHOS_DEBUG
738 // Add the node if this is the first RCPNodeHandle to get it. We have
739 // to add it because unbind() will call the remove_RCPNode(...) function
740 // and it needs to match when node tracing is on from the beginning.
741 if (RCPNodeTracer::isTracingActiveRCPNodes() && newNode) {
742 std::ostringstream os;
743 os << "{T=Unknown, ConcreteT=Unknown, p=Unknown,"
744 << " has_ownership="<<node_->has_ownership()<<"}";
745 RCPNodeTracer::addNewRCPNode(node_, os.str());
746 }
747#else
748 (void) newNode; // Silence "unused variable" compiler warning.
749#endif // TEUCHOS_DEBUG
750 }
751
752#ifdef TEUCHOS_DEBUG
754 template<typename T>
755 RCPNodeHandle (RCPNode* node, T *p, const std::string &T_name,
756 const std::string &ConcreteT_name,
757 const bool has_ownership_in,
758 ERCPStrength strength_in = RCP_STRONG)
759 : node_ (node), strength_ (strength_in)
760 {
761 TEUCHOS_ASSERT(strength_in == RCP_STRONG); // Can't handle weak yet!
762 TEUCHOS_ASSERT(node_);
763 bind();
764 if (RCPNodeTracer::isTracingActiveRCPNodes()) {
765 std::ostringstream os;
766 os << "{T="<<T_name<<", ConcreteT="<< ConcreteT_name
767 <<", p="<<static_cast<const void*>(p)
768 <<", has_ownership="<<has_ownership_in<<"}";
769 RCPNodeTracer::addNewRCPNode(node_, os.str());
770 }
771 }
772#endif // TEUCHOS_DEBUG
773
776 : node_ (node_ref.node_), strength_ (node_ref.strength_)
777 {
778 bind();
779 }
780
783 : node_ (node_ref.node_), strength_ (node_ref.strength_)
784 {
785 node_ref.node_ = 0;
786 node_ref.strength_ = RCP_STRONG;
787 }
788
791 std::swap (node_ref.node_, node_);
792 std::swap (node_ref.strength_, strength_);
793 }
794
795
796
803 unbind(); // May throw in some cases
804 node_ = 0;
805 strength_ = RCP_STRONG;
806 return *this;
807 }
808
815 // NOTE: Don't need to check assignment to self since user-facing classes
816 // do that!
817 unbind(); // May throw in some cases
818 node_ = node_ref.node_;
819 strength_ = node_ref.strength_;
820 bind();
821 return *this;
822 }
823
830 // NOTE: Don't need to check assignment to self since user-facing classes
831 // do that!
832 unbind(); // May throw in some cases
833 node_ = node_ref.node_;
834 strength_ = node_ref.strength_;
835 node_ref.node_ = 0;
836 node_ref.strength_ = RCP_STRONG;
837 return *this;
838 }
839
842 unbind();
843 }
844
846 // otherwise return a null handle
848 // make weak handle
849 RCPNodeHandle possibleStrongNode(node_, RCP_WEAK, false);
850 if (possibleStrongNode.attemptConvertWeakToStrong()) {
851 return possibleStrongNode; // success - we have a good strong handle
852 }
853 return RCPNodeHandle(); // failure - return an empty handle
854 }
855
858 if (node_) {
859 return RCPNodeHandle(node_, RCP_WEAK, false);
860 }
861 return RCPNodeHandle();
862 }
865 if (node_) {
866 return RCPNodeHandle(node_, RCP_STRONG, false);
867 }
868 return RCPNodeHandle();
869 }
871 RCPNode* node_ptr() const {
872 return node_;
873 }
875 bool is_node_null() const {
876 return node_==0;
877 }
881 bool is_valid_ptr() const {
882 if (node_) {
883 return node_->is_valid_ptr();
884 }
885 return true; // Null is a valid ptr!
886 }
889 bool same_node(const RCPNodeHandle &node2) const {
890 return node_ == node2.node_;
891 }
893 int strong_count() const {
894 if (node_) {
895 return node_->strong_count();
896 }
897 return 0;
898 }
900 int weak_count() const {
901 if (node_) {
902 return node_->weak_count(); // Not atomically safe
903 }
904 return 0;
905 }
907 int total_count() const {
908 if (node_) {
909 return node_->strong_count() + node_->weak_count(); // not atomically safe
910 }
911 return 0;
912 }
915 return strength_;
916 }
919 {
920 if (node_)
922 }
924 bool has_ownership() const
925 {
926 if (node_)
927 return node_->has_ownership();
928 return false;
929 }
932 const any &extra_data, const std::string& name,
933 EPrePostDestruction destroy_when, bool force_unique
934 )
935 {
936 debug_assert_not_null();
937 node_->set_extra_data(extra_data, name, destroy_when, force_unique);
938 }
940 any& get_extra_data( const std::string& type_name,
941 const std::string& name
942 )
943 {
944 debug_assert_not_null();
945 return node_->get_extra_data(type_name, name);
946 }
948 const any& get_extra_data( const std::string& type_name,
949 const std::string& name
950 ) const
951 {
952 return const_cast<RCPNodeHandle*>(this)->get_extra_data(type_name, name);
953 }
956 const std::string& type_name, const std::string& name
957 )
958 {
959 debug_assert_not_null();
960 return node_->get_optional_extra_data(type_name, name);
961 }
964 const std::string& type_name, const std::string& name
965 ) const
966 {
967 return const_cast<RCPNodeHandle*>(this)->get_optional_extra_data(type_name, name);
968 }
971 {
972#ifdef TEUCHOS_DEBUG
973 if (!node_)
974 throw_null_ptr_error(typeName(*this));
975#endif
976 }
978 template<class RCPType>
980 {
981 if (!node_)
982 return; // Null is a valid pointer!
983 if (!is_valid_ptr()) {
984 node_->throw_invalid_obj_exception( typeName(rcp_obj),
985 this, node_, rcp_obj.access_private_ptr() );
986 }
987 }
989 template<class RCPType>
991 {
992#ifdef TEUCHOS_DEBUG
993 assert_valid_ptr(rcp_obj);
994#endif
995 }
996#ifdef TEUCHOS_DEBUG
997 const void* get_base_obj_map_key_void_ptr() const
998 {
999 if (node_)
1000 return node_->get_base_obj_map_key_void_ptr();
1001 return 0;
1002 }
1003#endif
1004private:
1005 RCPNode *node_;
1006 ERCPStrength strength_;
1007 // atomically safe conversion of a weak handle to a strong handle if
1008 // possible - if not possible nothing changes
1009 bool attemptConvertWeakToStrong() {
1010 if (node_->attemptIncrementStrongCountFromNonZeroValue()) {
1011 // because we converted strong + 1 we account for this by doing weak - 1
1012 node_->deincr_count(RCP_WEAK);
1013 // we have successfully incremented the strong count by one
1014 strength_ = RCP_STRONG;
1015 return true;
1016 }
1017 return false;
1018 }
1019 inline void bind()
1020 {
1021 if (node_)
1022 node_->incr_count(strength_);
1023 }
1024 inline void unbind()
1025 {
1026 if (node_) {
1027 if(strength_ == RCP_STRONG) {
1028 // only strong checks for --strong == 0
1029 if (node_->deincr_count(RCP_STRONG) == 0) {
1030 unbindOneStrong();
1031 // but if strong hits 0 it also decrements weak_count_plus which
1032 // is weak + (strong != 0)
1033 if( node_->deincr_count(RCP_WEAK) == 0) {
1034 unbindOneTotal();
1035 }
1036 }
1037 }
1038 else if(node_->deincr_count(RCP_WEAK) == 0) { // weak checks here
1039 unbindOneTotal();
1040 }
1041 }
1042 }
1043 void unbindOneStrong();
1044 void unbindOneTotal();
1045};
1046
1047
1052inline
1053std::ostream& operator<<(std::ostream& out, const RCPNodeHandle& node)
1054{
1055 // mfh 15 Sep 2015: Make sure that NULL pointers print consistently.
1056 // Clang 3.5 likes to print an empty string in that case, while GCC
1057 // prints 0. Thus, we test if the pointer is NULL and print 0 in
1058 // that case. This is important for MueLu tests, which compare
1059 // string print-outs.
1060 if (node.node_ptr () == NULL) {
1061 out << "0";
1062 } else {
1063 out << node.node_ptr ();
1064 }
1065 return out;
1066}
1067
1068
1078class TEUCHOSCORE_LIB_DLL_EXPORT RCPNodeThrowDeleter {
1079public:
1082 : node_(node)
1083 {}
1090 {
1091 if (node_) {
1092 node_->has_ownership(false); // Avoid actually deleting ptr_
1093 node_->delete_obj(); // Sets the pointer ptr_=0 to allow RCPNode delete
1094 delete node_;
1095 }
1096 }
1098 RCPNode* get() const
1099 {
1100 return node_;
1101 }
1103 void release()
1104 {
1105 node_ = 0;
1106 }
1107private:
1108 RCPNode *node_;
1109 RCPNodeThrowDeleter(); // Not defined
1110 RCPNodeThrowDeleter(const RCPNodeThrowDeleter&); // Not defined
1111 RCPNodeThrowDeleter& operator=(const RCPNodeThrowDeleter&); // Not defined
1112};
1113
1114
1115//
1116// Unit testing support
1117//
1118
1119
1120#if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1121
1122class SetTracingActiveNodesStack {
1123public:
1124 SetTracingActiveNodesStack()
1125 {RCPNodeTracer::setTracingActiveRCPNodes(true);}
1126 ~SetTracingActiveNodesStack()
1127 {RCPNodeTracer::setTracingActiveRCPNodes(false);}
1128};
1129
1130# define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack;
1131
1132#else
1133
1134# define SET_RCPNODE_TRACING() (void)0
1135
1136#endif // defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING)
1137
1138
1139} // end namespace Teuchos
1140
1141
1142#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.
Dangling reference error exception class.
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 std::string getCommonDebugNotesString()
Common error message string on how to debug RCPNode problems.
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_MSG(throw_exception_test, msg)
This macro is designed to be a short version of TEUCHOS_TEST_FOR_EXCEPTION() that is easier to call.
#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)