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"
7 #include <algorithm>
8 #include <map>
9 #include "GaudiKernel/HashMap.h"
10 
11 namespace Containers {
12  struct hashmap {
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;
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 }
68  throw GaudiException("Cannot assign key to keyed object! Object already has a key.",
69  "KeyedObject",
70  0);
71 }
73  throw GaudiException("Cannot insert element to Keyed Container!",
74  "KeyedContainer",
75  0);
76 }
77 
79  throw GaudiException("Keyed Container structures are inconsistent - severe problem!",
80  "KeyedContainer",
81  0);
82 }
83 
85  throw GaudiException("Keyed Container cannot satisfy request - severe problem!",
86  "KeyedContainer",
87  0);
88 }
89 
90 template <class T>
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>
105 {
106  m_setup.s->~T();
107 }
108 
110 template <class T> void
112 {
113  m_seq = (seq_type*)seq;
114  *rndm = &m_setup.s->v;
115 }
116 
117 template <class T>
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>
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>
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  }
172  return OBJ_CANNOT_INSERT;
173 }
174 
175 template <class T>
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  }
208  return OBJ_CANNOT_INSERT;
209 }
210 
211 // Remove object from container
212 template <class T>
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  }
231  }
232  onDirty();
233  return erase(key, obj);
234 }
235 
236 template <class T>
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>
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>
266 {
267  clearDirect();
268  m_seq->clear();
269 }
270 
271 template <class T>
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  }
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<>
325  return CLID_ObjectVector+0x00030000;
326  }
327  template<>
329  return CLID_ObjectVector+0x00040000;
330  }
331 
334 }
335 
336 /*
337  *
338  *
339  * Inline code for indirection array implementation
340  *
341  */
343 
344 namespace Containers {
345 
346 //__forceinline
347 template<> void*
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<>
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 ) {
371  }
372  m_setup.s->m_idx.push_back(i);
373  }
374 }
375 
376 // Insert new object into container
377 template<>
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  }
392  return OBJ_CANNOT_INSERT;
393 }
394 
395 // Insert new object into container
396 template<>
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  }
424  return OBJ_CANNOT_INSERT;
425 }
426 
427 // Insert new object into container
428 template<> long
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  }
458  return OBJ_CANNOT_INSERT;
459 }
460 
461 // Clear content of the vector
462 template<>
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<>
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() ) {
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() ) {
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  }
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 ) {
559  }
560  return OBJ_ERASED;
561  }
562  // cannot reach this point
563 }
564 
565 template<>
567  return CLID_ObjectVector+0x00050000;
568 }
569 }
571 /*
572  *
573  *
574  * Implementation for objects with vector like access
575  *
576  *
577  **/
579 
580 namespace Containers {
581 // Access single entry by long(integer) key
582 template<>
583 void* KeyedObjectManager< __V >::object(long /* value */) const
584 {
586  return 0;
587 }
588 
589 template<>
592 }
593 
594 // Insert new object into container
595 template<>
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<>
612  void* o,
613  long k)
614 {
615  if ( k == long(m_setup.s->v.size()) ) {
616  return insert(b, c, o, &k);
617  }
619  return OBJ_CANNOT_INSERT;
620 }
621 
622 // Insert new object into container
623 template<> long
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  }
635  return OBJ_CANNOT_INSERT;
636 }
637 
638 // Clear content of the vector
639 template<>
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*
649  const void* /* obj */)
650 {
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  }
665  return OBJ_ERASED;
666 }
667 
668 template<>
670  return CLID_ObjectVector+0x00060000;
671 }
672 
673 }
Object was inserted into the container.
Definition: KeyedTraits.h:24
Containers::vector __V
Define general base for Gaudi exception.
std::vector< void * > v
std::vector< void * > map_type
virtual ~KeyedObjectManager()
Standard Destructor.
void clear()
Clear content of the vector.
CONT::value_type v_type
std::vector< long > map_type
tuple c
Definition: gaudirun.py:341
union Containers::KeyedObjectManager::@6 m_setup
GAUDI_API void containerIsInconsistent()
Function to be called to indicate that the container is found to be inconsistent. ...
void clearDirect()
Clear all direct access fields.
std::vector< long > m_idx
Indirection array.
void * object(long key) const
Retrieve object identified by a key from the container.
void * erase(long key, const void *obj)
Remove object from container (very inefficient if key is invalid)
std::map< long, void * > map_type
const ObjectContainerBase * parent() const
Access to parent object.
bool insert(void *obj, long key)
GAUDI_API void cannotInsertToContainer()
Function to be called to indicate that an object cannot be inserted to the container.
std::vector< void * > v
Direct access array.
std::pair< iterator, bool > insert(const value_type &val)
Definition: Map.h:165
void reserve(long size)
Reserve buffer space.
Cannot insert object into container.
Definition: KeyedTraits.h:25
GAUDI_API void invalidContainerOperation()
Function to be called to indicate that an operation should be performed on the container or it's cont...
std::pair< const long, void * > value_type
Definition: Map.h:94
GaudiUtils::HashMap< long, void * > map_type
void onDirty() const
Callback when the container becomes dirty.
long insert(ObjectContainerBase *b, ContainedObject *c, void *o, long *k)
Insert new object into container.
unsigned int CLID
Class ID definition.
Definition: ClassID.h:9
std::vector< void * > seq_type
bool operator()(const v_type &cmp) const
tuple end
Definition: IOTest.py:101
Object was removed, but not deleted.
Definition: KeyedTraits.h:23
All classes that their objects may be contained in an LHCb ObjectContainer (e.g.
GAUDI_API void cannotAssignObjectKey()
Function to be called when an object key cannot be assigned.
KeyedObjectManager Class to manage keyed objects.
std::vector< void * > v
Direct access array.
void setParent(ObjectContainerBase *value)
Update parent member.
static CLID classID()
Access CLID for this type of container.
void setup(void *seq, void **rndm)
Setup of the Map and the parent object.
Containers::array __A
std::vector< void * > v
ObjectContainerBase is the base class for Gaudi container classes.
KeyedObjectManager()
Standard Constructor.
list i
Definition: ana.py:128
bool operator()(const void *cmp) const
bool insert(void *obj, long key)
long insertDirect(ObjectContainerBase *b, ContainedObject *c, void *o, long k)
Insert element into direct access map.