| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
KeyedObjectManager.cpp
Go to the documentation of this file.
1 // $Id $
2 // Include files
3 #include "GaudiKernel/Kernel.h"
4 #include "GaudiKernel/GaudiException.h"
5 #include "GaudiKernel/ContainedObject.h"
6 #include "GaudiKernel/KeyedObjectManager.h"
7 #include <algorithm>
8 #include <map>
9 #include "GaudiKernel/HashMap.h"
10
11 namespace Containers {
12 struct hashmap {
13 typedef GaudiUtils::HashMap<long, void*> map_type;
14 map_type m;
15 std::vector<void*> v;
16 bool insert(void* obj, long key) {
17 std::pair<map_type::iterator,bool> p =
18 m.insert(map_type::value_type(key,obj));
19 return p.second;
20 }
21 };
22 struct map {
23 typedef std::map<long, void*> map_type;
24 map_type m;
25 std::vector<void*> v;
26 bool insert(void* obj, long key) {
27 std::pair<map_type::iterator,bool> p =
28 m.insert(map_type::value_type(key,obj));
29 return p.second;
30 }
31 };
32 struct array {
33 typedef std::vector<long> map_type;
35 std::vector<long> m_idx;
37 std::vector<void*> v;
38 struct decrement {
39 long m_min;
40 decrement(long m) : m_min(m) {}
41 bool operator()(long& j) const {
42 if ( j > m_min ) --j;
43 return true;
44 }
45 };
46 };
47 struct vector {
48 typedef std::vector<void*> map_type;
50 std::vector<void*> v;
51 };
52
53 template <class CONT>
54 class find {
55 const void* m_obj;
56 typedef typename CONT::value_type v_type;
57 public:
58 find(const void* o) : m_obj(o) {}
59 bool operator()(const void* cmp) const {
60 return cmp == m_obj;
61 }
62 bool operator()(const v_type& cmp) const {
63 return (*this)(cmp.second);
64 }
65 };
66 }
67 void Containers::cannotAssignObjectKey() {
68 throw GaudiException("Cannot assign key to keyed object! Object already has a key.",
69 "KeyedObject",
70 0);
71 }
72 void Containers::cannotInsertToContainer() {
73 throw GaudiException("Cannot insert element to Keyed Container!",
74 "KeyedContainer",
75 0);
76 }
77
78 void Containers::containerIsInconsistent() {
79 throw GaudiException("Keyed Container structures are inconsistent - severe problem!",
80 "KeyedContainer",
81 0);
82 }
83
84 void Containers::invalidContainerOperation() {
85 throw GaudiException("Keyed Container cannot satisfy request - severe problem!",
86 "KeyedContainer",
87 0);
88 }
89
90 template <class T>
91 Containers::KeyedObjectManager<T>::KeyedObjectManager()
92 : m_direct(0)
93 {
94 if ( sizeof(typename T::map_type) > sizeof(m_setup.buffer) ) {
95 throw GaudiException("Basic STL contaier sizes are incompatible",
96 "KeyedContainer",
97 0);
98 }
99 m_setup.s = ::new(m_setup.buffer+sizeof(m_setup.s)) T();
100 m_keyCtxt = -1;
101 }
102
103 template <class T>
104 Containers::KeyedObjectManager<T>::~KeyedObjectManager()
105 {
106 m_setup.s->~T();
107 }
108
110 template <class T> void
111 Containers::KeyedObjectManager<T>::setup(void* seq, void** rndm)
112 {
113 m_seq = (seq_type*)seq;
114 *rndm = &m_setup.s->v;
115 }
116
117 template <class T>
118 void Containers::KeyedObjectManager<T>::onDirty() const {
119 m_direct = 1;
120 for(int i = 0, stop = m_setup.s->v.size(); i < stop; i++ ) {
121 m_setup.s->insert(*(m_setup.s->v.begin()+i), i);
122 }
123 m_setup.s->v.clear();
124 }
125
126 template <class T>
127 long Containers::KeyedObjectManager<T>::insert(
128 ObjectContainerBase* pBase,
129 ContainedObject* pObject,
130 void* obj,
131 long* key)
132 {
133 *key = ++m_keyCtxt;
134 return insert(pBase, pObject, obj, *key);
135 }
136
137 template <class T>
138 long Containers::KeyedObjectManager<T>::insert(
139 ObjectContainerBase* pBase,
140 ContainedObject* pObject,
141 void* obj,
142 long key)
143 {
145 if ( key > m_keyCtxt ) {
146 m_keyCtxt = key;
147 }
148 if ( 1==m_direct ) {
149 if ( m_setup.s->insert(obj, key) ) {
150 if ( !pObject->parent() ) {
151 pObject->setParent(pBase);
152 }
153 m_seq->push_back(obj);
154 return OBJ_INSERTED;
155 }
156 }
157 else if ( key == long(m_setup.s->v.size()) ) {
158 m_setup.s->v.push_back(obj);
159 if ( !pObject->parent() ) {
160 pObject->setParent(pBase);
161 }
162 m_seq->push_back(obj);
163 return OBJ_INSERTED;
164 }
165 else {
166 // Document is dirty now...
167 // need to copy all pointers from the vector to the map
168 onDirty();
169 return insert(pBase, pObject, obj, key);
170 }
171 cannotInsertToContainer();
172 return OBJ_CANNOT_INSERT;
173 }
174
175 template <class T>
176 long Containers::KeyedObjectManager<T>::insertDirect(
177 ObjectContainerBase* pBase,
178 ContainedObject* pObject,
179 void* obj,
180 long key)
181 {
183 if ( key > m_keyCtxt ) {
184 m_keyCtxt = key;
185 }
186 if ( 1==m_direct ) {
187 if ( m_setup.s->insert(obj, key) ) {
188 if ( !pObject->parent() ) {
189 pObject->setParent(pBase);
190 }
191 return OBJ_INSERTED;
192 }
193 }
194 else if ( key == long(m_setup.s->v.size()) ) {
195 m_setup.s->v.push_back(obj);
196 if ( !pObject->parent() ) {
197 pObject->setParent(pBase);
198 }
199 return OBJ_INSERTED;
200 }
201 else {
202 // Document is dirty now...
203 // need to copy all pointers from the vector to the map
204 onDirty();
205 return insertDirect(pBase, pObject, obj, key);
206 }
207 cannotInsertToContainer();
208 return OBJ_CANNOT_INSERT;
209 }
210
211 // Remove object from container
212 template <class T>
213 void* Containers::KeyedObjectManager<T>::erase(long key,
214 const void* obj) {
215 typedef typename T::map_type MTYP;
216 typedef find<MTYP> FND;
217 if ( 1 == m_direct ) {
218 typename T::map_type& m = m_setup.s->m;
219 typename T::map_type::iterator i = (0==obj) ? m_setup.s->m.find(key)
220 : std::find_if(m.begin(),m.end(),FND(obj));
221 if ( i != m_setup.s->m.end() ) {
222 void* o = (*i).second;
223 seq_type::iterator j = std::find(m_seq->begin(),m_seq->end(),o);
224 if ( j != m_seq->end() ) {
225 m_seq->erase(j);
226 m_setup.s->m.erase(i);
227 return o;
228 }
229 }
230 containerIsInconsistent();
231 }
232 onDirty();
233 return erase(key, obj);
234 }
235
236 template <class T>
237 void* Containers::KeyedObjectManager<T>::object(long key) const
238 {
239 if ( 0 == m_direct ) {
240 onDirty();
241 }
242 typename T::map_type::const_iterator i = m_setup.s->m.find(key);
243 if ( i != m_setup.s->m.end() ) {
244 return (*i).second;
245 }
246 return 0;
247 }
248
249 template <class T>
250 void Containers::KeyedObjectManager<T>::reserve(long len)
251 {
252 switch( m_direct ) {
253 case 1:
254 break;
255 case 0:
256 m_setup.s->v.reserve(len);
257 break;
258 default:
259 break;
260 }
261 m_seq->reserve(len);
262 }
263
264 template <class T>
265 void Containers::KeyedObjectManager<T>::clear()
266 {
267 clearDirect();
268 m_seq->clear();
269 }
270
271 template <class T>
272 void Containers::KeyedObjectManager<T>::clearDirect()
273 {
274 typedef typename T::map_type MTYP;
275 switch( m_direct ) {
276 case 1:
277 m_setup.s->m.clear();
278 break;
279 case 0:
280 m_setup.s->v.clear();
281 break;
282 default:
283 break;
284 }
285 m_direct = 0;
286 m_keyCtxt = -1;
287 }
288
289 // Remove object by sequential iterators
290 template <class T>
291 long Containers::KeyedObjectManager<T>::erase(seq_type::iterator beg,
292 seq_type::iterator end)
293 {
294 typedef typename T::map_type MTYP;
295 typedef find<MTYP> FND;
296 if ( 0 == m_direct ) {
297 onDirty();
298 return erase(beg, end);
299 }
300 if ( beg == m_seq->begin() && end == m_seq->end() ) {
301 clear();
302 }
303 else {
304 for ( seq_type::iterator j=beg; j != end; ++j) {
305 typename T::map_type& m = m_setup.s->m;
306 typename T::map_type::iterator i = std::find_if(m.begin(),m.end(),FND(*j));
307 if ( i != m_setup.s->m.end() ) {
308 m_setup.s->m.erase(i);
309 continue;
310 }
311 containerIsInconsistent();
312 }
313 m_seq->erase(beg, end);
314 }
315 return OBJ_ERASED;
316 }
317
318 namespace Containers {
319
320 /* First specialize static methods and then instantiate templated class to appear as symbols in the library
321 This order in needed for gcc 4.0 (MacOSX) */
322
323 template<>
324 CLID KeyedObjectManager< Containers::map >::classID() {
325 return CLID_ObjectVector+0x00030000;
326 }
327 template<>
328 CLID KeyedObjectManager< Containers::hashmap >::classID() {
329 return CLID_ObjectVector+0x00040000;
330 }
331
332 template class KeyedObjectManager<Containers::hashmap>;
333 template class KeyedObjectManager<Containers::map>;
334 }
335
336 /*
337 *
338 *
339 * Inline code for indirection array implementation
340 *
341 */
342 typedef Containers::array __A;
343
344 namespace Containers {
345
346 //__forceinline
347 template<> void*
348 KeyedObjectManager< __A >::object(long value) const
349 {
350 #ifdef CHECK_KEYED_CONTAINER
351 unsigned long siz = m_setup.s->m_idx.size();
352 if ( value >= 0 && size_t(value) < siz ) {
353 long ent = *(m_setup.s->m_idx.begin()+value);
354 if ( ent >= 0 ) {
355 return *(m_setup.s->v.begin() + ent);
356 }
357 }
358 return 0;
359 #else
360 return *(m_setup.s->v.begin() + (*(m_setup.s->m_idx.begin()+value)));
361 #endif
362 }
363
364 template<>
365 void KeyedObjectManager< __A >::onDirty() const {
366 m_direct = 1;
367 m_setup.s->m_idx.reserve(m_setup.s->v.size()+1);
368 for(int i = 0, stop = m_setup.s->v.size(); i < stop; ++i) {
369 if ( m_setup.s->v[i] == 0 ) {
370 containerIsInconsistent();
371 }
372 m_setup.s->m_idx.push_back(i);
373 }
374 }
375
376 // Insert new object into container
377 template<>
378 long KeyedObjectManager< __A >::insert(ObjectContainerBase* b,
379 ContainedObject* c,
380 void* o,
381 long* k)
382 {
383 // auto key creation only possible for direct access!
384 if ( 0 == m_direct ) {
385 m_seq->push_back(o);
386 m_setup.s->v.push_back(o);
387 if ( !c->parent() ) c->setParent(b);
388 *k = ++m_keyCtxt;
389 return OBJ_INSERTED;
390 }
391 cannotInsertToContainer();
392 return OBJ_CANNOT_INSERT;
393 }
394
395 // Insert new object into container
396 template<>
397 long KeyedObjectManager< __A >::insert(ObjectContainerBase* b,
398 ContainedObject* c,
399 void* o,
400 long k)
401 {
402 if ( 0 == m_direct ) {
403 if ( k == m_keyCtxt+1 ) {
404 return insert(b, c, o, &k);
405 }
406 onDirty();
407 return insert(b, c, o, k);
408 }
410 if ( k > m_keyCtxt ) m_keyCtxt = k;
412 if ( k+1 > long(m_setup.s->m_idx.size()) ) {
413 m_setup.s->m_idx.resize(k+1, -1);
414 }
415 std::vector<long>::iterator idx = m_setup.s->m_idx.begin()+k;
416 if ( *idx == -1 ) {
417 *idx = m_setup.s->v.size();
418 m_setup.s->v.push_back(o);
419 m_seq->push_back(o);
420 if ( !c->parent() ) c->setParent(b);
421 return OBJ_INSERTED;
422 }
423 cannotInsertToContainer();
424 return OBJ_CANNOT_INSERT;
425 }
426
427 // Insert new object into container
428 template<> long
429 KeyedObjectManager< __A >::insertDirect(ObjectContainerBase* b,
430 ContainedObject* c,
431 void* o,
432 long k)
433 {
434 if ( 0 == m_direct ) {
435 if ( k == m_keyCtxt+1 ) {
436 m_setup.s->v.push_back(o);
437 if ( !c->parent() ) c->setParent(b);
438 ++m_keyCtxt;
439 return OBJ_INSERTED;
440 }
441 onDirty();
442 return insertDirect(b, c, o, k);
443 }
445 if ( k > m_keyCtxt ) m_keyCtxt = k;
447 if ( k+1 > long(m_setup.s->m_idx.size()) ) {
448 m_setup.s->m_idx.resize(k+1, -1);
449 }
450 std::vector<long>::iterator idx = m_setup.s->m_idx.begin()+k;
451 if ( *idx == -1 ) {
452 *idx = m_setup.s->v.size();
453 m_setup.s->v.push_back(o);
454 if ( !c->parent() ) c->setParent(b);
455 return OBJ_INSERTED;
456 }
457 cannotInsertToContainer();
458 return OBJ_CANNOT_INSERT;
459 }
460
461 // Clear content of the vector
462 template<>
463 void KeyedObjectManager< __A >::clearDirect() {
464 m_setup.s->v.clear();
465 m_setup.s->m_idx.clear();
466 m_direct = 0;
467 m_keyCtxt = -1;
468 }
469
470 // Remove object from container (very inefficient if key is invalid)
471 template<>
472 void* KeyedObjectManager< __A >::erase(long key,
473 const void* obj)
474 {
475 typedef std::vector<long> id_type;
476 typedef id_type::iterator id_iter;
477 typedef __A::map_type MTYP;
478 typedef find<MTYP> FND;
479 if ( 0 == m_direct ) {
480 onDirty();
481 return erase(key, obj);
482 }
483 if ( 0 != obj ) {
484 id_type& idx = m_setup.s->m_idx;
485 for ( id_iter i=idx.begin(); i != idx.end(); i++ ) {
486 seq_type::iterator j = m_setup.s->v.begin()+(*i);
487 seq_type::iterator k = std::find(m_seq->begin(),m_seq->end(),*j);
488 if ( *j == obj ) {
489 void* o = *j;
490 m_seq->erase(k);
491 m_setup.s->v.erase(j);
492 std::for_each(m_setup.s->m_idx.begin(),
493 m_setup.s->m_idx.end(),
494 array::decrement(*i));
495 *i = -1;
496 return o;
497 }
498 }
499 }
500 else if ( key >= 0 && key < long(m_setup.s->m_idx.size()) ) {
501 id_iter idx = m_setup.s->m_idx.begin()+key;
502 if ( *idx != -1 ) {
503 seq_type::iterator i = m_setup.s->v.begin()+(*idx);
504 if ( i == m_setup.s->v.end() ) {
505 containerIsInconsistent();
506 }
507 void* o = *i;
508 seq_type::iterator j=std::find(m_seq->begin(),m_seq->end(),o);
509 if ( j == m_seq->end() ) {
510 containerIsInconsistent();
511 }
512 m_seq->erase(j);
513 m_setup.s->v.erase(i);
514 std::for_each(m_setup.s->m_idx.begin(),
515 m_setup.s->m_idx.end(),
516 array::decrement(*idx));
517 *idx = -1;
518 return o;
519 }
520 }
521 containerIsInconsistent();
522 return 0;
523 }
524
525 // Remove object by sequential iterators
526 template<>
527 long KeyedObjectManager< __A >::erase(seq_type::iterator beg,
528 seq_type::iterator end)
529 {
530 typedef std::vector<long> id_type;
531 typedef id_type::iterator id_iter;
532 if ( beg == m_seq->begin() && end == m_seq->end() ) {
533 clear();
534 return OBJ_ERASED;
535 }
536 else if ( 0 == m_direct ) {
537 onDirty();
538 return erase(beg, end);
539 }
540 else {
541 long cnt = 0, nobj = end-beg;
542 id_type& idx = m_setup.s->m_idx;
543 for ( id_iter i=idx.begin(); i != idx.end(); i++ ) {
544 seq_type::iterator j = m_setup.s->v.begin()+(*i);
545 seq_type::iterator k = std::find(beg,end,*j);
546 if ( k != end ) {
547 m_setup.s->v.erase(j);
548 std::for_each(m_setup.s->m_idx.begin(),
549 m_setup.s->m_idx.end(),
550 array::decrement(*i));
551 *i = -1;
552 cnt++;
553 if ( cnt == nobj ) break;
554 }
555 }
556 m_seq->erase(beg, end);
557 if ( cnt != nobj ) {
558 containerIsInconsistent();
559 }
560 return OBJ_ERASED;
561 }
562 // cannot reach this point
563 }
564
565 template<>
566 CLID KeyedObjectManager< __A >::classID() {
567 return CLID_ObjectVector+0x00050000;
568 }
569 }
570 template class Containers::KeyedObjectManager<__A>;
571 /*
572 *
573 *
574 * Implementation for objects with vector like access
575 *
576 *
577 **/
578 typedef Containers::vector __V;
579
580 namespace Containers {
581 // Access single entry by long(integer) key
582 template<>
583 void* KeyedObjectManager< __V >::object(long /* value */) const
584 {
585 invalidContainerOperation();
586 return 0;
587 }
588
589 template<>
590 void KeyedObjectManager<__V>::onDirty() const {
591 invalidContainerOperation();
592 }
593
594 // Insert new object into container
595 template<>
596 long KeyedObjectManager< __V >::insert(ObjectContainerBase* b,
597 ContainedObject* c,
598 void* o,
599 long* k)
600 {
601 m_seq->push_back(o);
602 m_setup.s->v.push_back(o);
603 if ( !c->parent() ) c->setParent(b);
604 *k = (m_setup.s->v.size()-1);
605 return OBJ_INSERTED;
606 }
607
608 // Insert new object into container
609 template<>
610 long KeyedObjectManager< __V >::insert(ObjectContainerBase* b,
611 ContainedObject* c,
612 void* o,
613 long k)
614 {
615 if ( k == long(m_setup.s->v.size()) ) {
616 return insert(b, c, o, &k);
617 }
618 cannotInsertToContainer();
619 return OBJ_CANNOT_INSERT;
620 }
621
622 // Insert new object into container
623 template<> long
624 KeyedObjectManager< __V >::insertDirect(ObjectContainerBase* b,
625 ContainedObject* c,
626 void* o,
627 long k)
628 {
629 if ( k == long(m_setup.s->v.size()) ) {
630 m_setup.s->v.push_back(o);
631 if ( !c->parent() ) c->setParent(b);
632 return OBJ_INSERTED;
633 }
634 cannotInsertToContainer();
635 return OBJ_CANNOT_INSERT;
636 }
637
638 // Clear content of the vector
639 template<>
640 void KeyedObjectManager< __V >::clearDirect() {
641 m_setup.s->v.clear();
642 m_direct = 0;
643 m_keyCtxt = -1;
644 }
645
646 // Remove object from container (very inefficient if key is invalid)
647 template<> void*
648 KeyedObjectManager< __V >::erase(long /* key */,
649 const void* /* obj */)
650 {
651 invalidContainerOperation();
652 return 0;
653 }
654
655 // Remove object by sequential iterators
656 template<>
657 long KeyedObjectManager< __V >::erase(seq_type::iterator beg,
658 seq_type::iterator end)
659 {
660 if ( beg == m_seq->begin() && end == m_seq->end() ) {
661 clear();
662 return OBJ_ERASED;
663 }
664 invalidContainerOperation();
665 return OBJ_ERASED;
666 }
667
668 template<>
669 CLID KeyedObjectManager< __V >::classID() {
670 return CLID_ObjectVector+0x00060000;
671 }
672
673 }
674 template class Containers::KeyedObjectManager<__V>;