CLHEP VERSION Reference Documentation
CLHEP Home Page CLHEP Documentation CLHEP Bug Reports |
00001 // ====================================================================== 00002 // 00003 // Test compilability and basic functionality of Utility/memory.h 00004 // 00005 // Author: W. E. Brown, 2010-03-19, adapted from the boost library's 00006 // shared_ptr and related functionality whose internal attributions bear 00007 // the following various notices: 00008 // 00009 // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. 00010 // Distributed under the Boost Software License, Version 1.0. 00011 // See http://www.boost.org/LICENSE_1_0.txt 00012 // 00013 // ====================================================================== 00014 00015 00016 #include "CLHEP/Utility/noncopyable.h" 00017 #include "CLHEP/Utility/memory.h" 00018 00019 #include <cassert> 00020 00021 00022 using namespace CLHEP; 00023 using CLHEP::shared_ptr; 00024 00025 00026 int cnt = 0; 00027 00028 struct X : public noncopyable { 00029 X() { ++cnt; } 00030 ~X() { --cnt; } // virtual destructor deliberately omitted 00031 virtual int id() const { return 1; } 00032 }; // X 00033 00034 struct Y: public X 00035 { 00036 Y() { ++cnt; } 00037 ~Y() { --cnt; } 00038 virtual int id() const { return 2; } 00039 }; // Y 00040 00041 int * get_object() 00042 { return &++cnt; } 00043 00044 void release_object(int * p) 00045 { 00046 assert(p == &cnt); 00047 --cnt; 00048 } 00049 00050 template< class T > 00051 void test_is_X(shared_ptr<T> const & p) 00052 { 00053 assert(p->id() == 1); 00054 assert((*p).id() == 1); 00055 } 00056 00057 template< class T > 00058 void test_is_X(weak_ptr<T> const & p) 00059 { 00060 assert(p.get() != 0); 00061 assert(p.get()->id() == 1); 00062 } 00063 00064 template< class T > 00065 void test_is_Y(shared_ptr<T> const & p) 00066 { 00067 assert(p->id() == 2); 00068 assert((*p).id() == 2); 00069 } 00070 00071 template< class T > 00072 void test_is_Y(weak_ptr<T> const & p) 00073 { 00074 shared_ptr<T> q = p.lock(); 00075 assert(q.get() != 0); 00076 assert(q->id() == 2); 00077 } 00078 00079 template< class T > 00080 void test_eq(T const & a, T const & b) 00081 { 00082 assert(a == b); 00083 assert(!(a != b)); 00084 assert(!(a < b)); 00085 assert(!(b < a)); 00086 } 00087 00088 template< class T > 00089 void test_ne(T const & a, T const & b) 00090 { 00091 assert(!(a == b)); 00092 assert(a != b); 00093 assert(a < b || b < a); 00094 assert(!(a < b && b < a)); 00095 } 00096 00097 template< class T, class U > 00098 void test_shared(weak_ptr<T> const & a, weak_ptr<U> const & b) 00099 { 00100 assert(!(a < b)); 00101 assert(!(b < a)); 00102 } 00103 00104 template< class T, class U > 00105 void test_nonshared(weak_ptr<T> const & a, weak_ptr<U> const & b) 00106 { 00107 assert(a < b || b < a); 00108 assert(!(a < b && b < a)); 00109 } 00110 00111 template< class T, class U > 00112 void test_eq2(T const & a, U const & b) 00113 { 00114 assert(a == b); 00115 assert(!(a != b)); 00116 } 00117 00118 template< class T, class U > 00119 void test_ne2(T const & a, U const & b) 00120 { 00121 assert(!(a == b)); 00122 assert(a != b); 00123 } 00124 00125 template< class T > 00126 void test_is_zero(shared_ptr<T> const & p) 00127 { 00128 assert(!p); 00129 assert(p.get() == 0); 00130 } 00131 00132 template< class T > 00133 void test_is_nonzero(shared_ptr<T> const & p) 00134 { 00135 // p? true: false is used to test p in a boolean context. 00136 // assert(p) is not guaranteed to test the conversion, 00137 // as the macro might test !!p instead. 00138 assert(p? true: false); 00139 assert(p.get() != 0); 00140 } 00141 00142 int main() 00143 { 00144 00145 { 00146 shared_ptr<X> p(new Y); 00147 shared_ptr<X> p2(new X); 00148 00149 test_is_nonzero(p); 00150 test_is_nonzero(p2); 00151 test_is_Y(p); 00152 test_is_X(p2); 00153 test_ne(p, p2); 00154 00155 { 00156 shared_ptr<X> q(p); 00157 test_eq(p, q); 00158 } 00159 00160 shared_ptr<Y> p3 = dynamic_pointer_cast<Y>(p); 00161 shared_ptr<Y> p4 = dynamic_pointer_cast<Y>(p2); 00162 00163 test_is_nonzero(p3); 00164 test_is_zero(p4); 00165 00166 assert(p.use_count() == 2); 00167 assert(p2.use_count() == 1); 00168 assert(p3.use_count() == 2); 00169 00170 test_is_Y(p3); 00171 test_eq2(p, p3); 00172 test_ne2(p2, p4); 00173 00174 shared_ptr<void> p5(p); 00175 00176 test_is_nonzero(p5); 00177 test_eq2(p, p5); 00178 00179 weak_ptr<X> wp1(p2); 00180 00181 assert(!wp1.expired()); 00182 assert(wp1.use_count() != 0); 00183 00184 p.reset(); 00185 p2.reset(); 00186 p3.reset(); 00187 p4.reset(); 00188 00189 test_is_zero(p); 00190 test_is_zero(p2); 00191 test_is_zero(p3); 00192 test_is_zero(p4); 00193 00194 assert(p5.use_count() == 1); 00195 00196 assert(wp1.expired()); 00197 assert(wp1.use_count() == 0); 00198 00199 try 00200 { 00201 shared_ptr<X> sp1(wp1); 00202 throw "shared_ptr<X> sp1(wp1) failed to throw"; 00203 } 00204 catch(bad_weak_ptr const &) 00205 { 00206 } 00207 00208 test_is_zero(wp1.lock()); 00209 00210 weak_ptr<X> wp2 = static_pointer_cast<X>(p5); 00211 00212 assert(wp2.use_count() == 1); 00213 test_is_Y(wp2); 00214 test_nonshared(wp1, wp2); 00215 00216 // Scoped to not affect the subsequent use_count() tests. 00217 { 00218 shared_ptr<X> sp2(wp2); 00219 test_is_nonzero(wp2.lock()); 00220 } 00221 00222 weak_ptr<Y> wp3 = dynamic_pointer_cast<Y>(wp2.lock()); 00223 00224 assert(wp3.use_count() == 1); 00225 test_shared(wp2, wp3); 00226 00227 weak_ptr<X> wp4(wp3); 00228 00229 assert(wp4.use_count() == 1); 00230 test_shared(wp2, wp4); 00231 00232 wp1 = p2; 00233 test_is_zero(wp1.lock()); 00234 00235 wp1 = p4; 00236 wp1 = wp3; 00237 wp1 = wp2; 00238 00239 assert(wp1.use_count() == 1); 00240 test_shared(wp1, wp2); 00241 00242 weak_ptr<X> wp5; 00243 00244 bool b1 = wp1 < wp5; 00245 bool b2 = wp5 < wp1; 00246 00247 p5.reset(); 00248 00249 assert(wp1.use_count() == 0); 00250 assert(wp2.use_count() == 0); 00251 assert(wp3.use_count() == 0); 00252 00253 // Test operator< stability for std::set< weak_ptr<> > 00254 // Thanks to Joe Gottman for pointing this out 00255 00256 assert(b1 == (wp1 < wp5)); 00257 assert(b2 == (wp5 < wp1)); 00258 00259 { 00260 // note that both get_object and release_object deal with int* 00261 shared_ptr<void> p6(get_object(), release_object); 00262 } 00263 00264 } 00265 00266 assert(cnt == 0); 00267 00268 return 0; 00269 00270 } // main()