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