00001
00002
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
00167
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
00203
00204 onDirty();
00205 return insertDirect(pBase, pObject, obj, key);
00206 }
00207 cannotInsertToContainer();
00208 return OBJ_CANNOT_INSERT;
00209 }
00210
00211
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
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
00321
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
00340
00341
00342 typedef Containers::array __A;
00343
00344 namespace Containers {
00345
00346
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
00377 template<>
00378 long KeyedObjectManager< __A >::insert(ObjectContainerBase* b,
00379 ContainedObject* c,
00380 void* o,
00381 long* k)
00382 {
00383
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
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
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
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
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
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
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
00575
00576
00577
00578 typedef Containers::vector __V;
00579
00580 namespace Containers {
00581
00582 template<>
00583 void* KeyedObjectManager< __V >::object(long ) const
00584 {
00585 invalidContainerOperation();
00586 return 0;
00587 }
00588
00589 template<>
00590 void KeyedObjectManager<__V>::onDirty() const {
00591 invalidContainerOperation();
00592 }
00593
00594
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
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
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
00639 template<>
00640 void KeyedObjectManager< __V >::clearDirect() {
00641 m_setup.s->v.clear();
00642 m_direct = 0;
00643 m_keyCtxt = -1;
00644 }
00645
00646
00647 template<> void*
00648 KeyedObjectManager< __V >::erase(long ,
00649 const void* )
00650 {
00651 invalidContainerOperation();
00652 return 0;
00653 }
00654
00655
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>;