Teuchos_RCP.cpp

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 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #include "Teuchos_RCP.hpp"
00030 #include "Teuchos_TestForException.hpp"
00031 #include "Teuchos_VerboseObject.hpp"
00032 
00033 
00034 namespace {
00035 
00036 
00037 struct InfoAndCallNumber {
00038   InfoAndCallNumber()
00039     :call_number(-1)
00040   {}
00041   InfoAndCallNumber(
00042         const std::string &info_in,
00043         const int &call_number_in
00044         )
00045     :info(info_in), call_number(call_number_in)
00046 
00047   {}
00048   std::string info;
00049   int call_number;
00050 };
00051 
00052 
00053 typedef std::map<Teuchos::PrivateUtilityPack::RCP_node*,InfoAndCallNumber>
00054 rcp_node_list_t;
00055 
00056 
00057 // Here we must let the PrintActiveRCPNodes constructor and destructor handle
00058 // the creation and destruction of this map object.  This will ensure that
00059 // this map object will be valid when any global/static RCP objects are
00060 // destroyed!
00061 rcp_node_list_t *rcp_node_list = 0;
00062 
00063 
00064 } // namespace
00065 
00066 
00067 namespace Teuchos {
00068 
00069 
00070 void PrivateUtilityPack::throw_null( const std::string &type_name )
00071 {
00072   TEST_FOR_EXCEPTION(
00073     true, std::logic_error
00074     ,"RCP<"<<type_name<<">::assert_not_null() : You can not"
00075     " call operator->() or operator*() if get()==NULL!" );
00076 }
00077 
00078 
00079 namespace PrivateUtilityPack {
00080 
00081 
00082 void RCP_node::set_extra_data(
00083   const any &extra_data, const std::string& name
00084   ,EPrePostDestruction destroy_when
00085   ,bool force_unique
00086   )
00087 {
00088   if(extra_data_map_==NULL) {
00089     extra_data_map_ = new extra_data_map_t;
00090   }
00091   const std::string type_and_name( extra_data.typeName() + std::string(":") + name );
00092   if( !extra_data_map_->empty() && force_unique ) {
00093     extra_data_map_t::iterator itr = extra_data_map_->find(type_and_name);
00094 #ifdef TEUCHOS_DEBUG
00095     TEST_FOR_EXCEPTION(
00096       itr != extra_data_map_->end(), std::invalid_argument
00097       ,"Error, the type:name pair \'" << type_and_name << "\' already exists and force_unique==true!" );
00098 #endif
00099   }
00100   (*extra_data_map_)[type_and_name] = extra_data_entry_t(extra_data,destroy_when); // This may add or replace!
00101 }
00102 
00103 
00104 any& RCP_node::get_extra_data( const std::string& type_name, const std::string& name )
00105 {
00106 #ifdef TEUCHOS_DEBUG
00107   TEST_FOR_EXCEPTION(
00108     extra_data_map_==NULL, std::invalid_argument
00109     ,"Error, no extra data has been set yet!" );
00110 #endif
00111   any *extra_data = get_optional_extra_data(type_name,name);
00112   if(extra_data) return *extra_data;
00113   const std::string type_and_name( type_name + std::string(":") + name );
00114 #ifdef TEUCHOS_DEBUG
00115   TEST_FOR_EXCEPTION(
00116     extra_data == NULL, std::invalid_argument
00117     ,"Error, the type:name pair \'" << type_and_name << "\' is not found!" );
00118 #endif
00119   return *extra_data; // Will never be executed!
00120 }
00121 
00122 
00123 any* RCP_node::get_optional_extra_data( const std::string& type_name, const std::string& name )
00124 {
00125   if( extra_data_map_ == NULL ) return NULL;
00126   const std::string type_and_name( type_name + std::string(":") + name );
00127   extra_data_map_t::iterator itr = extra_data_map_->find(type_and_name);
00128   if(itr != extra_data_map_->end())
00129     return &(*itr).second.extra_data;
00130   return NULL;
00131 }
00132 
00133 
00134 void RCP_node::impl_pre_delete_extra_data()
00135 {
00136   for( extra_data_map_t::iterator itr = extra_data_map_->begin(); itr != extra_data_map_->end(); ++itr ) {
00137     extra_data_map_t::value_type &entry = *itr;
00138     if(entry.second.destroy_when == PRE_DESTROY)
00139       entry.second.extra_data = any();
00140   }
00141 }
00142 
00143 
00144 } // namespace PrivateUtilityPack
00145 
00146 
00147 // Define this macro here locally and rebuild just this *.cpp file and update
00148 // the Teuchos library and you will get node tracing turned on when debugging
00149 // support is enabled!  Note that you also have to TEUCHOS_DEBUG defined as
00150 // well (using --enable-teuchos-debug at configure time).
00151 
00152 //#define TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES
00153 
00154 
00155 void PrivateUtilityPack::add_new_RCP_node( RCP_node* rcp_node, const std::string &info )
00156 {
00157 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES
00158   TEST_FOR_EXCEPT(0==rcp_node_list);
00159   static int call_number = 0;
00160   (*rcp_node_list)[rcp_node] = InfoAndCallNumber(info,call_number);
00161   ++call_number;
00162 #endif
00163 }
00164 
00165 
00166 void PrivateUtilityPack::remove_RCP_node( RCP_node* rcp_node )
00167 {
00168 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES
00169   TEST_FOR_EXCEPT(0==rcp_node_list);
00170   const rcp_node_list_t::iterator itr = rcp_node_list->find(rcp_node);
00171   TEST_FOR_EXCEPT_PRINT(itr==rcp_node_list->end(),&std::cerr);
00172   rcp_node_list->erase(itr);
00173 #endif
00174 }
00175 
00176 
00177 namespace PrivateUtilityPack {
00178 
00179 
00180 PrintActiveRCPNodes::PrintActiveRCPNodes()
00181 {
00182 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00183   std::cerr << "\nCalled PrintActiveRCPNodes::PrintActiveRCPNodes() : count = " << count_ << "\n";
00184 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00185   if (!rcp_node_list)
00186     rcp_node_list = new rcp_node_list_t;
00187   ++count_;
00188 }
00189 
00190 
00191 PrintActiveRCPNodes::~PrintActiveRCPNodes()
00192 {
00193 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00194   std::cerr << "\nCalled PrintActiveRCPNodes::~PrintActiveRCPNodes() : count = " << count_ << "\n";
00195 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00196   if(--count_ == 0 ) {
00197 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00198     std::cerr << "\nPrint active nodes!\n";
00199 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00200     std::cout << std::flush;
00201     print_active_RCP_nodes(std::cerr);
00202     TEST_FOR_EXCEPT(0==rcp_node_list);
00203     delete rcp_node_list;
00204   }
00205 }
00206 
00207 
00208 void PrintActiveRCPNodes::foo()
00209 {
00210   int dummy = count_;
00211   ++dummy; // Avoid unused variable warning (bug 2664)
00212 }
00213 
00214 
00215 int PrintActiveRCPNodes::count_ = 0;
00216 
00217 
00218 } // namespace PrivateUtilityPack
00219 
00220 
00221 } // namespace Teuchos
00222  
00223 
00224 void Teuchos::print_active_RCP_nodes(std::ostream &out)
00225 {
00226 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00227   out
00228     << "\nCalled PrivateUtilityPack::print_active_RCP_nodes() :"
00229     << " rcp_node_list.size() = " << rcp_node_list.size() << "\n";
00230 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00231 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES
00232   TEST_FOR_EXCEPT(0==rcp_node_list);
00233   rcp_node_list_t::const_iterator itr = rcp_node_list->begin();
00234   if(itr != rcp_node_list->end()) {
00235     out
00236       << "\n***"
00237       << "\n*** Warning! The following Teucho::RCP_node objects were created but have"
00238       << "\n*** not been destoryed yet.  This may be an indication that these objects may"
00239       << "\n*** be involved in a circular dependency!  A memory checking tool may complain"
00240       << "\n*** that these objects are not destoryed correctly."
00241       << "\n***\n";
00242     while( itr != rcp_node_list->end() ) {
00243       const rcp_node_list_t::value_type &entry = *itr;
00244       out
00245         << "\n  RCP_node address = \'" << entry.first << "\',"
00246         << " information = " << entry.second.info << ","
00247         << " call number = " << entry.second.call_number;
00248       ++itr;
00249     }
00250     out << "\n";
00251   }
00252 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES
00253 }

Generated on Tue Oct 20 12:45:26 2009 for Teuchos - Trilinos Tools Package by doxygen 1.4.7