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.
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.
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...
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
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-...
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)