RCP_test.cpp

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