The Gaudi Framework  v30r3 (a5ef0a68)
KeyedObjectManager.cpp
Go to the documentation of this file.
1 // Include files
5 #include "GaudiKernel/HashMap.h"
6 #include "GaudiKernel/Kernel.h"
7 #include <algorithm>
8 #include <map>
9 
10 namespace Containers
11 {
12  struct hashmap {
14  map_type m;
16  bool insert( void* obj, long key )
17  {
18  auto p = m.insert( map_type::value_type( key, obj ) );
19  return p.second;
20  }
21  hashmap() = default;
22  hashmap( hashmap&& ) = default;
23  };
24  struct map {
26  map_type m;
28  bool insert( void* obj, long key )
29  {
30  auto p = m.insert( map_type::value_type( key, obj ) );
31  return p.second;
32  }
33  map() = default;
34  map( map&& ) = default;
35  };
36  struct array {
42  struct decrement {
43  long m_min;
44  decrement( long m ) : m_min( m ) {}
45  bool operator()( long& j ) const
46  {
47  if ( j > m_min ) --j;
48  return true;
49  }
50  };
51  array() = default;
52  array( array&& ) = default;
53  };
54  struct vector {
58  vector() = default;
59  vector( vector&& ) = default;
60  };
61 
62  template <class CONT>
63  class find
64  {
65  const void* m_obj;
66  typedef typename CONT::value_type v_type;
67 
68  public:
69  find( const void* o ) : m_obj( o ) {}
70  bool operator()( const void* cmp ) const { return cmp == m_obj; }
71  bool operator()( const v_type& cmp ) const { return ( *this )( cmp.second ); }
72  };
73 }
75 {
76  throw GaudiException( "Cannot assign key to keyed object! Object already has a key.", "KeyedObject",
78 }
80 {
81  throw GaudiException( "Cannot insert element to Keyed Container!", "KeyedContainer", StatusCode::FAILURE );
82 }
83 
85 {
86  throw GaudiException( "Keyed Container structures are inconsistent - severe problem!", "KeyedContainer",
88 }
89 
91 {
92  throw GaudiException( "Keyed Container cannot satisfy request - severe problem!", "KeyedContainer",
94 }
95 
96 template <class T>
97 Containers::KeyedObjectManager<T>::KeyedObjectManager() : 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", "KeyedContainer", StatusCode::FAILURE );
101  }
102  m_setup.s = ::new ( m_setup.buffer + sizeof( m_setup.s ) ) T();
103  m_keyCtxt = -1;
104 }
105 
106 template <class T>
108  : m_seq( nullptr ), m_direct( other.m_direct ), m_keyCtxt( other.m_keyCtxt )
109 {
110  m_setup.s = ::new ( m_setup.buffer + sizeof( m_setup.s ) ) T( std::move( *other.m_setup.s ) );
111 
112  other.m_keyCtxt = -1;
113  other.m_seq = nullptr;
114  other.m_direct = 0;
115 }
116 
117 template <class T>
119 {
120  m_setup.s->~T();
121 }
122 
124 template <class T>
126 {
127  m_seq = (seq_type*)seq;
128  *rndm = &m_setup.s->v;
129 }
130 
131 template <class T>
133 {
134  m_direct = 1;
135  auto& s = *m_setup.s;
136  long i = 0;
137  for ( auto p : s.v ) s.insert( p, i++ );
138  s.v.clear();
139 }
140 
141 template <class T>
143  long* key )
144 {
145  *key = ++m_keyCtxt;
146  return insert( pBase, pObject, obj, *key );
147 }
148 
149 template <class T>
151  long key )
152 {
154  if ( key > m_keyCtxt ) {
155  m_keyCtxt = key;
156  }
157  if ( 1 == m_direct ) {
158  if ( m_setup.s->insert( obj, key ) ) {
159  if ( !pObject->parent() ) {
160  pObject->setParent( pBase );
161  }
162  m_seq->push_back( obj );
163  return OBJ_INSERTED;
164  }
165  } else if ( key == long( m_setup.s->v.size() ) ) {
166  m_setup.s->v.push_back( obj );
167  if ( !pObject->parent() ) {
168  pObject->setParent( pBase );
169  }
170  m_seq->push_back( obj );
171  return OBJ_INSERTED;
172  } else {
173  // Document is dirty now...
174  // need to copy all pointers from the vector to the map
175  onDirty();
176  return insert( pBase, pObject, obj, key );
177  }
179  return OBJ_CANNOT_INSERT;
180 }
181 
182 template <class T>
184  long key )
185 {
187  if ( key > m_keyCtxt ) {
188  m_keyCtxt = key;
189  }
190  if ( 1 == m_direct ) {
191  if ( m_setup.s->insert( obj, key ) ) {
192  if ( !pObject->parent() ) {
193  pObject->setParent( pBase );
194  }
195  return OBJ_INSERTED;
196  }
197  } else if ( key == long( m_setup.s->v.size() ) ) {
198  m_setup.s->v.push_back( obj );
199  if ( !pObject->parent() ) {
200  pObject->setParent( pBase );
201  }
202  return OBJ_INSERTED;
203  } else {
204  // Document is dirty now...
205  // need to copy all pointers from the vector to the map
206  onDirty();
207  return insertDirect( pBase, pObject, obj, key );
208  }
210  return OBJ_CANNOT_INSERT;
211 }
212 
213 // Remove object from container
214 template <class T>
215 void* Containers::KeyedObjectManager<T>::erase( long key, const void* obj )
216 {
217  typedef typename T::map_type MTYP;
218  typedef find<MTYP> FND;
219  if ( 1 == m_direct ) {
220  auto& m = m_setup.s->m;
221  auto i = ( obj ? std::find_if( m.begin(), m.end(), FND( obj ) ) : m_setup.s->m.find( key ) );
222  if ( i != m_setup.s->m.end() ) {
223  void* o = i->second;
224  auto j = std::find( m_seq->begin(), m_seq->end(), o );
225  if ( j != m_seq->end() ) {
226  m_seq->erase( j );
227  m_setup.s->m.erase( i );
228  return o;
229  }
230  }
232  }
233  onDirty();
234  return erase( key, obj );
235 }
236 
237 template <class T>
239 {
240  if ( 0 == m_direct ) onDirty();
241  auto i = m_setup.s->m.find( key );
242  if ( i != m_setup.s->m.end() ) return ( *i ).second;
243  return nullptr;
244 }
245 
246 template <class T>
248 {
249  switch ( m_direct ) {
250  case 1:
251  break;
252  case 0:
253  m_setup.s->v.reserve( len );
254  break;
255  default:
256  break;
257  }
258  m_seq->reserve( len );
259 }
260 
261 template <class T>
263 {
264  clearDirect();
265  m_seq->clear();
266 }
267 
268 template <class T>
270 {
271  switch ( m_direct ) {
272  case 1:
273  m_setup.s->m.clear();
274  break;
275  case 0:
276  m_setup.s->v.clear();
277  break;
278  default:
279  break;
280  }
281  m_direct = 0;
282  m_keyCtxt = -1;
283 }
284 
285 // Remove object by sequential iterators
286 template <class T>
287 long Containers::KeyedObjectManager<T>::erase( seq_type::iterator beg, seq_type::iterator end )
288 {
289  typedef typename T::map_type MTYP;
290  typedef find<MTYP> FND;
291  if ( 0 == m_direct ) {
292  onDirty();
293  return erase( beg, end );
294  }
295  if ( beg == m_seq->begin() && end == m_seq->end() ) {
296  clear();
297  } else {
298  for ( auto j = beg; j != end; ++j ) {
299  // auto& m = m_setup.s->m;
300  auto i = std::find_if( m_setup.s->m.begin(), m_setup.s->m.end(), FND( *j ) );
301  if ( i != m_setup.s->m.end() ) {
302  m_setup.s->m.erase( i );
303  continue;
304  }
306  }
307  m_seq->erase( beg, end );
308  }
309  return OBJ_ERASED;
310 }
311 
312 namespace Containers
313 {
314 
315  /* First specialize static methods and then instantiate templated class to appear as symbols in the library
316  This order in needed for gcc 4.0 (MacOSX) */
317 
318  template <>
320  {
321  return CLID_ObjectVector + 0x00030000;
322  }
323  template <>
325  {
326  return CLID_ObjectVector + 0x00040000;
327  }
328 
331 }
332 
333 /*
334  *
335  *
336  * Inline code for indirection array implementation
337  *
338  */
340 
341 namespace Containers
342 {
343 
344  //__forceinline
345  template <>
346  void* KeyedObjectManager<__A>::object( long value ) const
347  {
348 #ifdef CHECK_KEYED_CONTAINER
349  unsigned long siz = m_setup.s->m_idx.size();
350  if ( value >= 0 && size_t( value ) < siz ) {
351  long ent = *( m_setup.s->m_idx.begin() + value );
352  if ( ent >= 0 ) {
353  return *( m_setup.s->v.begin() + ent );
354  }
355  }
356  return nullptr;
357 #else
358  return *( m_setup.s->v.begin() + ( *( m_setup.s->m_idx.begin() + value ) ) );
359 #endif
360  }
361 
362  template <>
364  {
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] ) {
370  }
371  m_setup.s->m_idx.push_back( i );
372  }
373  }
374 
375  // Insert new object into container
376  template <>
378  {
379  // auto key creation only possible for direct access!
380  if ( 0 == m_direct ) {
381  m_seq->push_back( o );
382  m_setup.s->v.push_back( o );
383  if ( !c->parent() ) c->setParent( b );
384  *k = ++m_keyCtxt;
385  return OBJ_INSERTED;
386  }
388  return OBJ_CANNOT_INSERT;
389  }
390 
391  // Insert new object into container
392  template <>
394  {
395  if ( 0 == m_direct ) {
396  if ( k == m_keyCtxt + 1 ) {
397  return insert( b, c, o, &k );
398  }
399  onDirty();
400  return insert( b, c, o, k );
401  }
403  if ( k > m_keyCtxt ) m_keyCtxt = k;
405  if ( k + 1 > long( m_setup.s->m_idx.size() ) ) {
406  m_setup.s->m_idx.resize( k + 1, -1 );
407  }
408  auto idx = m_setup.s->m_idx.begin() + k;
409  if ( *idx == -1 ) {
410  *idx = m_setup.s->v.size();
411  m_setup.s->v.push_back( o );
412  m_seq->push_back( o );
413  if ( !c->parent() ) c->setParent( b );
414  return OBJ_INSERTED;
415  }
417  return OBJ_CANNOT_INSERT;
418  }
419 
420  // Insert new object into container
421  template <>
423  {
424  if ( 0 == m_direct ) {
425  if ( k == m_keyCtxt + 1 ) {
426  m_setup.s->v.push_back( o );
427  if ( !c->parent() ) c->setParent( b );
428  ++m_keyCtxt;
429  return OBJ_INSERTED;
430  }
431  onDirty();
432  return insertDirect( b, c, o, k );
433  }
435  if ( k > m_keyCtxt ) m_keyCtxt = k;
437  if ( k + 1 > long( m_setup.s->m_idx.size() ) ) {
438  m_setup.s->m_idx.resize( k + 1, -1 );
439  }
440  auto idx = m_setup.s->m_idx.begin() + k;
441  if ( *idx == -1 ) {
442  *idx = m_setup.s->v.size();
443  m_setup.s->v.push_back( o );
444  if ( !c->parent() ) c->setParent( b );
445  return OBJ_INSERTED;
446  }
448  return OBJ_CANNOT_INSERT;
449  }
450 
451  // Clear content of the vector
452  template <>
454  {
455  m_setup.s->v.clear();
456  m_setup.s->m_idx.clear();
457  m_direct = 0;
458  m_keyCtxt = -1;
459  }
460 
461  // Remove object from container (very inefficient if key is invalid)
462  template <>
463  void* KeyedObjectManager<__A>::erase( long key, const void* obj )
464  {
465  typedef std::vector<long> id_type;
466  if ( 0 == m_direct ) {
467  onDirty();
468  return erase( key, obj );
469  }
470  if ( obj ) {
471  id_type& idx = m_setup.s->m_idx;
472  for ( auto& elem : idx ) {
473  auto j = m_setup.s->v.begin() + ( elem );
474  auto k = std::find( m_seq->begin(), m_seq->end(), *j );
475  if ( *j == obj ) {
476  void* o = *j;
477  m_seq->erase( k );
478  m_setup.s->v.erase( j );
479  std::for_each( m_setup.s->m_idx.begin(), m_setup.s->m_idx.end(), array::decrement( elem ) );
480  elem = -1;
481  return o;
482  }
483  }
484  } else if ( key >= 0 && key < long( m_setup.s->m_idx.size() ) ) {
485  auto idx = m_setup.s->m_idx.begin() + key;
486  if ( *idx != -1 ) {
487  auto i = m_setup.s->v.begin() + ( *idx );
488  if ( i == m_setup.s->v.end() ) {
490  }
491  void* o = *i;
492  auto j = std::find( m_seq->begin(), m_seq->end(), o );
493  if ( j == m_seq->end() ) {
495  }
496  m_seq->erase( j );
497  m_setup.s->v.erase( i );
498  std::for_each( m_setup.s->m_idx.begin(), m_setup.s->m_idx.end(), array::decrement( *idx ) );
499  *idx = -1;
500  return o;
501  }
502  }
504  return nullptr;
505  }
506 
507  // Remove object by sequential iterators
508  template <>
509  long KeyedObjectManager<__A>::erase( seq_type::iterator beg, seq_type::iterator end )
510  {
511  typedef std::vector<long> id_type;
512  if ( beg == m_seq->begin() && end == m_seq->end() ) {
513  clear();
514  return OBJ_ERASED;
515  } else if ( 0 == m_direct ) {
516  onDirty();
517  return erase( beg, end );
518  } else {
519  long cnt = 0, nobj = end - beg;
520  id_type& idx = m_setup.s->m_idx;
521  for ( auto& elem : idx ) {
522  auto j = m_setup.s->v.begin() + ( elem );
523  auto k = std::find( beg, end, *j );
524  if ( k != end ) {
525  m_setup.s->v.erase( j );
526  std::for_each( m_setup.s->m_idx.begin(), m_setup.s->m_idx.end(), array::decrement( elem ) );
527  elem = -1;
528  cnt++;
529  if ( cnt == nobj ) break;
530  }
531  }
532  m_seq->erase( beg, end );
533  if ( cnt != nobj ) {
535  }
536  return OBJ_ERASED;
537  }
538  // cannot reach this point
539  }
540 
541  template <>
543  {
544  return CLID_ObjectVector + 0x00050000;
545  }
546 }
548 /*
549  *
550  *
551  * Implementation for objects with vector like access
552  *
553  *
554  **/
556 
557 namespace Containers
558 {
559  // Access single entry by long(integer) key
560  template <>
561  void* KeyedObjectManager<__V>::object( long /* value */ ) const
562  {
564  return nullptr;
565  }
566 
567  template <>
569  {
571  }
572 
573  // Insert new object into container
574  template <>
576  {
577  m_seq->push_back( o );
578  m_setup.s->v.push_back( o );
579  if ( !c->parent() ) c->setParent( b );
580  *k = ( m_setup.s->v.size() - 1 );
581  return OBJ_INSERTED;
582  }
583 
584  // Insert new object into container
585  template <>
587  {
588  if ( k == long( m_setup.s->v.size() ) ) {
589  return insert( b, c, o, &k );
590  }
592  return OBJ_CANNOT_INSERT;
593  }
594 
595  // Insert new object into container
596  template <>
598  {
599  if ( k == long( m_setup.s->v.size() ) ) {
600  m_setup.s->v.push_back( o );
601  if ( !c->parent() ) c->setParent( b );
602  return OBJ_INSERTED;
603  }
605  return OBJ_CANNOT_INSERT;
606  }
607 
608  // Clear content of the vector
609  template <>
611  {
612  m_setup.s->v.clear();
613  m_direct = 0;
614  m_keyCtxt = -1;
615  }
616 
617  // Remove object from container (very inefficient if key is invalid)
618  template <>
619  void* KeyedObjectManager<__V>::erase( long /* key */, const void* /* obj */ )
620  {
622  return nullptr;
623  }
624 
625  // Remove object by sequential iterators
626  template <>
627  long KeyedObjectManager<__V>::erase( seq_type::iterator beg, seq_type::iterator end )
628  {
629  if ( beg == m_seq->begin() && end == m_seq->end() ) {
630  clear();
631  return OBJ_ERASED;
632  }
634  return OBJ_ERASED;
635  }
636 
637  template <>
639  {
640  return CLID_ObjectVector + 0x00060000;
641  }
642 }
constexpr static const auto FAILURE
Definition: StatusCode.h:88
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
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.
Object was inserted into the container.
Definition: KeyedTraits.h:27
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)
std::pair< iterator, bool > insert(ValueType &&val)
Definition: Map.h:174
void reserve(long size)
Reserve buffer space.
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.
constexpr double m
Definition: SystemOfUnits.h:94
GaudiUtils::HashMap< long, void * > map_type
T erase(T...args)
void onDirty() const
Callback when the container becomes dirty.
Object was removed, but not deleted.
Definition: KeyedTraits.h:26
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)
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)
Cannot insert object into container.
Definition: KeyedTraits.h:28
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.
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.
union Containers::KeyedObjectManager::@2 m_setup