|
Teuchos - Trilinos Tools Package Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Teuchos: Common Tools Package 00005 // Copyright (2004) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 // @HEADER 00041 00042 #ifndef TEUCHOS_RCP_NODE_HPP 00043 #define TEUCHOS_RCP_NODE_HPP 00044 00045 00052 #include "Teuchos_ConfigDefs.hpp" 00053 #include "Teuchos_any.hpp" 00054 #include "Teuchos_map.hpp" 00055 #include "Teuchos_ENull.hpp" 00056 #include "Teuchos_Assert.hpp" 00057 #include "Teuchos_Exceptions.hpp" 00058 #include "Teuchos_TypeNameTraits.hpp" 00059 #include "Teuchos_toString.hpp" 00060 #include "Teuchos_getBaseObjVoidPtr.hpp" 00061 00062 00063 namespace Teuchos { 00064 00065 00070 enum EPrePostDestruction { PRE_DESTROY, POST_DESTROY }; 00071 00076 enum ERCPStrength { RCP_STRENGTH_INVALID=-1, RCP_STRONG=0, RCP_WEAK=1 }; 00077 00082 enum ERCPNodeLookup { RCP_ENABLE_NODE_LOOKUP, RCP_DISABLE_NODE_LOOKUP }; 00083 00085 inline void debugAssertStrength(ERCPStrength strength) 00086 { 00087 #ifdef TEUCHOS_DEBUG 00088 switch (strength) { 00089 case RCP_STRONG: 00090 // fall through 00091 case RCP_WEAK: 00092 return; // Fine 00093 case RCP_STRENGTH_INVALID: 00094 default: 00095 TEUCHOS_TEST_FOR_EXCEPT(true); 00096 } 00097 #endif 00098 } 00099 00105 template<> 00106 class TEUCHOS_LIB_DLL_EXPORT ToStringTraits<ERCPStrength> { 00107 public: 00108 static std::string toString( const ERCPStrength &t ) 00109 { 00110 switch (t) { 00111 case RCP_STRENGTH_INVALID: 00112 return "RCP_STRENGTH_INVALID"; 00113 case RCP_STRONG: 00114 return "RCP_STRONG"; 00115 case RCP_WEAK: 00116 return "RCP_WEAK"; 00117 default: 00118 // Should never get here but fall through ... 00119 break; 00120 } 00121 // Should never get here! 00122 #ifdef TEUCHOS_DEBUG 00123 TEUCHOS_TEST_FOR_EXCEPT(true); 00124 #endif 00125 return ""; 00126 // 2009/06/30: rabartl: The above logic avoid a warning from the Intel 00127 // 10.1 compiler (remark #111) about the statement being unreachable. 00128 } 00129 }; 00130 00131 00143 class TEUCHOS_LIB_DLL_EXPORT RCPNode { 00144 public: 00146 RCPNode(bool has_ownership_in) 00147 : has_ownership_(has_ownership_in), extra_data_map_(NULL) 00148 #ifdef TEUCHOS_DEBUG 00149 ,insertion_number_(-1) 00150 #endif // TEUCHOS_DEBUG 00151 { 00152 count_[RCP_STRONG] = 0; 00153 count_[RCP_WEAK] = 0; 00154 } 00156 virtual ~RCPNode() 00157 { 00158 if(extra_data_map_) 00159 delete extra_data_map_; 00160 } 00162 int strong_count() const 00163 { 00164 return count_[RCP_STRONG]; 00165 } 00167 int weak_count() const 00168 { 00169 return count_[RCP_WEAK]; 00170 } 00172 int count( const ERCPStrength strength ) 00173 { 00174 debugAssertStrength(strength); 00175 return count_[strength]; 00176 } 00178 int incr_count( const ERCPStrength strength ) 00179 { 00180 debugAssertStrength(strength); 00181 return ++count_[strength]; 00182 } 00184 int deincr_count( const ERCPStrength strength ) 00185 { 00186 debugAssertStrength(strength); 00187 return --count_[strength]; 00188 } 00190 void has_ownership(bool has_ownership_in) 00191 { 00192 has_ownership_ = has_ownership_in; 00193 } 00195 bool has_ownership() const 00196 { 00197 return has_ownership_; 00198 } 00200 void set_extra_data( 00201 const any &extra_data, const std::string& name, 00202 EPrePostDestruction destroy_when, bool force_unique ); 00204 any& get_extra_data( const std::string& type_name, 00205 const std::string& name ); 00207 const any& get_extra_data( const std::string& type_name, 00208 const std::string& name 00209 ) const 00210 { 00211 return const_cast<RCPNode*>(this)->get_extra_data(type_name, name); 00212 } 00214 any* get_optional_extra_data(const std::string& type_name, 00215 const std::string& name ); 00217 const any* get_optional_extra_data( 00218 const std::string& type_name, const std::string& name 00219 ) const 00220 { 00221 return const_cast<RCPNode*>(this)->get_optional_extra_data(type_name, name); 00222 } 00224 virtual bool is_valid_ptr() const = 0; 00226 virtual void delete_obj() = 0; 00228 virtual void throw_invalid_obj_exception( 00229 const std::string& rcp_type_name, 00230 const void* rcp_ptr, 00231 const RCPNode* rcp_node_ptr, 00232 const void* rcp_obj_ptr 00233 ) const = 0; 00235 virtual const std::string get_base_obj_type_name() const = 0; 00236 #ifdef TEUCHOS_DEBUG 00237 00238 virtual const void* get_base_obj_map_key_void_ptr() const = 0; 00239 #endif 00240 protected: 00242 void pre_delete_extra_data() 00243 { 00244 if(extra_data_map_) 00245 impl_pre_delete_extra_data(); 00246 } 00247 private: 00248 struct extra_data_entry_t { 00249 extra_data_entry_t() : destroy_when(POST_DESTROY) {} 00250 extra_data_entry_t( const any &_extra_data, EPrePostDestruction _destroy_when ) 00251 : extra_data(_extra_data), destroy_when(_destroy_when) 00252 {} 00253 any extra_data; 00254 EPrePostDestruction destroy_when; 00255 }; 00256 typedef Teuchos::map<std::string,extra_data_entry_t> extra_data_map_t; 00257 int count_[2]; 00258 bool has_ownership_; 00259 extra_data_map_t *extra_data_map_; 00260 // Above is made a pointer to reduce overhead for the general case when this 00261 // is not used. However, this adds just a little bit to the overhead when 00262 // it is used. 00263 // Provides the "basic" guarantee! 00264 void impl_pre_delete_extra_data(); 00265 // Not defined and not to be called 00266 RCPNode(); 00267 RCPNode(const RCPNode&); 00268 RCPNode& operator=(const RCPNode&); 00269 #ifdef TEUCHOS_DEBUG 00270 int insertion_number_; 00271 public: 00272 void set_insertion_number(int insertion_number_in) 00273 { 00274 insertion_number_ = insertion_number_in; 00275 } 00276 int insertion_number() const 00277 { 00278 return insertion_number_; 00279 } 00280 #endif // TEUCHOS_DEBUG 00281 }; 00282 00283 00288 TEUCHOS_LIB_DLL_EXPORT void throw_null_ptr_error( const std::string &type_name ); 00289 00290 00307 class TEUCHOS_LIB_DLL_EXPORT RCPNodeTracer { 00308 public: 00309 00312 00314 struct RCPNodeStatistics { 00315 RCPNodeStatistics() 00316 : maxNumRCPNodes(0), totalNumRCPNodeAllocations(0), 00317 totalNumRCPNodeDeletions(0) 00318 {} 00319 long int maxNumRCPNodes; 00320 long int totalNumRCPNodeAllocations; 00321 long int totalNumRCPNodeDeletions; 00322 }; 00323 00325 00328 00334 static bool isTracingActiveRCPNodes(); 00335 00336 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 00337 00354 static void setTracingActiveRCPNodes(bool tracingActiveNodes); 00355 #endif 00356 00360 static int numActiveRCPNodes(); 00361 00363 static RCPNodeStatistics getRCPNodeStatistics() ; 00364 00366 static void printRCPNodeStatistics( 00367 const RCPNodeStatistics& rcpNodeStatistics, std::ostream &out); 00368 00372 static void setPrintRCPNodeStatisticsOnExit( 00373 bool printRCPNodeStatisticsOnExit); 00374 00378 static bool getPrintRCPNodeStatisticsOnExit(); 00379 00394 static void printActiveRCPNodes(std::ostream &out); 00395 00397 00402 00407 static void addNewRCPNode(RCPNode* rcp_node, 00408 const std::string &info ); 00409 00415 static void removeRCPNode( RCPNode* rcp_node ); 00416 00425 template<class T> 00426 static const void* getRCPNodeBaseObjMapKeyVoidPtr(T *p) 00427 { 00428 #ifdef HAS_TEUCHOS_GET_BASE_OBJ_VOID_PTR 00429 return getBaseObjVoidPtr(p); 00430 #else 00431 // This will not return the base address for polymorphic types if 00432 // multiple inheritance and/or virtual bases are used but returning the 00433 // static_cast should be okay in how it is used. It is just that the 00434 // RCPNode tracing support will not always be able to figure out if two 00435 // pointers of different type are pointing to the same object or not. 00436 return static_cast<const void*>(p); 00437 #endif 00438 } 00439 00446 static RCPNode* getExistingRCPNodeGivenLookupKey( 00447 const void* lookupKey); 00448 00455 template<class T> 00456 static RCPNode* getExistingRCPNode(T *p) 00457 { 00458 return getExistingRCPNodeGivenLookupKey(getRCPNodeBaseObjMapKeyVoidPtr(p)); 00459 } 00460 00462 static std::string getActiveRCPNodeHeaderString(); 00463 00465 static std::string getCommonDebugNotesString(); 00466 00468 00469 }; 00470 00471 00472 #ifdef TEUCHOS_DEBUG 00473 # define TEUCHOS_RCP_INSERION_NUMBER_STR() \ 00474 " insertionNumber: " << rcp_node_ptr->insertion_number() << "\n" 00475 #else 00476 # define TEUCHOS_RCP_INSERION_NUMBER_STR() 00477 #endif 00478 00479 00485 template<class T, class Dealloc_T> 00486 class RCPNodeTmpl : public RCPNode { 00487 public: 00489 RCPNodeTmpl(T* p, Dealloc_T dealloc, bool has_ownership_in) 00490 : RCPNode(has_ownership_in), ptr_(p), 00491 #ifdef TEUCHOS_DEBUG 00492 base_obj_map_key_void_ptr_(RCPNodeTracer::getRCPNodeBaseObjMapKeyVoidPtr(p)), 00493 deleted_ptr_(0), 00494 #endif 00495 dealloc_(dealloc) 00496 {} 00498 RCPNodeTmpl(T* p, Dealloc_T dealloc, bool has_ownership_in, ENull) 00499 : RCPNode(has_ownership_in), ptr_(p), 00500 #ifdef TEUCHOS_DEBUG 00501 base_obj_map_key_void_ptr_(0), 00502 deleted_ptr_(0), 00503 #endif 00504 dealloc_(dealloc) 00505 {} 00507 Dealloc_T& get_nonconst_dealloc() 00508 { return dealloc_; } 00510 const Dealloc_T& get_dealloc() const 00511 { return dealloc_; } 00513 ~RCPNodeTmpl() 00514 { 00515 #ifdef TEUCHOS_DEBUG 00516 TEUCHOS_TEST_FOR_EXCEPTION( ptr_!=0, std::logic_error, 00517 "Error, the underlying object must be explicitly deleted before deleting" 00518 " the node object!" ); 00519 #endif 00520 } 00522 virtual bool is_valid_ptr() const 00523 { 00524 return ptr_ != 0; 00525 } 00531 virtual void delete_obj() 00532 { 00533 if (ptr_!= 0) { 00534 this->pre_delete_extra_data(); // May throw! 00535 T* tmp_ptr = ptr_; 00536 #ifdef TEUCHOS_DEBUG 00537 deleted_ptr_ = tmp_ptr; 00538 #endif 00539 ptr_ = 0; 00540 if (has_ownership()) { 00541 #ifdef TEUCHOS_DEBUG 00542 try { 00543 #endif 00544 dealloc_.free(tmp_ptr); 00545 #ifdef TEUCHOS_DEBUG 00546 } 00547 catch(...) { 00548 // Object was not deleted due to an exception! 00549 ptr_ = tmp_ptr; 00550 throw; 00551 } 00552 #endif 00553 } 00554 // 2008/09/22: rabartl: Above, we have to be careful to set the member 00555 // this->ptr_=0 before calling delete on the object's address in order 00556 // to avoid a double call to delete in cases of circular references 00557 // involving weak and strong pointers (see the unit test 00558 // circularReference_c_then_a in RCP_UnitTests.cpp). NOTE: It is 00559 // critcial that no member of *this get accesses after 00560 // dealloc_.free(...) gets called! Also, in order to provide the 00561 // "strong" guarantee we have to include the above try/catch. This 00562 // overhead is unfortunate but I don't know of any other way to 00563 // statisfy the "strong" guarantee and still avoid a double delete. 00564 } 00565 } 00567 virtual void throw_invalid_obj_exception( 00568 const std::string& rcp_type_name, 00569 const void* rcp_ptr, 00570 const RCPNode* rcp_node_ptr, 00571 const void* rcp_obj_ptr 00572 ) const 00573 { 00574 TEUCHOS_TEST_FOR_EXCEPT_MSG( ptr_!=0, "Internal coding error!" ); 00575 const T* deleted_ptr = 00576 #ifdef TEUCHOS_DEBUG 00577 deleted_ptr_ 00578 #else 00579 0 00580 #endif 00581 ; 00582 TEUCHOS_ASSERT(rcp_node_ptr); 00583 TEUCHOS_TEST_FOR_EXCEPTION( true, DanglingReferenceError, 00584 "Error, an attempt has been made to dereference the underlying object\n" 00585 "from a weak smart pointer object where the underling object has already\n" 00586 "been deleted since the strong count has already gone to zero.\n" 00587 "\n" 00588 "Context information:\n" 00589 "\n" 00590 " RCP type: " << rcp_type_name << "\n" 00591 " RCP address: " << rcp_ptr << "\n" 00592 " RCPNode type: " << typeName(*this) << "\n" 00593 " RCPNode address: " << rcp_node_ptr << "\n" 00594 TEUCHOS_RCP_INSERION_NUMBER_STR() 00595 " RCP ptr address: " << rcp_obj_ptr << "\n" 00596 " Concrete ptr address: " << deleted_ptr << "\n" 00597 "\n" 00598 << RCPNodeTracer::getCommonDebugNotesString() 00599 ); 00600 // 2008/09/22: rabartl: Above, we do not provide the concreate object 00601 // type or the concrete object address. In the case of the concrete 00602 // object address, in a non-debug build, we don't want to pay a price 00603 // for extra storage that we strictly don't need. In the case of the 00604 // concrete object type name, we don't want to force non-debug built 00605 // code to have the require that types be fully defined in order to use 00606 // the memory management software. This is related to bug 4016. 00607 00608 } 00610 const std::string get_base_obj_type_name() const 00611 { 00612 #ifdef TEUCHOS_DEBUG 00613 return TypeNameTraits<T>::name(); 00614 #else 00615 return "UnknownType"; 00616 #endif 00617 } 00618 #ifdef TEUCHOS_DEBUG 00619 00620 const void* get_base_obj_map_key_void_ptr() const 00621 { 00622 return base_obj_map_key_void_ptr_; 00623 } 00624 #endif 00625 private: 00626 T *ptr_; 00627 #ifdef TEUCHOS_DEBUG 00628 const void *base_obj_map_key_void_ptr_; 00629 T *deleted_ptr_; 00630 #endif 00631 Dealloc_T dealloc_; 00632 // not defined and not to be called 00633 RCPNodeTmpl(); 00634 RCPNodeTmpl(const RCPNodeTmpl&); 00635 RCPNodeTmpl& operator=(const RCPNodeTmpl&); 00636 00637 }; // end class RCPNodeTmpl<T> 00638 00639 00647 class TEUCHOS_LIB_DLL_EXPORT ActiveRCPNodesSetup { 00648 public: 00650 ActiveRCPNodesSetup(); 00652 ~ActiveRCPNodesSetup(); 00654 void foo(); 00655 private: 00656 static int count_; 00657 }; 00658 00659 00660 } // namespace Teuchos 00661 00662 00663 namespace { 00664 // This static variable is delcared before all other static variables that 00665 // depend on RCP or other classes. Therefore, this static varaible will be 00666 // deleted *after* all of these other static variables that depend on RCP or 00667 // created classes go away! This ensures that the node tracing machinery is 00668 // setup and torn down correctly (this is the same trick used by the standard 00669 // stream objects in many compiler implementations). 00670 Teuchos::ActiveRCPNodesSetup local_activeRCPNodesSetup; 00671 } // namespace 00672 00673 00674 namespace Teuchos { 00675 00676 00692 class TEUCHOS_LIB_DLL_EXPORT RCPNodeHandle { 00693 public: 00695 RCPNodeHandle(ENull null_arg = null) 00696 : node_(0), strength_(RCP_STRENGTH_INVALID) 00697 {(void)null_arg;} 00699 RCPNodeHandle( RCPNode* node, ERCPStrength strength_in = RCP_STRONG, 00700 bool newNode = true 00701 ) 00702 : node_(node), strength_(strength_in) 00703 { 00704 #ifdef TEUCHOS_DEBUG 00705 TEUCHOS_ASSERT(node); 00706 #endif 00707 bind(); 00708 #ifdef TEUCHOS_DEBUG 00709 // Add the node if this is the first RCPNodeHandle to get it. We have 00710 // to add it because unbind() will call the remove_RCPNode(...) function 00711 // and it needs to match when node tracing is on from the beginning. 00712 if (RCPNodeTracer::isTracingActiveRCPNodes() && newNode) 00713 { 00714 std::ostringstream os; 00715 os << "{T=Unknown, ConcreteT=Unknown, p=Unknown," 00716 << " has_ownership="<<node_->has_ownership()<<"}"; 00717 RCPNodeTracer::addNewRCPNode(node_, os.str()); 00718 } 00719 #endif 00720 } 00721 #ifdef TEUCHOS_DEBUG 00722 00723 template<typename T> 00724 RCPNodeHandle(RCPNode* node, T *p, const std::string &T_name, 00725 const std::string &ConcreteT_name, const bool has_ownership_in, 00726 ERCPStrength strength_in = RCP_STRONG 00727 ) 00728 : node_(node), strength_(strength_in) 00729 { 00730 TEUCHOS_ASSERT(strength_in == RCP_STRONG); // Can't handle weak yet! 00731 TEUCHOS_ASSERT(node_); 00732 bind(); 00733 if (RCPNodeTracer::isTracingActiveRCPNodes()) { 00734 std::ostringstream os; 00735 os << "{T="<<T_name<<", ConcreteT="<< ConcreteT_name 00736 <<", p="<<static_cast<const void*>(p) 00737 <<", has_ownership="<<has_ownership_in<<"}"; 00738 RCPNodeTracer::addNewRCPNode(node_, os.str()); 00739 } 00740 } 00741 #endif // TEUCHOS_DEBUG 00742 00743 RCPNodeHandle(const RCPNodeHandle& node_ref) 00744 : node_(node_ref.node_), strength_(node_ref.strength_) 00745 { 00746 bind(); 00747 } 00749 void swap( RCPNodeHandle& node_ref ) 00750 { 00751 std::swap(node_ref.node_, node_); 00752 std::swap(node_ref.strength_, strength_); 00753 } 00755 RCPNodeHandle& operator=(const RCPNodeHandle& node_ref) 00756 { 00757 // Assignment to self check: Note, We don't need to do an assigment to 00758 // self check here because such a check is already done in the RCP and 00759 // ArrayRCP classes. 00760 // Take care of this's existing node and object 00761 unbind(); // May throw in some cases 00762 // Assign the new node 00763 node_ = node_ref.node_; 00764 strength_ = node_ref.strength_; 00765 bind(); 00766 // Return 00767 return *this; 00768 } 00770 ~RCPNodeHandle() 00771 { 00772 unbind(); 00773 } 00775 RCPNodeHandle create_weak() const 00776 { 00777 if (node_) { 00778 return RCPNodeHandle(node_, RCP_WEAK, false); 00779 } 00780 return RCPNodeHandle(); 00781 } 00783 RCPNodeHandle create_strong() const 00784 { 00785 if (node_) { 00786 return RCPNodeHandle(node_, RCP_STRONG, false); 00787 } 00788 return RCPNodeHandle(); 00789 } 00791 RCPNode* node_ptr() const 00792 { 00793 return node_; 00794 } 00796 bool is_node_null() const 00797 { 00798 return node_==0; 00799 } 00801 bool is_valid_ptr() const 00802 { 00803 if (node_) 00804 return node_->is_valid_ptr(); 00805 return true; // Null is a valid ptr! 00806 } 00808 bool same_node(const RCPNodeHandle &node2) const 00809 { 00810 return node_ == node2.node_; 00811 } 00813 int strong_count() const 00814 { 00815 if (node_) 00816 return node_->strong_count(); 00817 return 0; 00818 } 00820 int weak_count() const 00821 { 00822 if (node_) 00823 return node_->weak_count(); 00824 return 0; 00825 } 00827 int total_count() const 00828 { 00829 if (node_) 00830 return node_->strong_count() + node_->weak_count(); 00831 return 0; 00832 } 00834 int count() const 00835 { 00836 if (node_) 00837 return node_->strong_count(); 00838 return 0; 00839 } 00841 ERCPStrength strength() const 00842 { 00843 return strength_; 00844 } 00846 void has_ownership(bool has_ownership_in) 00847 { 00848 if (node_) 00849 node_->has_ownership(has_ownership_in); 00850 } 00852 bool has_ownership() const 00853 { 00854 if (node_) 00855 return node_->has_ownership(); 00856 return false; 00857 } 00859 void set_extra_data( 00860 const any &extra_data, const std::string& name, 00861 EPrePostDestruction destroy_when, bool force_unique 00862 ) 00863 { 00864 debug_assert_not_null(); 00865 node_->set_extra_data(extra_data, name, destroy_when, force_unique); 00866 } 00868 any& get_extra_data( const std::string& type_name, 00869 const std::string& name 00870 ) 00871 { 00872 debug_assert_not_null(); 00873 return node_->get_extra_data(type_name, name); 00874 } 00876 const any& get_extra_data( const std::string& type_name, 00877 const std::string& name 00878 ) const 00879 { 00880 return const_cast<RCPNodeHandle*>(this)->get_extra_data(type_name, name); 00881 } 00883 any* get_optional_extra_data( 00884 const std::string& type_name, const std::string& name 00885 ) 00886 { 00887 debug_assert_not_null(); 00888 return node_->get_optional_extra_data(type_name, name); 00889 } 00891 const any* get_optional_extra_data( 00892 const std::string& type_name, const std::string& name 00893 ) const 00894 { 00895 return const_cast<RCPNodeHandle*>(this)->get_optional_extra_data(type_name, name); 00896 } 00898 void debug_assert_not_null() const 00899 { 00900 #ifdef TEUCHOS_DEBUG 00901 if (!node_) 00902 throw_null_ptr_error(typeName(*this)); 00903 #endif 00904 } 00906 template<class RCPType> 00907 void assert_valid_ptr(const RCPType& rcp_obj) const 00908 { 00909 if (!node_) 00910 return; // Null is a valid pointer! 00911 if (!is_valid_ptr()) { 00912 node_->throw_invalid_obj_exception( typeName(rcp_obj), 00913 this, node_, rcp_obj.access_private_ptr() ); 00914 } 00915 } 00917 template<class RCPType> 00918 void debug_assert_valid_ptr(const RCPType& rcp_obj) const 00919 { 00920 #ifdef TEUCHOS_DEBUG 00921 assert_valid_ptr(rcp_obj); 00922 #endif 00923 } 00924 #ifdef TEUCHOS_DEBUG 00925 const void* get_base_obj_map_key_void_ptr() const 00926 { 00927 if (node_) 00928 return node_->get_base_obj_map_key_void_ptr(); 00929 return 0; 00930 } 00931 #endif 00932 private: 00933 RCPNode *node_; 00934 ERCPStrength strength_; 00935 inline void bind() 00936 { 00937 if (node_) 00938 node_->incr_count(strength_); 00939 } 00940 inline void unbind() 00941 { 00942 // Optimize this implementation for count > 1 00943 if (node_ && node_->deincr_count(strength_)==0) { 00944 // If we get here, the reference count has gone to 0 and something 00945 // interesting is going to happen. In this case, we need to 00946 // reincrement the count back to 1 and call the more complex function 00947 // that will either delete the object or delete the node. 00948 node_->incr_count(strength_); 00949 unbindOne(); 00950 } 00951 // If we get here, either node_==0 or the count is still greater than 0. 00952 // In this case, nothing interesting is going to happen so we are done! 00953 } 00954 void unbindOne(); // Provides the "strong" guarantee! 00955 00956 }; 00957 00958 00963 inline 00964 std::ostream& operator<<(std::ostream& out, const RCPNodeHandle& node) 00965 { 00966 return (out << node.node_ptr()); 00967 } 00968 00969 00979 class TEUCHOS_LIB_DLL_EXPORT RCPNodeThrowDeleter { 00980 public: 00982 RCPNodeThrowDeleter(RCPNode *node) 00983 : node_(node) 00984 {} 00990 ~RCPNodeThrowDeleter() 00991 { 00992 if (node_) { 00993 node_->has_ownership(false); // Avoid actually deleting ptr_ 00994 node_->delete_obj(); // Sets the pointer ptr_=0 to allow RCPNode delete 00995 delete node_; 00996 } 00997 } 00999 RCPNode* get() const 01000 { 01001 return node_; 01002 } 01004 void release() 01005 { 01006 node_ = 0; 01007 } 01008 private: 01009 RCPNode *node_; 01010 RCPNodeThrowDeleter(); // Not defined 01011 RCPNodeThrowDeleter(const RCPNodeThrowDeleter&); // Not defined 01012 RCPNodeThrowDeleter& operator=(const RCPNodeThrowDeleter&); // Not defined 01013 }; 01014 01015 01016 // 01017 // Unit testing support 01018 // 01019 01020 01021 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 01022 01023 class SetTracingActiveNodesStack { 01024 public: 01025 SetTracingActiveNodesStack() 01026 {RCPNodeTracer::setTracingActiveRCPNodes(true);} 01027 ~SetTracingActiveNodesStack() 01028 {RCPNodeTracer::setTracingActiveRCPNodes(false);} 01029 }; 01030 01031 # define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack; 01032 01033 #else 01034 01035 # define SET_RCPNODE_TRACING() (void)0 01036 01037 #endif // defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 01038 01039 01040 } // end namespace Teuchos 01041 01042 01043 #endif // TEUCHOS_RCP_NODE_HPP
1.7.4