| # Gaudi Framework, version v21r10p1 |

Home |  | Generated: 29 Jul 2010

# 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>;