00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "Teuchos_RCPNode.hpp"
00030 #include "Teuchos_TestForException.hpp"
00031 #include "Teuchos_Exceptions.hpp"
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 namespace {
00042
00043
00044 struct InfoAndCallNumber {
00045 InfoAndCallNumber()
00046 :call_number(-1)
00047 {}
00048 InfoAndCallNumber(
00049 const std::string &info_in,
00050 const int &call_number_in
00051 )
00052 :info(info_in), call_number(call_number_in)
00053
00054 {}
00055 std::string info;
00056 int call_number;
00057 };
00058
00059
00060 typedef std::map<Teuchos::RCPNode*,InfoAndCallNumber>
00061 rcp_node_list_t;
00062
00063
00064
00065
00066
00067
00068
00069
00070 rcp_node_list_t *rcp_node_list = 0;
00071
00072
00073 bool loc_isTracingActiveRCPNodes =
00074 #if defined(TEUCHOS_DEBUG) && defined(TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES)
00075 true
00076 #else
00077 false
00078 #endif
00079 ;
00080
00081
00082 }
00083
00084
00085
00086
00087
00088
00089
00090 namespace Teuchos {
00091
00092
00093 void RCPNode::set_extra_data(
00094 const any &extra_data, const std::string& name
00095 ,EPrePostDestruction destroy_when
00096 ,bool force_unique
00097 )
00098 {
00099 if(extra_data_map_==NULL) {
00100 extra_data_map_ = new extra_data_map_t;
00101 }
00102 const std::string type_and_name( extra_data.typeName() + std::string(":") + name );
00103 if( !extra_data_map_->empty() && force_unique ) {
00104 extra_data_map_t::iterator itr = extra_data_map_->find(type_and_name);
00105 #ifdef TEUCHOS_DEBUG
00106 TEST_FOR_EXCEPTION(
00107 itr != extra_data_map_->end(), std::invalid_argument
00108 ,"Error, the type:name pair \'" << type_and_name
00109 << "\' already exists and force_unique==true!" );
00110 #endif
00111 }
00112 (*extra_data_map_)[type_and_name] =
00113 extra_data_entry_t(extra_data,destroy_when);
00114 }
00115
00116
00117 any& RCPNode::get_extra_data( const std::string& type_name, const std::string& name )
00118 {
00119 #ifdef TEUCHOS_DEBUG
00120 TEST_FOR_EXCEPTION(
00121 extra_data_map_==NULL, std::invalid_argument
00122 ,"Error, no extra data has been set yet!" );
00123 #endif
00124 any *extra_data = get_optional_extra_data(type_name,name);
00125 if(extra_data) return *extra_data;
00126 const std::string type_and_name( type_name + std::string(":") + name );
00127 #ifdef TEUCHOS_DEBUG
00128 TEST_FOR_EXCEPTION(
00129 extra_data == NULL, std::invalid_argument
00130 ,"Error, the type:name pair \'" << type_and_name << "\' is not found!" );
00131 #endif
00132 return *extra_data;
00133 }
00134
00135
00136 any* RCPNode::get_optional_extra_data( const std::string& type_name,
00137 const std::string& name )
00138 {
00139 if( extra_data_map_ == NULL ) return NULL;
00140 const std::string type_and_name( type_name + std::string(":") + name );
00141 extra_data_map_t::iterator itr = extra_data_map_->find(type_and_name);
00142 if(itr != extra_data_map_->end())
00143 return &(*itr).second.extra_data;
00144 return NULL;
00145 }
00146
00147
00148 void RCPNode::impl_pre_delete_extra_data()
00149 {
00150 for(
00151 extra_data_map_t::iterator itr = extra_data_map_->begin();
00152 itr != extra_data_map_->end();
00153 ++itr
00154 )
00155 {
00156 extra_data_map_t::value_type &entry = *itr;
00157 if(entry.second.destroy_when == PRE_DESTROY)
00158 entry.second.extra_data = any();
00159 }
00160 }
00161
00162 }
00163
00164
00165 void Teuchos::add_new_RCPNode( RCPNode* rcp_node, const std::string &info )
00166 {
00167 if (loc_isTracingActiveRCPNodes) {
00168 TEST_FOR_EXCEPT(0==rcp_node_list);
00169 static int call_number = 0;
00170 (*rcp_node_list)[rcp_node] = InfoAndCallNumber(info,call_number);
00171 ++call_number;
00172 }
00173 }
00174
00175
00176 void Teuchos::remove_RCPNode( RCPNode* rcp_node )
00177 {
00178
00179
00180
00181
00182
00183
00184
00185
00186 TEST_FOR_EXCEPT(0==rcp_node_list);
00187 const rcp_node_list_t::iterator itr = rcp_node_list->find(rcp_node);
00188 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES
00189
00190
00191
00192 TEST_FOR_EXCEPT_PRINT(itr==rcp_node_list->end(),&std::cerr);
00193 #else
00194
00195
00196
00197
00198
00199 #endif
00200 if (itr != rcp_node_list->end())
00201 rcp_node_list->erase(itr);
00202 }
00203
00204
00205
00206
00207
00208
00209
00210 Teuchos::PrintActiveRCPNodes::PrintActiveRCPNodes()
00211 {
00212 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00213 std::cerr << "\nCalled PrintActiveRCPNodes::PrintActiveRCPNodes() : count = " << count_ << "\n";
00214 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00215 if (!rcp_node_list)
00216 rcp_node_list = new rcp_node_list_t;
00217 ++count_;
00218 }
00219
00220
00221 Teuchos::PrintActiveRCPNodes::~PrintActiveRCPNodes()
00222 {
00223 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00224 std::cerr << "\nCalled PrintActiveRCPNodes::~PrintActiveRCPNodes() : count = " << count_ << "\n";
00225 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00226 if( --count_ == 0 ) {
00227 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00228 std::cerr << "\nPrint active nodes!\n";
00229 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00230 std::cout << std::flush;
00231 TEST_FOR_EXCEPT(0==rcp_node_list);
00232 printActiveRCPNodes(std::cerr);
00233 delete rcp_node_list;
00234 }
00235 }
00236
00237
00238 void Teuchos::PrintActiveRCPNodes::foo()
00239 {
00240 int dummy = count_;
00241 ++dummy;
00242 }
00243
00244
00245 int Teuchos::PrintActiveRCPNodes::count_ = 0;
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 bool Teuchos::isTracingActiveRCPNodes()
00256 {
00257 return loc_isTracingActiveRCPNodes;
00258 }
00259
00260 #ifdef TEUCHOS_DEBUG
00261
00262 void Teuchos::setTracingActiveRCPNodes(bool tracingActiveNodes)
00263 {
00264 #ifdef TEUCHOS_DEBUG
00265 loc_isTracingActiveRCPNodes = tracingActiveNodes;
00266 #else
00267 TEST_FOR_EXCEPT_MSG(true,"Error, you can not call setTracingActiveRCPNodes(...)"
00268 " when TEUCHOS_DEBUG is not defined!");
00269 #endif
00270 }
00271
00272 #endif // TEUCHOS_DEBUG
00273
00274
00275 int Teuchos::numActiveRCPNodes() {
00276 #ifdef TEUCHOS_DEBUG
00277 TEST_FOR_EXCEPT(0==rcp_node_list);
00278 return rcp_node_list->size();
00279 #endif
00280 return 0;
00281 }
00282
00283
00284 void Teuchos::printActiveRCPNodes(std::ostream &out)
00285 {
00286 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00287 out
00288 << "\nCalled printActiveRCPNodes() :"
00289 << " rcp_node_list.size() = " << rcp_node_list.size() << "\n";
00290 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00291 if (loc_isTracingActiveRCPNodes) {
00292 TEST_FOR_EXCEPT(0==rcp_node_list);
00293 rcp_node_list_t::const_iterator itr = rcp_node_list->begin();
00294 if(itr != rcp_node_list->end()) {
00295 out
00296 << "\n***"
00297 << "\n*** Warning! The following Teuchos::RCPNode objects were created but have"
00298 << "\n*** not been destroyed yet. This may be an indication that these objects may"
00299 << "\n*** be involved in a circular dependency! A memory checking tool may complain"
00300 << "\n*** that these objects are not destroyed correctly."
00301 << "\n***\n";
00302 while( itr != rcp_node_list->end() ) {
00303 const rcp_node_list_t::value_type &entry = *itr;
00304 out
00305 << "\n RCPNode address = \'" << entry.first << "\',"
00306 << " information = " << entry.second.info << ","
00307 << " call number = " << entry.second.call_number;
00308 ++itr;
00309 }
00310 out << "\n";
00311 }
00312 }
00313 }
00314
00315
00316 void Teuchos::throw_null_ptr_error( const std::string &type_name )
00317 {
00318 TEST_FOR_EXCEPTION(
00319 true, NullReferenceError,
00320 type_name << " : You can not call operator->() or operator*()"
00321 <<" if getRawPtr()==0!" );
00322 }