|
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 #include "Teuchos_RCP.hpp" 00043 #include "Teuchos_GlobalMPISession.hpp" 00044 #include "Teuchos_oblackholestream.hpp" 00045 #include "Teuchos_CommandLineProcessor.hpp" 00046 #include "Teuchos_StandardCatchMacros.hpp" 00047 #include "Teuchos_Assert.hpp" 00048 #include "Teuchos_getConst.hpp" 00049 #include "Teuchos_Version.hpp" 00050 00051 #ifdef HAVE_TEUCHOS_BOOST 00052 # include "Teuchos_RCPBoostSharedPtrConversions.hpp" 00053 #endif 00054 00055 #include "TestClasses.hpp" 00056 00057 00058 // 00059 // Uncomment these macros to see example errors 00060 // 00061 00062 //#define SHOW_COMPILE_TIME_ERRORS 00063 //#define SHOW_RUN_TIME_ERROR_1 00064 //#define SHOW_RUN_TIME_ERROR_2 00065 //#define SHOW_RUN_TIME_ERROR_3 00066 //#define SHOW_RUN_TIME_ERROR_4 00067 #define SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS 00068 #define SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS_PRINT 00069 //#define SHOW_MEMORY_LEAK_1 00070 00071 // 00072 // This program prints minimal output to standard error 00073 // 00074 00075 int main( int argc, char* argv[] ) { 00076 00077 using Teuchos::RCP; 00078 using Teuchos::DeallocDelete; 00079 using Teuchos::deallocFunctorDelete; 00080 using Teuchos::deallocFunctorHandleDelete; 00081 using Teuchos::null; 00082 using Teuchos::rcp; 00083 using Teuchos::rcpFromRef; 00084 using Teuchos::inOutArg; 00085 using Teuchos::is_null; 00086 using Teuchos::rcp_implicit_cast; 00087 using Teuchos::rcp_const_cast; 00088 using Teuchos::rcp_static_cast; 00089 using Teuchos::rcp_dynamic_cast; 00090 using Teuchos::set_extra_data; 00091 using Teuchos::get_extra_data; 00092 using Teuchos::get_nonconst_extra_data; 00093 using Teuchos::get_optional_extra_data; 00094 using Teuchos::get_optional_nonconst_extra_data; 00095 using Teuchos::get_dealloc; 00096 using Teuchos::get_nonconst_dealloc; 00097 using Teuchos::get_optional_dealloc; 00098 using Teuchos::get_optional_nonconst_dealloc; 00099 using Teuchos::rcpWithEmbeddedObj; 00100 using Teuchos::rcpWithEmbeddedObjPreDestroy; 00101 using Teuchos::rcpWithEmbeddedObjPostDestroy; 00102 using Teuchos::getEmbeddedObj; 00103 using Teuchos::getNonconstEmbeddedObj; 00104 using Teuchos::getConst; 00105 using Teuchos::CommandLineProcessor; 00106 00107 bool success = true; 00108 bool createCircRefs = false; // Don't create memory leak by default! 00109 00110 Teuchos::GlobalMPISession mpiSession(&argc,&argv); 00111 const int procRank = Teuchos::GlobalMPISession::getRank(); 00112 00113 Teuchos::oblackholestream blackhole; 00114 std::ostream &out = ( procRank == 0 ? std::cout : blackhole ); 00115 00116 try { 00117 00118 // Read options from the commandline 00119 CommandLineProcessor clp(false); // Don't throw exceptions 00120 clp.setOption( "create-circ-refs", "no-create-circ-refs", &createCircRefs, 00121 "Set if output is printed or not." ); 00122 CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv); 00123 if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) { 00124 out << "\nEnd Result: TEST FAILED" << std::endl; 00125 return parse_return; 00126 } 00127 00128 blackhole << "\nThis should not print anywhere.\n"; 00129 00130 out << std::endl << Teuchos::Teuchos_Version() << std::endl; 00131 00132 out << "\nTesting basic RCP functionality ...\n"; 00133 00134 // Create some smart pointers 00135 00136 RCP<A> a_ptr1 = rcp(new C); 00137 out << "\na_ptr1 = " << a_ptr1 << "\n"; 00138 // RAB: 2003/11/24: The Sun compiler ("Forte Developer 7 C++ 00139 // 5.4 2002/03/09" returned from CC -V) does not seem to be 00140 // following the standard when it comes to the handling of 00141 // temporary objects and therefore the count() is not currect. 00142 // In the above statement, at least one and perhaps two 00143 // temporary RCP objects are created before the object 00144 // a_ptr1 is initialized. However, the standard says that the 00145 // lifetime of temprary objects must not extend past the 00146 // statement in which it was created (see section 10.4.10 in 00147 // Stroustroup, 3ed edition). This compiler stinks!!!!! 00148 TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.strong_count() != 1 ); 00149 TEUCHOS_TEST_FOR_EXCEPT( !a_ptr1.shares_resource(a_ptr1) ); 00150 TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.ptr() == null ); 00151 TEUCHOS_TEST_FOR_EXCEPT( a_ptr1 == null ); 00152 TEUCHOS_TEST_FOR_EXCEPT( !(a_ptr1 != null) ); 00153 TEUCHOS_TEST_FOR_EXCEPT( is_null(a_ptr1) ); 00154 RCP<D> d_ptr1 = rcp(new E); 00155 TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.shares_resource(a_ptr1) ); 00156 TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.strong_count() != 1 ); 00157 TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.get() == NULL); 00158 TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.getRawPtr() == NULL); 00159 00160 { 00161 00162 // Create some more smart points (no new memory!) 00163 00164 const RCP<const A> ca_ptr1 = rcp_const_cast<const A>(a_ptr1); 00165 TEUCHOS_TEST_FOR_EXCEPT( !(ca_ptr1 == a_ptr1) ); 00166 TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1 != a_ptr1 ); 00167 TEUCHOS_TEST_FOR_EXCEPT( !ca_ptr1.shares_resource(a_ptr1) ); 00168 TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.strong_count() != 2 ); 00169 TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1.ptr() == null ); 00170 TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1.strong_count() != 2 ); 00171 const RCP<const D> cd_ptr1 = rcp_const_cast<const D>(d_ptr1); 00172 TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.strong_count() != 2 ); 00173 TEUCHOS_TEST_FOR_EXCEPT( cd_ptr1.ptr() == null ); 00174 TEUCHOS_TEST_FOR_EXCEPT( cd_ptr1.strong_count() != 2 ); 00175 00176 #ifdef SHOW_RUN_TIME_ERROR_1 00177 // Conversion using get() is a no no! When a_ptr2 is deleted so will the allocated 00178 // object and then a_ptr1 will be corrupted after this block ends! 00179 const RCP<A> a_ptr2 = a_ptr1.get(); 00180 #endif 00181 00182 // Test assignment functions 00183 00184 a_ptr1 = rcp_const_cast<A>(ca_ptr1.assert_not_null()); // Should be okay, assignment to self 00185 00186 #ifdef SHOW_COMPILE_TIME_ERRORS 00187 ca_ptr1 = ca_ptr1; // Should not compile since ca_ptr1 is declared constant 00188 ca_ptr1->A_g(); // Should not compile since A_g() is a non-const member function 00189 #endif 00190 00191 // Test function calls through operaor->(...) 00192 00193 TEUCHOS_TEST_FOR_EXCEPT( a_ptr1->A_g() != A_g_return ); 00194 TEUCHOS_TEST_FOR_EXCEPT( a_ptr1->A_f() != A_f_return ); 00195 TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1->A_f() != A_f_return ); 00196 TEUCHOS_TEST_FOR_EXCEPT( d_ptr1->D_g() != D_g_return ); 00197 TEUCHOS_TEST_FOR_EXCEPT( d_ptr1->D_f() != D_f_return ); 00198 TEUCHOS_TEST_FOR_EXCEPT( cd_ptr1->D_f() != D_f_return ); 00199 00200 // Test funciton calls through operator*(...) 00201 00202 TEUCHOS_TEST_FOR_EXCEPT( (*a_ptr1).A_g() != A_g_return ); 00203 TEUCHOS_TEST_FOR_EXCEPT( (*a_ptr1).A_f() != A_f_return ); 00204 TEUCHOS_TEST_FOR_EXCEPT( (*ca_ptr1).A_f() != A_f_return ); 00205 TEUCHOS_TEST_FOR_EXCEPT( (*d_ptr1).D_g() != D_g_return ); 00206 TEUCHOS_TEST_FOR_EXCEPT( (*d_ptr1).D_f() != D_f_return ); 00207 TEUCHOS_TEST_FOR_EXCEPT( (*cd_ptr1).D_f() != D_f_return ); 00208 00209 // Test dynamic and static conversions 00210 00211 // Cast down the inheritance hiearchy (const A -> const B1) 00212 const RCP<const B1> cb1_ptr1 = rcp_dynamic_cast<const B1>(ca_ptr1); 00213 TEUCHOS_TEST_FOR_EXCEPT( cb1_ptr1.ptr() == null ); 00214 TEUCHOS_TEST_FOR_EXCEPT( cb1_ptr1.strong_count() != 3 ); 00215 TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1.strong_count() != 3 ); 00216 TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.strong_count() != 3 ); 00217 00218 // Cast up the inheritance hiearchy (const B1 -> const A) 00219 TEUCHOS_TEST_FOR_EXCEPT( rcp_implicit_cast<const A>(cb1_ptr1)->A_f() != A_f_return ); 00220 TEUCHOS_TEST_FOR_EXCEPT( RCP<const A>(cb1_ptr1)->A_f() != A_f_return ); 00221 // Implicit cast from const to non-const (A -> const A) 00222 TEUCHOS_TEST_FOR_EXCEPT( rcp_implicit_cast<const A>(a_ptr1)->A_f() != A_f_return ); 00223 TEUCHOS_TEST_FOR_EXCEPT( RCP<const A>(a_ptr1)->A_f() != A_f_return ); 00224 // Cast away constantness (const B1 -> B1) 00225 TEUCHOS_TEST_FOR_EXCEPT( rcp_const_cast<B1>(cb1_ptr1)->B1_g() != B1_g_return ); 00226 // Cast across the inheritance hiearchy (const B1 -> const B2) 00227 TEUCHOS_TEST_FOR_EXCEPT( rcp_dynamic_cast<const B2>(cb1_ptr1)->B2_f() != B2_f_return ); 00228 // Cast down the inheritance hiearchy (const B1 -> const C) 00229 TEUCHOS_TEST_FOR_EXCEPT( rcp_dynamic_cast<const C>(cb1_ptr1)->C_f() != C_f_return ); 00230 00231 // Cast away constantness (const C -> C) 00232 const RCP<C> 00233 c_ptr1 = rcp_const_cast<C>(rcp_dynamic_cast<const C>(ca_ptr1)); 00234 TEUCHOS_TEST_FOR_EXCEPT( c_ptr1.ptr() == null ); 00235 TEUCHOS_TEST_FOR_EXCEPT( c_ptr1.strong_count() != 4 ); 00236 TEUCHOS_TEST_FOR_EXCEPT( ca_ptr1.strong_count() != 4 ); 00237 TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.strong_count() != 4 ); 00238 00239 // Cast down the inheritance hiearchy using static_cast<...> (const D -> const E) 00240 const RCP<const E> 00241 ce_ptr1 = rcp_static_cast<const E>(cd_ptr1); // This is not checked at runtime! 00242 TEUCHOS_TEST_FOR_EXCEPT( ce_ptr1.ptr() == null); 00243 TEUCHOS_TEST_FOR_EXCEPT( ce_ptr1.strong_count() != 3 ); 00244 TEUCHOS_TEST_FOR_EXCEPT( cd_ptr1.strong_count() != 3 ); 00245 TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.strong_count() != 3 ); 00246 00247 // Cast up the inheritance hiearchy (const E -> const D) 00248 TEUCHOS_TEST_FOR_EXCEPT( rcp_implicit_cast<const D>(ce_ptr1)->D_f() != D_f_return ); 00249 // Cast away constantness (const E -> E) 00250 TEUCHOS_TEST_FOR_EXCEPT( rcp_const_cast<E>(ce_ptr1)->E_g() != E_g_return ); 00251 TEUCHOS_TEST_FOR_EXCEPT( ce_ptr1->D_f() != D_f_return ); 00252 00253 #ifdef SHOW_COMPILE_TIME_ERRORS 00254 // Try to cast down inheritance hiearchy using dynamic_cast<...> (const D -> const E) 00255 rcp_dynamic_cast<const E>( cd_ptr1 )->E_f(); // This should not compile since D and E are not polymophic 00256 #endif 00257 00258 #ifndef _INTEL // Intel compiler does not seem to be doing dynamic cast correctly? 00259 #ifdef TEUCHOS_DEBUG // operator->() only throws std::exception when TEUCHOS_DEBUG is defined 00260 try { 00261 // Try to cast form one interface to another that is not supported (B2 -> B1). 00262 // The RCP<B1> returned from rcp_dynamic_cast<...> should be null! 00263 // Note that RCP<...>::optertor->() should throw an std::exception in debug 00264 // mode (i.e. TEUCHOS_DEBUG is defined) but even so no memory leak occurs. If you 00265 // don't believe me then step through with a debugger and see for yourself. 00266 TEUCHOS_TEST_FOR_EXCEPT( rcp_dynamic_cast<B1>( rcp(new B2) )->B1_g() != B1_g_return ); 00267 return -1; // Should not be executed! 00268 } 00269 catch( const std::logic_error &excpt ) 00270 {} 00271 #endif 00272 try { 00273 // Try to cast form one interface to another that is not supported (B2 -> B1). 00274 // Note that rcp_dynamic_cast<B1>(...,true) should throw an std::exception but even 00275 // so no memory leak occurs. If you don't believe me then step through with a 00276 // debugger and see for yourself. 00277 rcp_dynamic_cast<B1>( rcp(new B2), true ); 00278 return -1; // Should not be executed! 00279 } 00280 catch( const std::bad_cast &excpt ) 00281 {} 00282 #endif 00283 00284 // Manually clean up some memory 00285 00286 delete d_ptr1.release().get(); // Now d_ptr1.get() no longer points to a valid object but okay 00287 // as long as no other access to this object is attempted! (see below) 00288 #ifdef SHOW_RUN_TIME_ERROR_2 00289 TEUCHOS_TEST_FOR_EXCEPT( d_ptr1->D_g() == D_g_return ); // Should cause a segmentation fault since d_ptr.get() was deleted! 00290 #endif 00291 00292 #ifdef SHOW_MEMORY_LEAK_1 00293 a_ptr1.release(); // If we release but do not delete manually then this is a memory leak! 00294 #endif 00295 00296 // Here at the end of the block, all of the other smart pointers are deleted! 00297 } 00298 // Check that all of the other references where removed but these 00299 TEUCHOS_TEST_FOR_EXCEPT( a_ptr1.strong_count() != 1 ); 00300 TEUCHOS_TEST_FOR_EXCEPT( d_ptr1.strong_count() != 1 ); 00301 00302 // Assign some other dynamically created objects. 00303 00304 a_ptr1 = rcp(new A); // In each case the current dynamically allocated object is deleted ... 00305 a_ptr1 = rcp(new B1); // before the new reference is set. 00306 a_ptr1 = rcp(new B2); // "" 00307 a_ptr1 = rcp(new C); // "" 00308 d_ptr1 = rcp(new D); // "" 00309 d_ptr1 = rcp(new E); // "" 00310 00311 // Assign pointers to some automatic objects that do not need deleted. 00312 // We can do this but we need to remove ownership of the pointer 00313 // from the smart pointer objects so that they do not try to 00314 // delete them. If we forget then delete will be called on these 00315 // pointers and will cause a runtime error. 00316 00317 C c; // Automatic object what will be deleted by compiler at end of block 00318 a_ptr1 = rcp(&c); 00319 #ifndef SHOW_RUN_TIME_ERROR_3 00320 // Release ownership so that a_ptr1 will not try to delete &c when a_ptr1 goes out of scope 00321 a_ptr1.release(); 00322 #endif 00323 00324 E e; // Automatic object what will be deleted by compiler at end of block 00325 d_ptr1 = rcp(&e); 00326 #ifndef SHOW_RUN_TIME_ERROR_4 00327 // Release ownership so that d_ptr1 will not try to delete &e when a_ptr1 goes out of scope 00328 d_ptr1.release(); 00329 #endif 00330 00331 #ifdef SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS 00332 // Allocate an using new and then store the non-base address in in 00333 // a RCP and then try to delete (this is a no-no usually). 00334 C *c_ptr5 = new C; // Okay, no type info lost and address should be same as returned from malloc(...) 00335 #ifdef SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS_PRINT 00336 const void *c_ptr5_base = dynamic_cast<void*>(c_ptr5); 00337 out << "\nSize of C = " << sizeof(C) << std::endl; 00338 out << "Base address of object of type C = " << dynamic_cast<void*>(c_ptr5) << std::endl; 00339 out << "Offset to address of object of type C = " << ((long int)c_ptr5 - (long int)c_ptr5_base) << std::endl; 00340 out << "Offset of B1 object in object of type C = " << ((long int)static_cast<B1*>(c_ptr5) - (long int)c_ptr5_base) << std::endl; 00341 out << "Offset of B2 object in object of type C = " << ((long int)static_cast<B2*>(c_ptr5) - (long int)c_ptr5_base) << std::endl; 00342 out << "Offset of A object in object of type C = " << ((long int)static_cast<A*>(c_ptr5) - (long int)c_ptr5_base) << std::endl; 00343 #endif // SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS_PRINT 00344 A *a_rptr5 = c_ptr5; // Here the address has changed and is no longer the same as the base address 00345 a_ptr1 = rcp(a_rptr5); // This is a no-no and could cause trouble! 00346 a_ptr1 = null; // This will cause a segmentation fault in free(...) on many platforms 00347 #endif // SHOW_RUN_TIME_ERROR_VIRTUAL_BASE_CLASS 00348 00349 // Test out getting the deallocator object 00350 a_ptr1 = rcpWithDealloc( new C, DeallocDelete<C>() ); 00351 get_dealloc<DeallocDelete<C> >(a_ptr1); 00352 get_nonconst_dealloc<DeallocDelete<C> >(a_ptr1); 00353 TEUCHOS_TEST_FOR_EXCEPT( get_optional_nonconst_dealloc<DeallocDelete<C> >(a_ptr1)==null ); 00354 TEUCHOS_TEST_FOR_EXCEPT( get_optional_nonconst_dealloc<DeallocDelete<A> >(a_ptr1)!=null ); 00355 TEUCHOS_TEST_FOR_EXCEPT( get_optional_dealloc<DeallocDelete<C> >(const_cast<const RCP<A>&>(a_ptr1))==null ); 00356 TEUCHOS_TEST_FOR_EXCEPT( get_optional_dealloc<DeallocDelete<A> >(const_cast<const RCP<A>&>(a_ptr1))!=null ); 00357 00358 // Test storing extra data and then getting it out again 00359 TEUCHOS_TEST_FOR_EXCEPT( get_optional_nonconst_extra_data<RCP<B1> >(a_ptr1,"blahblah") != null ); 00360 TEUCHOS_TEST_FOR_EXCEPT( get_optional_extra_data<int>(const_cast<const RCP<A>&>(a_ptr1),"blahblah") != null ); // test const version 00361 set_extra_data( int(-5), "int", inOutArg(a_ptr1) ); 00362 TEUCHOS_TEST_FOR_EXCEPT( get_extra_data<int>(a_ptr1,"int") != -5 ); 00363 TEUCHOS_TEST_FOR_EXCEPT( get_nonconst_extra_data<int>(a_ptr1,"int") != -5 ); 00364 set_extra_data( rcp(new B1), "B1", inOutArg(a_ptr1) ); 00365 TEUCHOS_TEST_FOR_EXCEPT( get_extra_data<RCP<B1> >(a_ptr1,"B1")->B1_f() != B1_f_return ); 00366 TEUCHOS_TEST_FOR_EXCEPT( get_extra_data<int>(const_cast<const RCP<A>&>(a_ptr1),"int") != -5 ); // test const version 00367 TEUCHOS_TEST_FOR_EXCEPT( (*get_optional_extra_data<RCP<B1> >(a_ptr1,"B1"))->B1_f() != B1_f_return ); 00368 TEUCHOS_TEST_FOR_EXCEPT( *get_optional_extra_data<int>(const_cast<const RCP<A>&>(a_ptr1),"int") != -5 ); // test const version 00369 TEUCHOS_TEST_FOR_EXCEPT( get_optional_extra_data<RCP<B1> >(a_ptr1,"blahblah") != null ); 00370 TEUCHOS_TEST_FOR_EXCEPT( get_optional_extra_data<int>(const_cast<const RCP<A>&>(a_ptr1),"blahblah") != null ); // test const version 00371 00372 // Test storage of extra data as embedded objects and then getting it out 00373 // again 00374 00375 { 00376 RCP<A> a_ptr = rcpWithEmbeddedObj(new C,int(-5)); 00377 const int intRtn1 = getEmbeddedObj<C,int>(a_ptr); 00378 TEUCHOS_TEST_FOR_EXCEPT( intRtn1 != -5 ); 00379 getNonconstEmbeddedObj<C,int>(a_ptr) = -4; 00380 const int intRtn2 = getEmbeddedObj<C,int>(a_ptr); 00381 TEUCHOS_TEST_FOR_EXCEPT( intRtn2 != -4 ); 00382 } 00383 00384 { 00385 RCP<A> a_ptr = rcpWithEmbeddedObjPreDestroy(new C,int(-5)); 00386 const int intRtn1 = getEmbeddedObj<C,int>(a_ptr); 00387 TEUCHOS_TEST_FOR_EXCEPT( intRtn1 != -5 ); 00388 getNonconstEmbeddedObj<C,int>(a_ptr) = -4; 00389 const int intRtn2 = getEmbeddedObj<C,int>(a_ptr); 00390 TEUCHOS_TEST_FOR_EXCEPT( intRtn2 != -4 ); 00391 } 00392 00393 { 00394 RCP<A> a_ptr = rcpWithEmbeddedObjPostDestroy(new C,int(-5)); 00395 const int intRtn1 = getEmbeddedObj<C,int>(a_ptr); 00396 TEUCHOS_TEST_FOR_EXCEPT( intRtn1 != -5 ); 00397 getNonconstEmbeddedObj<C,int>(a_ptr) = -4; 00398 const int intRtn2 = getEmbeddedObj<C,int>(a_ptr); 00399 TEUCHOS_TEST_FOR_EXCEPT( intRtn2 != -4 ); 00400 } 00401 00402 // Test pre-destruction of extra data 00403 int a_f_return = -2; 00404 set_extra_data( rcp(new Get_A_f_return(&*a_ptr1,&a_f_return)), 00405 "a_f_return", inOutArg(a_ptr1), Teuchos::PRE_DESTROY ); 00406 00407 // Set pointers to null to force releasing any owned memory 00408 a_ptr1 = null; 00409 d_ptr1 = null; 00410 00411 // RAB: 2004/08/12: It appears that SUN compiler is not deleting the piece of extra 00412 // data properly and therefore the destructor of the above Get_A_f_return object 00413 // is not being called (which sets the value of af_return). This compiler stinks! 00414 TEUCHOS_TEST_FOR_EXCEPT( a_f_return != A_f_return ); // Should be been called in destructor of a_ptr1 but before the A object is destroyed! 00415 00416 // Testing the deallocFunctorDelete function and DeallocFunctorDelete class 00417 a_ptr1 = rcpWithDealloc( new C, deallocFunctorDelete<A>(deallocA) ); 00418 a_ptr1 = null; 00419 00420 // Testing the deallocFunctorHandleDelete function and DeallocFunctorHandleDelete class 00421 a_ptr1 = rcpWithDealloc( new C, deallocFunctorHandleDelete<A>(deallocHandleA) ); 00422 a_ptr1 = null; 00423 00424 #ifdef TEUCHOS_DEBUG 00425 00426 if (createCircRefs) { 00427 out << "\nCreate a circular reference that will cause a memory leak! ...\n"; 00428 # if !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 00429 // Only trun on tracing if you have to 00430 Teuchos::RCPNodeTracer::setTracingActiveRCPNodes(true); 00431 # endif 00432 RCP<A> a = rcp(new A()); 00433 RCP<C> c2 = rcp(new C()); 00434 a->set_C(c2); 00435 c2->set_A(a); 00436 } 00437 00438 #endif // TEUCHOS_DEBUG 00439 00440 #ifndef TEUCHOS_DEBUG 00441 00442 out << "\nTesting using RCP to wrap an undefined opaque object (no TNT) ...\n"; 00443 { 00444 RCP<UndefinedType> op_ptr = 00445 rcpWithDeallocUndef (createOpaque (), 00446 deallocFunctorHandleDelete<UndefinedType> (destroyOpaque), 00447 true); 00448 TEUCHOS_ASSERT_EQUALITY( getOpaqueValue(&*op_ptr), getOpaqueValue_return ); 00449 } 00450 // 2008/08/01: rabartl: Above, we can only wrap an undefined type in 00451 // nondebug mode since there is no TypeNameTraits class defined for it and 00452 // the default uses typeid(...) which you can't call on an undefined type. 00453 // If you define a specialization of TypeNameTraits for this class, then 00454 // it will compile just fine! This is related to bug 4016. 00455 00456 #endif // not TEUCHOS_DEBUG 00457 00458 out << "\nTesting using RCP to wrap an undefined opaque object (with TNT) ...\n"; 00459 { 00460 RCP<UndefinedType2> op_ptr = rcpWithDeallocUndef( createOpaque2(), 00461 deallocFunctorHandleDelete<UndefinedType2>(destroyOpaque2) ); 00462 TEUCHOS_ASSERT_EQUALITY( getOpaque2Value(&*op_ptr), getOpaque2Value_return ); 00463 } 00464 // 2008/08/01: rabartl: Above, we can wrap an undefined type in debug mode 00465 // as long as we have a TypeNameTraits specialization of it to avoid 00466 // calling typeid(...). 00467 00468 #ifdef HAVE_TEUCHOS_BOOST 00469 00470 out << "\nTesting basic RCP compatibility with boost::shared_ptr ...\n"; 00471 00472 boost::shared_ptr<A> a_sptr1(new C()); 00473 RCP<A> a_rsptr1 = rcp(a_sptr1); 00474 TEUCHOS_TEST_FOR_EXCEPT( a_rsptr1.get() != a_sptr1.get() ); 00475 TEUCHOS_TEST_FOR_EXCEPT( a_rsptr1.getRawPtr() != a_sptr1.get() ); 00476 TEUCHOS_TEST_FOR_EXCEPT( a_rsptr1.get() != a_rsptr1.getRawPtr() ); 00477 boost::shared_ptr<A> a_sptr2 = shared_pointer(a_rsptr1); 00478 // There seems no standard way to test that a shared_ptr shares the same node 00479 //TEUCHOS_TEST_FOR_EXCEPT( a_sptr2._internal_equiv(a_sptr1) != true ); 00480 RCP<A> a_rsptr2 = rcp(a_sptr2); 00481 TEUCHOS_TEST_FOR_EXCEPT( a_rsptr2.ptr() != a_rsptr1.ptr() ); 00482 //TEUCHOS_TEST_FOR_EXCEPT( a_rsptr2 != a_rsptr1 ); // This should work if boost::get_deleter() works correctly! 00483 boost::shared_ptr<A> a_sptr3 = shared_pointer(a_rsptr2); 00484 TEUCHOS_TEST_FOR_EXCEPT( a_sptr3.get() != a_rsptr2.get() ); 00485 00486 out << "\nCompatibility with boost::shared_ptr passed ...\n"; 00487 00488 #endif // HAVE_TEUCHOS_BOOST 00489 00490 out << "\nAll tests for RCP seem to check out!\n"; 00491 00492 } // end try 00493 TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success); 00494 00495 try { 00496 // In debug mode, this should show that the A and C RCP objects are still 00497 // around! 00498 if (createCircRefs) { 00499 out << "\nPrinting the active nodes just to see them!\n"; 00500 Teuchos::RCPNodeTracer::printActiveRCPNodes(out); 00501 #if defined(TEUCHOS_DEBUG) && !defined(HAVE_TEUCHOS_DEBUG_RCP_NODE_TRACING) 00502 TEUCHOS_ASSERT_EQUALITY( 2, Teuchos::RCPNodeTracer::numActiveRCPNodes() ); 00503 #endif 00504 } 00505 } // end try 00506 TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success); 00507 00508 if(success) 00509 out << "\nEnd Result: TEST PASSED" << std::endl; 00510 00511 return ( success ? 0 : 1 ); 00512 00513 }
1.7.6.1