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_seq(nullptr), 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  switch( m_direct ) {
275  case 1:
276  m_setup.s->m.clear();
277  break;
278  case 0:
279  m_setup.s->v.clear();
280  break;
281  default:
282  break;
283  }
284  m_direct = 0;
285  m_keyCtxt = -1;
286 }
287 
288 // Remove object by sequential iterators
289 template <class T>
290 long Containers::KeyedObjectManager<T>::erase(seq_type::iterator beg,
291  seq_type::iterator end)
292 {
293  typedef typename T::map_type MTYP;
294  typedef find<MTYP> FND;
295  if ( 0 == m_direct ) {
296  onDirty();
297  return erase(beg, end);
298  }
299  if ( beg == m_seq->begin() && end == m_seq->end() ) {
300  clear();
301  }
302  else {
303  for ( seq_type::iterator j=beg; j != end; ++j) {
304  typename T::map_type& m = m_setup.s->m;
305  typename T::map_type::iterator i = std::find_if(m.begin(),m.end(),FND(*j));
306  if ( i != m_setup.s->m.end() ) {
307  m_setup.s->m.erase(i);
308  continue;
309  }
311  }
312  m_seq->erase(beg, end);
313  }
314  return OBJ_ERASED;
315 }
316 
317 namespace Containers {
318 
319  /* First specialize static methods and then instantiate templated class to appear as symbols in the library
320  This order in needed for gcc 4.0 (MacOSX) */
321 
322  template<>
324  return CLID_ObjectVector+0x00030000;
325  }
326  template<>
328  return CLID_ObjectVector+0x00040000;
329  }
330 
333 }
334 
335 /*
336  *
337  *
338  * Inline code for indirection array implementation
339  *
340  */
342 
343 namespace Containers {
344 
345 //__forceinline
346 template<> void*
348 {
349 #ifdef CHECK_KEYED_CONTAINER
350  unsigned long siz = m_setup.s->m_idx.size();
351  if ( value >= 0 && size_t(value) < siz ) {
352  long ent = *(m_setup.s->m_idx.begin()+value);
353  if ( ent >= 0 ) {
354  return *(m_setup.s->v.begin() + ent);
355  }
356  }
357  return 0;
358 #else
359  return *(m_setup.s->v.begin() + (*(m_setup.s->m_idx.begin()+value)));
360 #endif
361 }
362 
363 template<>
365  m_direct = 1;
366  m_setup.s->m_idx.reserve(m_setup.s->v.size()+1);
367  for(int i = 0, stop = m_setup.s->v.size(); i < stop; ++i) {
368  if ( m_setup.s->v[i] == 0 ) {
370  }
371  m_setup.s->m_idx.push_back(i);
372  }
373 }
374 
375 // Insert new object into container
376 template<>
379  void* o,
380  long* k)
381 {
382  // auto key creation only possible for direct access!
383  if ( 0 == m_direct ) {
384  m_seq->push_back(o);
385  m_setup.s->v.push_back(o);
386  if ( !c->parent() ) c->setParent(b);
387  *k = ++m_keyCtxt;
388  return OBJ_INSERTED;
389  }
391  return OBJ_CANNOT_INSERT;
392 }
393 
394 // Insert new object into container
395 template<>
398  void* o,
399  long k)
400 {
401  if ( 0 == m_direct ) {
402  if ( k == m_keyCtxt+1 ) {
403  return insert(b, c, o, &k);
404  }
405  onDirty();
406  return insert(b, c, o, k);
407  }
409  if ( k > m_keyCtxt ) m_keyCtxt = k;
411  if ( k+1 > long(m_setup.s->m_idx.size()) ) {
412  m_setup.s->m_idx.resize(k+1, -1);
413  }
414  std::vector<long>::iterator idx = m_setup.s->m_idx.begin()+k;
415  if ( *idx == -1 ) {
416  *idx = m_setup.s->v.size();
417  m_setup.s->v.push_back(o);
418  m_seq->push_back(o);
419  if ( !c->parent() ) c->setParent(b);
420  return OBJ_INSERTED;
421  }
423  return OBJ_CANNOT_INSERT;
424 }
425 
426 // Insert new object into container
427 template<> long
430  void* o,
431  long k)
432 {
433  if ( 0 == m_direct ) {
434  if ( k == m_keyCtxt+1 ) {
435  m_setup.s->v.push_back(o);
436  if ( !c->parent() ) c->setParent(b);
437  ++m_keyCtxt;
438  return OBJ_INSERTED;
439  }
440  onDirty();
441  return insertDirect(b, c, o, k);
442  }
444  if ( k > m_keyCtxt ) m_keyCtxt = k;
446  if ( k+1 > long(m_setup.s->m_idx.size()) ) {
447  m_setup.s->m_idx.resize(k+1, -1);
448  }
449  std::vector<long>::iterator idx = m_setup.s->m_idx.begin()+k;
450  if ( *idx == -1 ) {
451  *idx = m_setup.s->v.size();
452  m_setup.s->v.push_back(o);
453  if ( !c->parent() ) c->setParent(b);
454  return OBJ_INSERTED;
455  }
457  return OBJ_CANNOT_INSERT;
458 }
459 
460 // Clear content of the vector
461 template<>
463  m_setup.s->v.clear();
464  m_setup.s->m_idx.clear();
465  m_direct = 0;
466  m_keyCtxt = -1;
467 }
468 
469 // Remove object from container (very inefficient if key is invalid)
470 template<>
472  const void* obj)
473 {
474  typedef std::vector<long> id_type;
475  typedef id_type::iterator id_iter;
476  if ( 0 == m_direct ) {
477  onDirty();
478  return erase(key, obj);
479  }
480  if ( 0 != obj ) {
481  id_type& idx = m_setup.s->m_idx;
482  for ( id_iter i=idx.begin(); i != idx.end(); i++ ) {
483  seq_type::iterator j = m_setup.s->v.begin()+(*i);
484  seq_type::iterator k = std::find(m_seq->begin(),m_seq->end(),*j);
485  if ( *j == obj ) {
486  void* o = *j;
487  m_seq->erase(k);
488  m_setup.s->v.erase(j);
489  std::for_each(m_setup.s->m_idx.begin(),
490  m_setup.s->m_idx.end(),
491  array::decrement(*i));
492  *i = -1;
493  return o;
494  }
495  }
496  }
497  else if ( key >= 0 && key < long(m_setup.s->m_idx.size()) ) {
498  id_iter idx = m_setup.s->m_idx.begin()+key;
499  if ( *idx != -1 ) {
500  seq_type::iterator i = m_setup.s->v.begin()+(*idx);
501  if ( i == m_setup.s->v.end() ) {
503  }
504  void* o = *i;
505  seq_type::iterator j=std::find(m_seq->begin(),m_seq->end(),o);
506  if ( j == m_seq->end() ) {
508  }
509  m_seq->erase(j);
510  m_setup.s->v.erase(i);
511  std::for_each(m_setup.s->m_idx.begin(),
512  m_setup.s->m_idx.end(),
513  array::decrement(*idx));
514  *idx = -1;
515  return o;
516  }
517  }
519  return 0;
520 }
521 
522 // Remove object by sequential iterators
523 template<>
524 long KeyedObjectManager< __A >::erase(seq_type::iterator beg,
525  seq_type::iterator end)
526 {
527  typedef std::vector<long> id_type;
528  typedef id_type::iterator id_iter;
529  if ( beg == m_seq->begin() && end == m_seq->end() ) {
530  clear();
531  return OBJ_ERASED;
532  }
533  else if ( 0 == m_direct ) {
534  onDirty();
535  return erase(beg, end);
536  }
537  else {
538  long cnt = 0, nobj = end-beg;
539  id_type& idx = m_setup.s->m_idx;
540  for ( id_iter i=idx.begin(); i != idx.end(); i++ ) {
541  seq_type::iterator j = m_setup.s->v.begin()+(*i);
542  seq_type::iterator k = std::find(beg,end,*j);
543  if ( k != end ) {
544  m_setup.s->v.erase(j);
545  std::for_each(m_setup.s->m_idx.begin(),
546  m_setup.s->m_idx.end(),
547  array::decrement(*i));
548  *i = -1;
549  cnt++;
550  if ( cnt == nobj ) break;
551  }
552  }
553  m_seq->erase(beg, end);
554  if ( cnt != nobj ) {
556  }
557  return OBJ_ERASED;
558  }
559  // cannot reach this point
560 }
561 
562 template<>
564  return CLID_ObjectVector+0x00050000;
565 }
566 }
568 /*
569  *
570  *
571  * Implementation for objects with vector like access
572  *
573  *
574  **/
576 
577 namespace Containers {
578 // Access single entry by long(integer) key
579 template<>
580 void* KeyedObjectManager< __V >::object(long /* value */) const
581 {
583  return 0;
584 }
585 
586 template<>
589 }
590 
591 // Insert new object into container
592 template<>
595  void* o,
596  long* k)
597 {
598  m_seq->push_back(o);
599  m_setup.s->v.push_back(o);
600  if ( !c->parent() ) c->setParent(b);
601  *k = (m_setup.s->v.size()-1);
602  return OBJ_INSERTED;
603 }
604 
605 // Insert new object into container
606 template<>
609  void* o,
610  long k)
611 {
612  if ( k == long(m_setup.s->v.size()) ) {
613  return insert(b, c, o, &k);
614  }
616  return OBJ_CANNOT_INSERT;
617 }
618 
619 // Insert new object into container
620 template<> long
623  void* o,
624  long k)
625 {
626  if ( k == long(m_setup.s->v.size()) ) {
627  m_setup.s->v.push_back(o);
628  if ( !c->parent() ) c->setParent(b);
629  return OBJ_INSERTED;
630  }
632  return OBJ_CANNOT_INSERT;
633 }
634 
635 // Clear content of the vector
636 template<>
638  m_setup.s->v.clear();
639  m_direct = 0;
640  m_keyCtxt = -1;
641 }
642 
643 // Remove object from container (very inefficient if key is invalid)
644 template<> void*
646  const void* /* obj */)
647 {
649  return 0;
650 }
651 
652 // Remove object by sequential iterators
653 template<>
654 long KeyedObjectManager< __V >::erase(seq_type::iterator beg,
655  seq_type::iterator end)
656 {
657  if ( beg == m_seq->begin() && end == m_seq->end() ) {
658  clear();
659  return OBJ_ERASED;
660  }
662  return OBJ_ERASED;
663 }
664 
665 template<>
667  return CLID_ObjectVector+0x00060000;
668 }
669 
670 }
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.