![]() |
|
|
Generated: 24 Nov 2008 |
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 invalidContainerOperation(); 00563 return 0; 00564 } 00565 00566 template<> 00567 CLID KeyedObjectManager< __A >::classID() { 00568 return CLID_ObjectVector+0x00050000; 00569 } 00570 } 00571 template class Containers::KeyedObjectManager<__A>; 00572 /* 00573 * 00574 * 00575 * Implementation for objects with vector like access 00576 * 00577 * 00578 **/ 00579 typedef Containers::vector __V; 00580 00581 namespace Containers { 00582 // Access single entry by long(integer) key 00583 template<> 00584 void* KeyedObjectManager< __V >::object(long /* value */) const 00585 { 00586 invalidContainerOperation(); 00587 return 0; 00588 } 00589 00590 template<> 00591 void KeyedObjectManager<__V>::onDirty() const { 00592 invalidContainerOperation(); 00593 } 00594 00595 // Insert new object into container 00596 template<> 00597 long KeyedObjectManager< __V >::insert(ObjectContainerBase* b, 00598 ContainedObject* c, 00599 void* o, 00600 long* k) 00601 { 00602 m_seq->push_back(o); 00603 m_setup.s->v.push_back(o); 00604 if ( !c->parent() ) c->setParent(b); 00605 *k = (m_setup.s->v.size()-1); 00606 return OBJ_INSERTED; 00607 } 00608 00609 // Insert new object into container 00610 template<> 00611 long KeyedObjectManager< __V >::insert(ObjectContainerBase* b, 00612 ContainedObject* c, 00613 void* o, 00614 long k) 00615 { 00616 if ( k == long(m_setup.s->v.size()) ) { 00617 return insert(b, c, o, &k); 00618 } 00619 cannotInsertToContainer(); 00620 return OBJ_CANNOT_INSERT; 00621 } 00622 00623 // Insert new object into container 00624 template<> long 00625 KeyedObjectManager< __V >::insertDirect(ObjectContainerBase* b, 00626 ContainedObject* c, 00627 void* o, 00628 long k) 00629 { 00630 if ( k == long(m_setup.s->v.size()) ) { 00631 m_setup.s->v.push_back(o); 00632 if ( !c->parent() ) c->setParent(b); 00633 return OBJ_INSERTED; 00634 } 00635 cannotInsertToContainer(); 00636 return OBJ_CANNOT_INSERT; 00637 } 00638 00639 // Clear content of the vector 00640 template<> 00641 void KeyedObjectManager< __V >::clearDirect() { 00642 m_setup.s->v.clear(); 00643 m_direct = 0; 00644 m_keyCtxt = -1; 00645 } 00646 00647 // Remove object from container (very inefficient if key is invalid) 00648 template<> void* 00649 KeyedObjectManager< __V >::erase(long /* key */, 00650 const void* /* obj */) 00651 { 00652 invalidContainerOperation(); 00653 return 0; 00654 } 00655 00656 // Remove object by sequential iterators 00657 template<> 00658 long KeyedObjectManager< __V >::erase(seq_type::iterator beg, 00659 seq_type::iterator end) 00660 { 00661 if ( beg == m_seq->begin() && end == m_seq->end() ) { 00662 clear(); 00663 return OBJ_ERASED; 00664 } 00665 invalidContainerOperation(); 00666 return OBJ_ERASED; 00667 } 00668 00669 template<> 00670 CLID KeyedObjectManager< __V >::classID() { 00671 return CLID_ObjectVector+0x00060000; 00672 } 00673 00674 } 00675 template class Containers::KeyedObjectManager<__V>;