Gaudi Framework, version v22r4

Home   Generated: Fri Sep 2 2011

KeyedObjectManager.cpp

Go to the documentation of this file.
00001 // $Id $
00002 // Include files
00003 #include "GaudiKernel/Kernel.h"
00004 #include "GaudiKernel/GaudiException.h"
00005 #include "GaudiKernel/ContainedObject.h"
00006 #include "GaudiKernel/KeyedObjectManager.h"
00007 #include <algorithm>
00008 #include <map>
00009 #include "GaudiKernel/HashMap.h"
00010 
00011 namespace Containers    {
00012   struct hashmap   {
00013     typedef GaudiUtils::HashMap<long, void*> map_type;
00014     map_type               m;
00015     std::vector<void*>     v;
00016     bool insert(void* obj, long key)    {
00017       std::pair<map_type::iterator,bool> p =
00018         m.insert(map_type::value_type(key,obj));
00019       return p.second;
00020     }
00021   };
00022   struct map   {
00023     typedef std::map<long, void*>      map_type;
00024     map_type                m;
00025     std::vector<void*>      v;
00026     bool insert(void* obj, long key)    {
00027       std::pair<map_type::iterator,bool> p =
00028         m.insert(map_type::value_type(key,obj));
00029       return p.second;
00030     }
00031   };
00032   struct array {
00033     typedef std::vector<long> map_type;
00035     std::vector<long>         m_idx;
00037     std::vector<void*>        v;
00038     struct decrement   {
00039       long m_min;
00040       decrement(long m) : m_min(m) {}
00041       bool operator()(long& j)  const {
00042         if ( j > m_min ) --j;
00043         return true;
00044       }
00045     };
00046   };
00047   struct vector {
00048     typedef std::vector<void*>  map_type;
00050     std::vector<void*>          v;
00051   };
00052 
00053   template <class CONT>
00054   class find   {
00055     const void* m_obj;
00056     typedef typename CONT::value_type v_type;
00057   public:
00058     find(const void* o) : m_obj(o) {}
00059     bool operator()(const void* cmp)  const {
00060       return cmp == m_obj;
00061     }
00062     bool operator()(const v_type& cmp)  const {
00063       return (*this)(cmp.second);
00064     }
00065   };
00066 }
00067 void Containers::cannotAssignObjectKey()   {
00068   throw GaudiException("Cannot assign key to keyed object! Object already has a key.",
00069                        "KeyedObject",
00070                        0);
00071 }
00072 void Containers::cannotInsertToContainer()   {
00073   throw GaudiException("Cannot insert element to Keyed Container!",
00074                        "KeyedContainer",
00075                        0);
00076 }
00077 
00078 void Containers::containerIsInconsistent()   {
00079   throw GaudiException("Keyed Container structures are inconsistent - severe problem!",
00080                        "KeyedContainer",
00081                        0);
00082 }
00083 
00084 void Containers::invalidContainerOperation()   {
00085   throw GaudiException("Keyed Container cannot satisfy request - severe problem!",
00086                        "KeyedContainer",
00087                        0);
00088 }
00089 
00090 template <class T>
00091 Containers::KeyedObjectManager<T>::KeyedObjectManager()
00092 : m_direct(0)
00093 {
00094   if ( sizeof(typename T::map_type) > sizeof(m_setup.buffer) )    {
00095     throw GaudiException("Basic STL contaier sizes are incompatible",
00096                          "KeyedContainer",
00097                          0);
00098   }
00099   m_setup.s = ::new(m_setup.buffer+sizeof(m_setup.s)) T();
00100   m_keyCtxt = -1;
00101 }
00102 
00103 template <class T>
00104 Containers::KeyedObjectManager<T>::~KeyedObjectManager()
00105 {
00106   m_setup.s->~T();
00107 }
00108 
00110 template <class T> void
00111 Containers::KeyedObjectManager<T>::setup(void* seq, void** rndm)
00112 {
00113   m_seq = (seq_type*)seq;
00114   *rndm = &m_setup.s->v;
00115 }
00116 
00117 template <class T>
00118 void Containers::KeyedObjectManager<T>::onDirty()   const  {
00119   m_direct = 1;
00120   for(int i = 0, stop = m_setup.s->v.size(); i < stop; i++ )   {
00121     m_setup.s->insert(*(m_setup.s->v.begin()+i), i);
00122   }
00123   m_setup.s->v.clear();
00124 }
00125 
00126 template <class T>
00127 long Containers::KeyedObjectManager<T>::insert(
00128                                 ObjectContainerBase* pBase,
00129                                 ContainedObject* pObject,
00130                                 void* obj,
00131                                 long* key)
00132 {
00133   *key = ++m_keyCtxt;
00134   return insert(pBase, pObject, obj, *key);
00135 }
00136 
00137 template <class T>
00138 long Containers::KeyedObjectManager<T>::insert(
00139                                 ObjectContainerBase* pBase,
00140                                 ContainedObject* pObject,
00141                                 void* obj,
00142                                 long key)
00143 {
00145   if ( key > m_keyCtxt )  {
00146     m_keyCtxt = key;
00147   }
00148   if ( 1==m_direct )  {
00149     if ( m_setup.s->insert(obj, key) )   {
00150       if ( !pObject->parent() )  {
00151         pObject->setParent(pBase);
00152       }
00153       m_seq->push_back(obj);
00154       return OBJ_INSERTED;
00155     }
00156   }
00157   else if ( key == long(m_setup.s->v.size()) )  {
00158     m_setup.s->v.push_back(obj);
00159     if ( !pObject->parent() )  {
00160       pObject->setParent(pBase);
00161     }
00162     m_seq->push_back(obj);
00163     return OBJ_INSERTED;
00164   }
00165   else  {
00166     // Document is dirty now...
00167     // need to copy all pointers from the vector to the map
00168     onDirty();
00169     return insert(pBase, pObject, obj, key);
00170   }
00171   cannotInsertToContainer();
00172   return OBJ_CANNOT_INSERT;
00173 }
00174 
00175 template <class T>
00176 long Containers::KeyedObjectManager<T>::insertDirect(
00177                                 ObjectContainerBase* pBase,
00178                                 ContainedObject* pObject,
00179                                 void* obj,
00180                                 long key)
00181 {
00183   if ( key > m_keyCtxt )  {
00184     m_keyCtxt = key;
00185   }
00186   if ( 1==m_direct )  {
00187     if ( m_setup.s->insert(obj, key) )   {
00188       if ( !pObject->parent() )  {
00189         pObject->setParent(pBase);
00190       }
00191       return OBJ_INSERTED;
00192     }
00193   }
00194   else if ( key == long(m_setup.s->v.size()) )  {
00195     m_setup.s->v.push_back(obj);
00196     if ( !pObject->parent() )  {
00197       pObject->setParent(pBase);
00198     }
00199     return OBJ_INSERTED;
00200   }
00201   else  {
00202     // Document is dirty now...
00203     // need to copy all pointers from the vector to the map
00204     onDirty();
00205     return insertDirect(pBase, pObject, obj, key);
00206   }
00207   cannotInsertToContainer();
00208   return OBJ_CANNOT_INSERT;
00209 }
00210 
00211 // Remove object from container
00212 template <class T>
00213 void* Containers::KeyedObjectManager<T>::erase(long  key,
00214                                                const void* obj) {
00215   typedef typename T::map_type MTYP;
00216   typedef find<MTYP> FND;
00217   if ( 1 == m_direct )   {
00218     typename T::map_type& m = m_setup.s->m;
00219     typename T::map_type::iterator i = (0==obj) ? m_setup.s->m.find(key)
00220       : std::find_if(m.begin(),m.end(),FND(obj));
00221     if ( i != m_setup.s->m.end() )   {
00222       void* o = (*i).second;
00223       seq_type::iterator j = std::find(m_seq->begin(),m_seq->end(),o);
00224       if ( j != m_seq->end() )   {
00225         m_seq->erase(j);
00226         m_setup.s->m.erase(i);
00227         return o;
00228       }
00229     }
00230     containerIsInconsistent();
00231   }
00232   onDirty();
00233   return erase(key, obj);
00234 }
00235 
00236 template <class T>
00237 void* Containers::KeyedObjectManager<T>::object(long key)  const
00238 {
00239   if ( 0 == m_direct )   {
00240     onDirty();
00241   }
00242   typename T::map_type::const_iterator i = m_setup.s->m.find(key);
00243   if ( i != m_setup.s->m.end() )  {
00244     return (*i).second;
00245   }
00246   return 0;
00247 }
00248 
00249 template <class T>
00250 void Containers::KeyedObjectManager<T>::reserve(long len)
00251 {
00252   switch( m_direct )   {
00253   case 1:
00254     break;
00255   case 0:
00256     m_setup.s->v.reserve(len);
00257     break;
00258   default:
00259     break;
00260   }
00261   m_seq->reserve(len);
00262 }
00263 
00264 template <class T>
00265 void Containers::KeyedObjectManager<T>::clear()
00266 {
00267   clearDirect();
00268   m_seq->clear();
00269 }
00270 
00271 template <class T>
00272 void Containers::KeyedObjectManager<T>::clearDirect()
00273 {
00274   typedef typename T::map_type MTYP;
00275   switch( m_direct )   {
00276   case 1:
00277     m_setup.s->m.clear();
00278     break;
00279   case 0:
00280     m_setup.s->v.clear();
00281     break;
00282   default:
00283     break;
00284   }
00285   m_direct = 0;
00286   m_keyCtxt = -1;
00287 }
00288 
00289 // Remove object by sequential iterators
00290 template <class T>
00291 long Containers::KeyedObjectManager<T>::erase(seq_type::iterator beg,
00292                                               seq_type::iterator end)
00293 {
00294   typedef typename T::map_type MTYP;
00295   typedef find<MTYP> FND;
00296   if ( 0 == m_direct )    {
00297     onDirty();
00298     return erase(beg, end);
00299   }
00300   if ( beg == m_seq->begin() && end == m_seq->end() )   {
00301     clear();
00302   }
00303   else  {
00304     for ( seq_type::iterator j=beg; j != end; ++j)  {
00305       typename T::map_type& m = m_setup.s->m;
00306       typename T::map_type::iterator i = std::find_if(m.begin(),m.end(),FND(*j));
00307       if ( i != m_setup.s->m.end() ) {
00308         m_setup.s->m.erase(i);
00309         continue;
00310       }
00311       containerIsInconsistent();
00312     }
00313     m_seq->erase(beg, end);
00314   }
00315   return OBJ_ERASED;
00316 }
00317 
00318 namespace Containers {
00319 
00320   /*  First specialize static methods and then instantiate templated class to appear as symbols in the library
00321       This order in needed for gcc 4.0 (MacOSX) */
00322 
00323   template<>
00324   CLID KeyedObjectManager< Containers::map >::classID()   {
00325     return CLID_ObjectVector+0x00030000;
00326   }
00327   template<>
00328   CLID KeyedObjectManager< Containers::hashmap >::classID()   {
00329     return CLID_ObjectVector+0x00040000;
00330   }
00331 
00332   template class KeyedObjectManager<Containers::hashmap>;
00333   template class KeyedObjectManager<Containers::map>;
00334 }
00335 
00336 /*
00337  *
00338  *
00339  *  Inline code for indirection array implementation
00340  *
00341  */
00342 typedef Containers::array __A;
00343 
00344 namespace Containers {
00345 
00346 //__forceinline
00347 template<> void*
00348 KeyedObjectManager< __A >::object(long value) const
00349 {
00350 #ifdef CHECK_KEYED_CONTAINER
00351   unsigned long siz = m_setup.s->m_idx.size();
00352   if ( value >= 0 && size_t(value) < siz )  {
00353     long ent =  *(m_setup.s->m_idx.begin()+value);
00354     if ( ent >= 0 )  {
00355       return *(m_setup.s->v.begin() + ent);
00356     }
00357   }
00358   return 0;
00359 #else
00360   return *(m_setup.s->v.begin() + (*(m_setup.s->m_idx.begin()+value)));
00361 #endif
00362 }
00363 
00364 template<>
00365 void KeyedObjectManager< __A >::onDirty()  const {
00366   m_direct = 1;
00367   m_setup.s->m_idx.reserve(m_setup.s->v.size()+1);
00368   for(int i = 0, stop = m_setup.s->v.size(); i < stop; ++i)   {
00369     if ( m_setup.s->v[i] == 0 )  {
00370       containerIsInconsistent();
00371     }
00372     m_setup.s->m_idx.push_back(i);
00373   }
00374 }
00375 
00376 // Insert new object into container
00377 template<>
00378 long KeyedObjectManager< __A >::insert(ObjectContainerBase* b,
00379                                                    ContainedObject* c,
00380                                                    void* o,
00381                                                    long* k)
00382 {
00383   // auto key creation only possible for direct access!
00384   if ( 0 == m_direct )    {
00385     m_seq->push_back(o);
00386     m_setup.s->v.push_back(o);
00387     if ( !c->parent() ) c->setParent(b);
00388     *k = ++m_keyCtxt;
00389     return OBJ_INSERTED;
00390   }
00391   cannotInsertToContainer();
00392   return OBJ_CANNOT_INSERT;
00393 }
00394 
00395 // Insert new object into container
00396 template<>
00397 long KeyedObjectManager< __A >::insert(ObjectContainerBase* b,
00398                                                    ContainedObject* c,
00399                                                    void* o,
00400                                                    long k)
00401 {
00402   if ( 0 == m_direct )    {
00403     if ( k == m_keyCtxt+1 ) {
00404       return insert(b, c, o, &k);
00405     }
00406     onDirty();
00407     return insert(b, c, o, k);
00408   }
00410   if ( k > m_keyCtxt ) m_keyCtxt = k;
00412   if ( k+1 > long(m_setup.s->m_idx.size()) )   {
00413     m_setup.s->m_idx.resize(k+1, -1);
00414   }
00415   std::vector<long>::iterator idx = m_setup.s->m_idx.begin()+k;
00416   if ( *idx == -1 )  {
00417     *idx = m_setup.s->v.size();
00418     m_setup.s->v.push_back(o);
00419     m_seq->push_back(o);
00420     if ( !c->parent() ) c->setParent(b);
00421     return OBJ_INSERTED;
00422   }
00423   cannotInsertToContainer();
00424   return OBJ_CANNOT_INSERT;
00425 }
00426 
00427 // Insert new object into container
00428 template<> long
00429 KeyedObjectManager< __A >::insertDirect(ObjectContainerBase* b,
00430                                                     ContainedObject* c,
00431                                                     void* o,
00432                                                     long k)
00433 {
00434   if ( 0 == m_direct )    {
00435     if ( k == m_keyCtxt+1 ) {
00436       m_setup.s->v.push_back(o);
00437       if ( !c->parent() ) c->setParent(b);
00438       ++m_keyCtxt;
00439       return OBJ_INSERTED;
00440     }
00441     onDirty();
00442     return insertDirect(b, c, o, k);
00443   }
00445   if ( k > m_keyCtxt ) m_keyCtxt = k;
00447   if ( k+1 > long(m_setup.s->m_idx.size()) )   {
00448     m_setup.s->m_idx.resize(k+1, -1);
00449   }
00450   std::vector<long>::iterator idx = m_setup.s->m_idx.begin()+k;
00451   if ( *idx == -1 )  {
00452     *idx = m_setup.s->v.size();
00453     m_setup.s->v.push_back(o);
00454     if ( !c->parent() ) c->setParent(b);
00455     return OBJ_INSERTED;
00456   }
00457   cannotInsertToContainer();
00458   return OBJ_CANNOT_INSERT;
00459 }
00460 
00461 // Clear content of the vector
00462 template<>
00463 void KeyedObjectManager< __A >::clearDirect() {
00464   m_setup.s->v.clear();
00465   m_setup.s->m_idx.clear();
00466   m_direct = 0;
00467   m_keyCtxt = -1;
00468 }
00469 
00470 // Remove object from container (very inefficient if key is invalid)
00471 template<>
00472 void* KeyedObjectManager< __A >::erase(long key,
00473                                                    const void* obj)
00474 {
00475   typedef std::vector<long> id_type;
00476   typedef id_type::iterator id_iter;
00477   typedef __A::map_type MTYP;
00478   typedef find<MTYP> FND;
00479   if ( 0 == m_direct )    {
00480     onDirty();
00481     return erase(key, obj);
00482   }
00483   if ( 0 != obj )   {
00484     id_type& idx = m_setup.s->m_idx;
00485     for ( id_iter i=idx.begin(); i != idx.end(); i++ )    {
00486       seq_type::iterator j = m_setup.s->v.begin()+(*i);
00487       seq_type::iterator k = std::find(m_seq->begin(),m_seq->end(),*j);
00488       if ( *j == obj )   {
00489         void* o = *j;
00490         m_seq->erase(k);
00491         m_setup.s->v.erase(j);
00492         std::for_each(m_setup.s->m_idx.begin(),
00493                       m_setup.s->m_idx.end(),
00494                       array::decrement(*i));
00495         *i = -1;
00496         return o;
00497       }
00498     }
00499   }
00500   else if ( key >= 0 && key < long(m_setup.s->m_idx.size()) )   {
00501     id_iter idx = m_setup.s->m_idx.begin()+key;
00502     if ( *idx != -1 )   {
00503       seq_type::iterator i = m_setup.s->v.begin()+(*idx);
00504       if ( i == m_setup.s->v.end() )   {
00505         containerIsInconsistent();
00506       }
00507       void* o = *i;
00508       seq_type::iterator j=std::find(m_seq->begin(),m_seq->end(),o);
00509       if ( j == m_seq->end() )   {
00510         containerIsInconsistent();
00511       }
00512       m_seq->erase(j);
00513       m_setup.s->v.erase(i);
00514       std::for_each(m_setup.s->m_idx.begin(),
00515                     m_setup.s->m_idx.end(),
00516                     array::decrement(*idx));
00517       *idx = -1;
00518       return o;
00519     }
00520   }
00521   containerIsInconsistent();
00522   return 0;
00523 }
00524 
00525 // Remove object by sequential iterators
00526 template<>
00527 long KeyedObjectManager< __A >::erase(seq_type::iterator beg,
00528                                                   seq_type::iterator end)
00529 {
00530   typedef std::vector<long> id_type;
00531   typedef id_type::iterator id_iter;
00532   if ( beg == m_seq->begin() && end == m_seq->end() )   {
00533     clear();
00534     return OBJ_ERASED;
00535   }
00536   else if ( 0 == m_direct )    {
00537     onDirty();
00538     return erase(beg, end);
00539   }
00540   else  {
00541     long cnt = 0, nobj = end-beg;
00542     id_type& idx = m_setup.s->m_idx;
00543     for ( id_iter i=idx.begin(); i != idx.end(); i++ )    {
00544       seq_type::iterator j = m_setup.s->v.begin()+(*i);
00545       seq_type::iterator k = std::find(beg,end,*j);
00546       if ( k != end )   {
00547         m_setup.s->v.erase(j);
00548         std::for_each(m_setup.s->m_idx.begin(),
00549                       m_setup.s->m_idx.end(),
00550                       array::decrement(*i));
00551         *i = -1;
00552         cnt++;
00553         if ( cnt == nobj ) break;
00554       }
00555     }
00556     m_seq->erase(beg, end);
00557     if ( cnt != nobj )  {
00558       containerIsInconsistent();
00559     }
00560     return OBJ_ERASED;
00561   }
00562   // cannot reach this point
00563 }
00564 
00565 template<>
00566 CLID KeyedObjectManager< __A >::classID()   {
00567   return CLID_ObjectVector+0x00050000;
00568 }
00569 }
00570 template class Containers::KeyedObjectManager<__A>;
00571 /*
00572   *
00573   *
00574   *  Implementation for objects with vector like access
00575   *
00576   *
00577   **/
00578 typedef Containers::vector __V;
00579 
00580 namespace Containers {
00581 // Access single entry by long(integer) key
00582 template<>
00583 void* KeyedObjectManager< __V >::object(long /* value */) const
00584 {
00585   invalidContainerOperation();
00586   return 0;
00587 }
00588 
00589 template<>
00590 void KeyedObjectManager<__V>::onDirty()   const  {
00591   invalidContainerOperation();
00592 }
00593 
00594 // Insert new object into container
00595 template<>
00596 long KeyedObjectManager< __V >::insert(ObjectContainerBase* b,
00597                                                    ContainedObject* c,
00598                                                    void* o,
00599                                                    long* k)
00600 {
00601   m_seq->push_back(o);
00602   m_setup.s->v.push_back(o);
00603   if ( !c->parent() ) c->setParent(b);
00604   *k = (m_setup.s->v.size()-1);
00605   return OBJ_INSERTED;
00606 }
00607 
00608 // Insert new object into container
00609 template<>
00610 long KeyedObjectManager< __V >::insert(ObjectContainerBase* b,
00611                                                    ContainedObject* c,
00612                                                    void* o,
00613                                                    long k)
00614 {
00615   if ( k == long(m_setup.s->v.size()) ) {
00616     return insert(b, c, o, &k);
00617   }
00618   cannotInsertToContainer();
00619   return OBJ_CANNOT_INSERT;
00620 }
00621 
00622 // Insert new object into container
00623 template<> long
00624 KeyedObjectManager< __V >::insertDirect(ObjectContainerBase* b,
00625                                                     ContainedObject* c,
00626                                                     void* o,
00627                                                     long k)
00628 {
00629   if ( k == long(m_setup.s->v.size()) ) {
00630     m_setup.s->v.push_back(o);
00631     if ( !c->parent() ) c->setParent(b);
00632     return OBJ_INSERTED;
00633   }
00634   cannotInsertToContainer();
00635   return OBJ_CANNOT_INSERT;
00636 }
00637 
00638 // Clear content of the vector
00639 template<>
00640 void KeyedObjectManager< __V >::clearDirect()  {
00641   m_setup.s->v.clear();
00642   m_direct = 0;
00643   m_keyCtxt = -1;
00644 }
00645 
00646 // Remove object from container (very inefficient if key is invalid)
00647 template<> void*
00648 KeyedObjectManager< __V >::erase(long /* key */,
00649                                              const void* /* obj */)
00650 {
00651   invalidContainerOperation();
00652   return 0;
00653 }
00654 
00655 // Remove object by sequential iterators
00656 template<>
00657 long KeyedObjectManager< __V >::erase(seq_type::iterator beg,
00658                                                   seq_type::iterator end)
00659 {
00660   if ( beg == m_seq->begin() && end == m_seq->end() )   {
00661     clear();
00662     return OBJ_ERASED;
00663   }
00664   invalidContainerOperation();
00665   return OBJ_ERASED;
00666 }
00667 
00668 template<>
00669 CLID KeyedObjectManager< __V >::classID()   {
00670   return CLID_ObjectVector+0x00060000;
00671 }
00672 
00673 }
00674 template class Containers::KeyedObjectManager<__V>;
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Fri Sep 2 2011 16:24:43 for Gaudi Framework, version v22r4 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004