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