Teuchos_RCPNode.cpp
Go to the documentation of this file.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 }