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 #ifdef TEUCHOS_DEBUG
00126 if (!extra_data) {
00127 const std::string type_and_name( type_name + std::string(":") + name );
00128 TEST_FOR_EXCEPTION(
00129 extra_data == NULL, std::invalid_argument
00130 ,"Error, the type:name pair \'" << type_and_name << "\' is not found!" );
00131 }
00132 #endif
00133 return *extra_data;
00134 }
00135
00136
00137 any* RCPNode::get_optional_extra_data( const std::string& type_name,
00138 const std::string& name )
00139 {
00140 if( extra_data_map_ == NULL ) return NULL;
00141 const std::string type_and_name( type_name + std::string(":") + name );
00142 extra_data_map_t::iterator itr = extra_data_map_->find(type_and_name);
00143 if(itr != extra_data_map_->end())
00144 return &(*itr).second.extra_data;
00145 return NULL;
00146 }
00147
00148
00149 void RCPNode::impl_pre_delete_extra_data()
00150 {
00151 for(
00152 extra_data_map_t::iterator itr = extra_data_map_->begin();
00153 itr != extra_data_map_->end();
00154 ++itr
00155 )
00156 {
00157 extra_data_map_t::value_type &entry = *itr;
00158 if(entry.second.destroy_when == PRE_DESTROY)
00159 entry.second.extra_data = any();
00160 }
00161 }
00162
00163 }
00164
00165
00166 void Teuchos::add_new_RCPNode( RCPNode* rcp_node, const std::string &info )
00167 {
00168 if (loc_isTracingActiveRCPNodes) {
00169 TEST_FOR_EXCEPT(0==rcp_node_list);
00170 static int call_number = 0;
00171 (*rcp_node_list)[rcp_node] = InfoAndCallNumber(info,call_number);
00172 ++call_number;
00173 }
00174 }
00175
00176
00177 void Teuchos::remove_RCPNode( RCPNode* rcp_node )
00178 {
00179
00180
00181
00182
00183
00184
00185
00186
00187 TEST_FOR_EXCEPT(0==rcp_node_list);
00188 const rcp_node_list_t::iterator itr = rcp_node_list->find(rcp_node);
00189 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES
00190
00191
00192
00193 TEST_FOR_EXCEPT_PRINT(itr==rcp_node_list->end(),&std::cerr);
00194 #else
00195
00196
00197
00198
00199
00200 #endif
00201 if (itr != rcp_node_list->end())
00202 rcp_node_list->erase(itr);
00203 }
00204
00205
00206
00207
00208
00209
00210
00211 Teuchos::PrintActiveRCPNodes::PrintActiveRCPNodes()
00212 {
00213 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00214 std::cerr << "\nCalled PrintActiveRCPNodes::PrintActiveRCPNodes() : count = " << count_ << "\n";
00215 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00216 if (!rcp_node_list)
00217 rcp_node_list = new rcp_node_list_t;
00218 ++count_;
00219 }
00220
00221
00222 Teuchos::PrintActiveRCPNodes::~PrintActiveRCPNodes()
00223 {
00224 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00225 std::cerr << "\nCalled PrintActiveRCPNodes::~PrintActiveRCPNodes() : count = " << count_ << "\n";
00226 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00227 if( --count_ == 0 ) {
00228 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00229 std::cerr << "\nPrint active nodes!\n";
00230 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00231 std::cout << std::flush;
00232 TEST_FOR_EXCEPT(0==rcp_node_list);
00233 printActiveRCPNodes(std::cerr);
00234 delete rcp_node_list;
00235 }
00236 }
00237
00238
00239 void Teuchos::PrintActiveRCPNodes::foo()
00240 {
00241 int dummy = count_;
00242 ++dummy;
00243 }
00244
00245
00246 int Teuchos::PrintActiveRCPNodes::count_ = 0;
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 bool Teuchos::isTracingActiveRCPNodes()
00257 {
00258 return loc_isTracingActiveRCPNodes;
00259 }
00260
00261 #ifdef TEUCHOS_DEBUG
00262
00263 void Teuchos::setTracingActiveRCPNodes(bool tracingActiveNodes)
00264 {
00265 #ifdef TEUCHOS_DEBUG
00266 loc_isTracingActiveRCPNodes = tracingActiveNodes;
00267 #else
00268 TEST_FOR_EXCEPT_MSG(true,"Error, you can not call setTracingActiveRCPNodes(...)"
00269 " when TEUCHOS_DEBUG is not defined!");
00270 #endif
00271 }
00272
00273 #endif // TEUCHOS_DEBUG
00274
00275
00276 int Teuchos::numActiveRCPNodes() {
00277 #ifdef TEUCHOS_DEBUG
00278 TEST_FOR_EXCEPT(0==rcp_node_list);
00279 return rcp_node_list->size();
00280 #endif
00281 return 0;
00282 }
00283
00284
00285 void Teuchos::printActiveRCPNodes(std::ostream &out)
00286 {
00287 #ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00288 out
00289 << "\nCalled printActiveRCPNodes() :"
00290 << " rcp_node_list.size() = " << rcp_node_list.size() << "\n";
00291 #endif // TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE
00292 if (loc_isTracingActiveRCPNodes) {
00293 TEST_FOR_EXCEPT(0==rcp_node_list);
00294 rcp_node_list_t::const_iterator itr = rcp_node_list->begin();
00295 if(itr != rcp_node_list->end()) {
00296 out
00297 << "\n***"
00298 << "\n*** Warning! The following Teuchos::RCPNode objects were created but have"
00299 << "\n*** not been destroyed yet. This may be an indication that these objects may"
00300 << "\n*** be involved in a circular dependency! A memory checking tool may complain"
00301 << "\n*** that these objects are not destroyed correctly."
00302 << "\n***\n";
00303 while( itr != rcp_node_list->end() ) {
00304 const rcp_node_list_t::value_type &entry = *itr;
00305 out
00306 << "\n RCPNode address = \'" << entry.first << "\',"
00307 << " information = " << entry.second.info << ","
00308 << " call number = " << entry.second.call_number;
00309 ++itr;
00310 }
00311 out << "\n";
00312 }
00313 }
00314 }
00315
00316
00317 void Teuchos::throw_null_ptr_error( const std::string &type_name )
00318 {
00319 TEST_FOR_EXCEPTION(
00320 true, NullReferenceError,
00321 type_name << " : You can not call operator->() or operator*()"
00322 <<" if getRawPtr()==0!" );
00323 }