CSet.cpp

00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010 Sandia Corporation.                     */
00003 /*  Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive   */
00004 /*  license for use of this work by or on behalf of the U.S. Government.  */
00005 /*  Export of this program may require a license from the                 */
00006 /*  United States Government.                                             */
00007 /*------------------------------------------------------------------------*/
00008 
00009 #include <algorithm>
00010 #include <stdexcept>
00011 #include <iostream>
00012 #include <sstream>
00013 
00014 #include <stk_util/util/CSet.hpp>
00015 
00016 namespace stk {
00017 
00018 namespace {
00019 
00020 typedef void (* DeleteFunction )( void * );
00021 
00022 typedef std::pair< const std::type_info * , DeleteFunction > Manager ;
00023 
00024 // Comparison for sorted vector
00025 
00026 struct less_cset {
00027   bool operator()( const Manager        & lhs ,
00028                    const std::type_info & rhs ) const ;
00029   bool operator()( const std::type_info & lhs ,
00030                    const Manager        & rhs ) const ;
00031 };
00032 
00033 // On some systems, namely AIX, std::type_info::before(...)
00034 // has a bug where it returns true instead of false for equality.
00035 // Thus we pay a small price on all systems to specifically
00036 // test for and eliminate equality.
00037 
00038 bool less_cset::operator()( const Manager        & lhs ,
00039                             const std::type_info & rhs ) const
00040 { return lhs.first->before( rhs ) && * lhs.first != rhs ; }
00041 
00042 bool less_cset::operator()( const std::type_info & lhs ,
00043                             const Manager        & rhs ) const
00044 { return lhs.before( *rhs.first ) && lhs != *rhs.first ; }
00045 
00046 
00047 std::vector< Manager >::const_iterator
00048 lower_bound( const std::vector< Manager > & v , const std::type_info & t )
00049 {
00050   std::vector< Manager >::const_iterator i = v.begin();
00051   std::vector< Manager >::const_iterator j = v.end();
00052 
00053   return std::lower_bound( i , j , t , less_cset() );
00054 }
00055 
00056 std::vector< Manager >::iterator
00057 lower_bound( std::vector< Manager > & v , const std::type_info & t )
00058 {
00059   std::vector< Manager >::iterator i = v.begin();
00060   std::vector< Manager >::iterator j = v.end();
00061 
00062   return std::lower_bound( i , j , t , less_cset() );
00063 }
00064 
00065 }
00066 
00067 //----------------------------------------------------------------------
00068 
00069 const void * CSet::p_get( const std::type_info & t ) const
00070 {
00071   const void * result = NULL ;
00072 
00073   const std::vector< Manager >::const_iterator im = lower_bound(m_manager,t);
00074 
00075   if ( im < m_manager.end() && t == * im->first ) {
00076     const size_t offset = im - m_manager.begin();
00077     result = m_value[ offset ];
00078   }
00079 
00080   return result ;
00081 }
00082 
00083 const void *
00084 CSet::p_insert( const Manager & m , const void * v )
00085 {
00086   std::vector< Manager >::iterator im = lower_bound( m_manager , * m.first );
00087 
00088   const size_t offset = im - m_manager.begin();
00089 
00090   std::vector<const void *>::iterator iv = m_value.begin();
00091   std::advance( iv , offset );
00092 
00093   if ( im == m_manager.end() || * m.first != * im->first ) {
00094     im = m_manager.insert( im , m );
00095     iv = m_value  .insert( iv , v );
00096   }
00097 
00098   return *iv ;
00099 }
00100 
00101 bool CSet::p_remove( const std::type_info & t , const void * v )
00102 {
00103   const std::vector< Manager >::iterator im = lower_bound( m_manager , t );
00104 
00105   const size_t offset = im - m_manager.begin();
00106 
00107   std::vector<const void *>::iterator iv = m_value.begin();
00108   std::advance( iv , offset );
00109 
00110   const bool result = im != m_manager.end() && t == * im->first && v == * iv ;
00111 
00112   if ( result ) {
00113     m_manager.erase( im );
00114     m_value  .erase( iv );
00115   }
00116 
00117   return result ;
00118 }
00119 
00120 //----------------------------------------------------------------------
00121 
00122 CSet::~CSet()
00123 {
00124   try {
00125     const size_t n = m_manager.size();
00126     for ( size_t i = 0 ; i < n ; ++i ) {
00127       try {
00128         if ( m_manager[i].second ) {
00129           (*m_manager[i].second)( const_cast<void*>( m_value[i] ) );
00130         }
00131       } catch(...) {}
00132     }
00133   } catch(...) {}
00134 }
00135 
00136 CSet::CSet() : m_manager(), m_value() {}
00137 
00138 } // namespace stk
00139 
00140 //----------------------------------------------------------------------
00141 //----------------------------------------------------------------------
00142 
00143 
00144 #ifdef UNIT_TEST
00145 
00146 namespace stk {
00147 namespace unit_test {
00148 
00149 class A {
00150 public:
00151   virtual const char * name() const = 0 ;
00152   virtual ~A();
00153 };
00154 
00155 class B {
00156 public:
00157   virtual const char * name() const = 0 ;
00158   virtual ~B();
00159 };
00160 
00161 void DoNotDelete( A * a )
00162 { std::cout << "DoNotDelete(" << a->name() << ")" << std::endl ; }
00163 
00164 void DoDelete( A * a )
00165 {
00166   std::cout << "DoDelete(" << a->name() << ")" << std::endl ;
00167   delete a ;
00168 }
00169 
00170 void DoNotDelete( B * b )
00171 { std::cout << "DoNotDelete(" << b->name() << ")" << std::endl ; }
00172 
00173 void DoDelete( B * b )
00174 {
00175   std::cout << "DoDelete(" << b->name() << ")" << std::endl ;
00176   delete b ;
00177 }
00178 
00179 class U : public A {
00180 public:
00181   const char * name() const ;
00182   ~U() {}
00183 };
00184 
00185 class V : public B {
00186 public:
00187   const char * name() const ;
00188   ~V() {}
00189 };
00190 
00191 class W : public B {
00192 public:
00193   const char * name() const ;
00194   ~W() {}
00195 };
00196 
00197 class X : public A , public B {
00198 public:
00199   const char * name() const ;
00200   ~X() {}
00201 };
00202 
00203 class Y : public A , public B {
00204 public:
00205   const char * name() const ;
00206   ~Y() {}
00207 };
00208 
00209 class Z {
00210 public:
00211   const char * name() const ;
00212   ~Z() {}
00213 };
00214 
00215 //----------------------------------------------------------------------
00216 
00217 int cset()
00218 {
00219   const A * sa ;
00220   const B * sb ;
00221   bool flag ;
00222 
00223   U * u = new U();
00224   V * v = new V();
00225   W * w = new W();
00226   X * x = new X();
00227   Y * y = new Y();
00228 
00229   {
00230     CSet cs ;
00231 
00232     sa = cs.insert<A>(u,true);
00233     std::cout << "cs.insert<A>(u,true)->name() = " << sa->name() << std::endl ;
00234 
00235     sb = cs.insert<B>(v,true);
00236     std::cout << "cs.insert<B>(v,true)->name() = " << sb->name() << std::endl ;
00237 
00238     // Should not replace:
00239     sb = cs.insert<B>(w,true);
00240     std::cout << "cs.insert<B>(w,true)->name() = " << sb->name() << std::endl ;
00241 
00242     flag = cs.remove<A>( u );
00243     std::cout << "s.remove<A>(u) = " << flag << std::endl ;
00244 
00245     flag = cs.remove<B>( v );
00246     std::cout << "s.remove<B>(v) = " << flag << std::endl ;
00247 
00248     sa = cs.insert<A>(x);
00249     sb = cs.insert<B>(x);
00250     std::cout << "s.insert<A>(x)->name() = " << sa->name() << std::endl ;
00251     std::cout << "s.insert<B>(x)->name() = " << sb->name() << std::endl ;
00252 
00253     sa = cs.insert<A>(y);
00254     sb = cs.insert<B>(y);
00255     std::cout << "s.insert<A>(y)->name() = " << sa->name() << std::endl ;
00256     std::cout << "s.insert<B>(y)->name() = " << sb->name() << std::endl ;
00257   }
00258 
00259   delete x ; x = NULL ;
00260   delete y ; y = NULL ;
00261   delete w ; w = NULL ;
00262   delete v ; v = NULL ;
00263   delete u ; u = NULL ;
00264 
00265   return 0 ;
00266 }
00267 
00268 //----------------------------------------------------------------------
00269 
00270 A::~A() {}
00271 B::~B() {}
00272 
00273 const char * U::name() const
00274 {
00275   static const char n[] = "U" ;
00276   return n ;
00277 }
00278 
00279 const char * V::name() const
00280 {
00281   static const char n[] = "V" ;
00282   return n ;
00283 }
00284 
00285 const char * W::name() const
00286 {
00287   static const char n[] = "W" ;
00288   return n ;
00289 }
00290 
00291 const char * X::name() const
00292 {
00293   static const char n[] = "X" ;
00294   return n ;
00295 }
00296 
00297 const char * Y::name() const
00298 {
00299   static const char n[] = "Y" ;
00300   return n ;
00301 }
00302 
00303 const char * Z::name() const
00304 {
00305   static const char n[] = "Z" ;
00306   return n ;
00307 }
00308 
00309 }
00310 }
00311 
00312 int main()
00313 {
00314   return phdmesh::unit_test::cset();
00315 }
00316 
00317 #endif
00318 
00319 
00320 

Generated on Tue Jul 13 09:27:31 2010 for Sierra Toolkit by  doxygen 1.4.7