|
Teuchos Package Browser (Single Doxygen Collection)
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_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 default: 00094 TEUCHOS_TEST_FOR_EXCEPTION( 00095 true, std::logic_error, "Teuchos::RCPNode: ERCPStrength enum value " 00096 << strength << " is invalid (neither RCP_STRONG = " << RCP_STRONG 00097 << " nor RCP_WEAK = " << RCP_WEAK << ")."); 00098 } 00099 #else 00100 (void) strength; // Silence "unused variable" compiler warning. 00101 #endif // TEUCHOS_DEBUG 00102 } 00103 00109 template<> 00110 class TEUCHOSCORE_LIB_DLL_EXPORT ToStringTraits<ERCPStrength> { 00111 public: 00112 static std::string toString( const ERCPStrength &t ) 00113 { 00114 switch (t) { 00115 case RCP_STRONG: 00116 return "RCP_STRONG"; 00117 case RCP_WEAK: 00118 return "RCP_WEAK"; 00119 default: 00120 // Should never get here but fall through ... 00121 break; 00122 } 00123 // Should never get here! 00124 #ifdef TEUCHOS_DEBUG 00125 TEUCHOS_TEST_FOR_EXCEPT(true); 00126 #endif 00127 return ""; 00128 // 2009/06/30: rabartl: The above logic avoid a warning from the Intel 00129 // 10.1 compiler (remark #111) about the statement being unreachable. 00130 // 00131 // mfh (06 Mar 2013) This triggers a warning in Clang 3.2 with 00132 // "-Weverything", because it's an unreachable statement. Alas, 00133 // we can't please _all_ the compilers equally... 00134 } 00135 }; 00136 00137 00149 class TEUCHOSCORE_LIB_DLL_EXPORT RCPNode { 00150 public: 00152 RCPNode(bool has_ownership_in) 00153 : has_ownership_(has_ownership_in), extra_data_map_(NULL) 00154 #ifdef TEUCHOS_DEBUG 00155 ,insertion_number_(-1) 00156 #endif // TEUCHOS_DEBUG 00157 { 00158 count_[RCP_STRONG] = 0; 00159 count_[RCP_WEAK] = 0; 00160 } 00162 virtual ~RCPNode() 00163 { 00164 if(extra_data_map_) 00165 delete extra_data_map_; 00166 } 00168 int strong_count() const 00169 { 00170 return count_[RCP_STRONG]; 00171 } 00173 int weak_count() const 00174 { 00175 return count_[RCP_WEAK]; 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 TEUCHOSCORE_LIB_DLL_EXPORT void throw_null_ptr_error( const std::string &type_name ); 00289 00290 00307 class TEUCHOSCORE_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 TEUCHOSCORE_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 declared before all other static variables that 00665 // depend on RCP or other classes. Therefore, this static variable 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 (anonymous) 00672 00673 00674 namespace Teuchos { 00675 00692 class TEUCHOSCORE_LIB_DLL_EXPORT RCPNodeHandle { 00693 public: 00695 RCPNodeHandle (ENull null_arg = null) 00696 : node_ (0), strength_ (RCP_STRONG) 00697 { 00698 (void) null_arg; // Silence "unused variable" compiler warning. 00699 } 00700 00702 RCPNodeHandle (RCPNode* node, 00703 ERCPStrength strength_in = RCP_STRONG, 00704 bool newNode = true) 00705 : node_ (node), strength_ (strength_in) 00706 { 00707 #ifdef TEUCHOS_DEBUG 00708 TEUCHOS_ASSERT(node); 00709 #endif // TEUCHOS_DEBUG 00710 00711 bind(); 00712 00713 #ifdef TEUCHOS_DEBUG 00714 // Add the node if this is the first RCPNodeHandle to get it. We have 00715 // to add it because unbind() will call the remove_RCPNode(...) function 00716 // and it needs to match when node tracing is on from the beginning. 00717 if (RCPNodeTracer::isTracingActiveRCPNodes() && newNode) { 00718 std::ostringstream os; 00719 os << "{T=Unknown, ConcreteT=Unknown, p=Unknown," 00720 << " has_ownership="<<node_->has_ownership()<<"}"; 00721 RCPNodeTracer::addNewRCPNode(node_, os.str()); 00722 } 00723 #else 00724 (void) newNode; // Silence "unused variable" compiler warning. 00725 #endif // TEUCHOS_DEBUG 00726 } 00727 00728 #ifdef TEUCHOS_DEBUG 00729 00730 template<typename T> 00731 RCPNodeHandle (RCPNode* node, T *p, const std::string &T_name, 00732 const std::string &ConcreteT_name, 00733 const bool has_ownership_in, 00734 ERCPStrength strength_in = RCP_STRONG) 00735 : node_ (node), strength_ (strength_in) 00736 { 00737 TEUCHOS_ASSERT(strength_in == RCP_STRONG); // Can't handle weak yet! 00738 TEUCHOS_ASSERT(node_); 00739 bind(); 00740 if (RCPNodeTracer::isTracingActiveRCPNodes()) { 00741 std::ostringstream os; 00742 os << "{T="<<T_name<<", ConcreteT="<< ConcreteT_name 00743 <<", p="<<static_cast<const void*>(p) 00744 <<", has_ownership="<<has_ownership_in<<"}"; 00745 RCPNodeTracer::addNewRCPNode(node_, os.str()); 00746 } 00747 } 00748 #endif // TEUCHOS_DEBUG 00749 00751 RCPNodeHandle (const RCPNodeHandle& node_ref) 00752 : node_ (node_ref.node_), strength_ (node_ref.strength_) 00753 { 00754 bind(); 00755 } 00756 00758 void swap (RCPNodeHandle& node_ref) { 00759 std::swap (node_ref.node_, node_); 00760 std::swap (node_ref.strength_, strength_); 00761 } 00762 00768 RCPNodeHandle& operator= (const RCPNodeHandle& node_ref) { 00769 // Assignment to self check: Note, We don't need to do an assigment to 00770 // self check here because such a check is already done in the RCP and 00771 // ArrayRCP classes. 00772 // Take care of this's existing node and object 00773 unbind(); // May throw in some cases 00774 // Assign the new node 00775 node_ = node_ref.node_; 00776 strength_ = node_ref.strength_; 00777 bind(); 00778 // Return 00779 return *this; 00780 } 00781 00783 ~RCPNodeHandle() { 00784 unbind(); 00785 } 00786 00788 RCPNodeHandle create_weak() const { 00789 if (node_) { 00790 return RCPNodeHandle(node_, RCP_WEAK, false); 00791 } 00792 return RCPNodeHandle(); 00793 } 00795 RCPNodeHandle create_strong() const { 00796 if (node_) { 00797 return RCPNodeHandle(node_, RCP_STRONG, false); 00798 } 00799 return RCPNodeHandle(); 00800 } 00802 RCPNode* node_ptr() const { 00803 return node_; 00804 } 00806 bool is_node_null() const { 00807 return node_==0; 00808 } 00812 bool is_valid_ptr() const { 00813 if (node_) { 00814 return node_->is_valid_ptr(); 00815 } 00816 return true; // Null is a valid ptr! 00817 } 00820 bool same_node(const RCPNodeHandle &node2) const { 00821 return node_ == node2.node_; 00822 } 00824 int strong_count() const { 00825 if (node_) { 00826 return node_->strong_count(); 00827 } 00828 return 0; 00829 } 00831 int weak_count() const { 00832 if (node_) { 00833 return node_->weak_count(); 00834 } 00835 return 0; 00836 } 00838 int total_count() const { 00839 if (node_) { 00840 return node_->strong_count() + node_->weak_count(); 00841 } 00842 return 0; 00843 } 00845 int count() const { 00846 if (node_) { 00847 return node_->strong_count(); 00848 } 00849 return 0; 00850 } 00852 ERCPStrength strength() const { 00853 return strength_; 00854 } 00856 void has_ownership(bool has_ownership_in) 00857 { 00858 if (node_) 00859 node_->has_ownership(has_ownership_in); 00860 } 00862 bool has_ownership() const 00863 { 00864 if (node_) 00865 return node_->has_ownership(); 00866 return false; 00867 } 00869 void set_extra_data( 00870 const any &extra_data, const std::string& name, 00871 EPrePostDestruction destroy_when, bool force_unique 00872 ) 00873 { 00874 debug_assert_not_null(); 00875 node_->set_extra_data(extra_data, name, destroy_when, force_unique); 00876 } 00878 any& get_extra_data( const std::string& type_name, 00879 const std::string& name 00880 ) 00881 { 00882 debug_assert_not_null(); 00883 return node_->get_extra_data(type_name, name); 00884 } 00886 const any& get_extra_data( const std::string& type_name, 00887 const std::string& name 00888 ) const 00889 { 00890 return const_cast<RCPNodeHandle*>(this)->get_extra_data(type_name, name); 00891 } 00893 any* get_optional_extra_data( 00894 const std::string& type_name, const std::string& name 00895 ) 00896 { 00897 debug_assert_not_null(); 00898 return node_->get_optional_extra_data(type_name, name); 00899 } 00901 const any* get_optional_extra_data( 00902 const std::string& type_name, const std::string& name 00903 ) const 00904 { 00905 return const_cast<RCPNodeHandle*>(this)->get_optional_extra_data(type_name, name); 00906 } 00908 void debug_assert_not_null() const 00909 { 00910 #ifdef TEUCHOS_DEBUG 00911 if (!node_) 00912 throw_null_ptr_error(typeName(*this)); 00913 #endif 00914 } 00916 template<class RCPType> 00917 void assert_valid_ptr(const RCPType& rcp_obj) const 00918 { 00919 if (!node_) 00920 return; // Null is a valid pointer! 00921 if (!is_valid_ptr()) { 00922 node_->throw_invalid_obj_exception( typeName(rcp_obj), 00923 this, node_, rcp_obj.access_private_ptr() ); 00924 } 00925 } 00927 template<class RCPType> 00928 void debug_assert_valid_ptr(const RCPType& rcp_obj) const 00929 { 00930 #ifdef TEUCHOS_DEBUG 00931 assert_valid_ptr(rcp_obj); 00932 #endif 00933 } 00934 #ifdef TEUCHOS_DEBUG 00935 const void* get_base_obj_map_key_void_ptr() const 00936 { 00937 if (node_) 00938 return node_->get_base_obj_map_key_void_ptr(); 00939 return 0; 00940 } 00941 #endif 00942 private: 00943 RCPNode *node_; 00944 ERCPStrength strength_; 00945 inline void bind() 00946 { 00947 if (node_) 00948 node_->incr_count(strength_); 00949 } 00950 inline void unbind() 00951 { 00952 // Optimize this implementation for count > 1 00953 if (node_ && node_->deincr_count(strength_)==0) { 00954 // If we get here, the reference count has gone to 0 and something 00955 // interesting is going to happen. In this case, we need to 00956 // reincrement the count back to 1 and call the more complex function 00957 // that will either delete the object or delete the node. 00958 node_->incr_count(strength_); 00959 unbindOne(); 00960 } 00961 // If we get here, either node_==0 or the count is still greater than 0. 00962 // In this case, nothing interesting is going to happen so we are done! 00963 } 00964 void unbindOne(); // Provides the "strong" guarantee! 00965 00966 }; 00967 00968 00973 inline 00974 std::ostream& operator<<(std::ostream& out, const RCPNodeHandle& node) 00975 { 00976 return (out << node.node_ptr()); 00977 } 00978 00979 00989 class TEUCHOSCORE_LIB_DLL_EXPORT RCPNodeThrowDeleter { 00990 public: 00992 RCPNodeThrowDeleter(RCPNode *node) 00993 : node_(node) 00994 {} 01000 ~RCPNodeThrowDeleter() 01001 { 01002 if (node_) { 01003 node_->has_ownership(false); // Avoid actually deleting ptr_ 01004 node_->delete_obj(); // Sets the pointer ptr_=0 to allow RCPNode delete 01005 delete node_; 01006 } 01007 } 01009 RCPNode* get() const 01010 { 01011 return node_; 01012 } 01014 void release() 01015 { 01016 node_ = 0; 01017 } 01018 private: 01019 RCPNode *node_; 01020 RCPNodeThrowDeleter(); // Not defined 01021 RCPNodeThrowDeleter(const RCPNodeThrowDeleter&); // Not defined 01022 RCPNodeThrowDeleter& operator=(const RCPNodeThrowDeleter&); // Not defined 01023 }; 01024 01025 01026 // 01027 // Unit testing support 01028 // 01029 01030 01031 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 01032 01033 class SetTracingActiveNodesStack { 01034 public: 01035 SetTracingActiveNodesStack() 01036 {RCPNodeTracer::setTracingActiveRCPNodes(true);} 01037 ~SetTracingActiveNodesStack() 01038 {RCPNodeTracer::setTracingActiveRCPNodes(false);} 01039 }; 01040 01041 # define SET_RCPNODE_TRACING() Teuchos::SetTracingActiveNodesStack setTracingActiveNodesStack; 01042 01043 #else 01044 01045 # define SET_RCPNODE_TRACING() (void)0 01046 01047 #endif // defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 01048 01049 01050 } // end namespace Teuchos 01051 01052 01053 #endif // TEUCHOS_RCP_NODE_HPP
1.7.6.1