| # Gaudi Framework, version v21r10p1 |

Home |  | Generated: 29 Jul 2010

# KeyedContainer.h

Go to the documentation of this file.

    00001 // $Id $
    00002 #ifndef GAUDIKERNEL_KEYEDCONTAINER_H
    00003 #define GAUDIKERNEL_KEYEDCONTAINER_H
    00004
    00005 // Include files
    00006 #include <iterator>
    00007 #include <algorithm>
    00008
    00009 namespace GaudiDict  {
    00010   template <class T> struct KeyedContainerDict;
    00011 }
    00012
    00013 // Framework include files
    00014 #include "GaudiKernel/ObjectContainerBase.h"
    00015 #include "GaudiKernel/KeyedObjectManager.h"
    00016 #include "GaudiKernel/KeyedObject.h"
    00017
    00018 // Forward declarations
    00019 // template <class T, class M> class KeyedContainer;
    00020
    00021 #ifdef WIN32
    00022 #define FORCE_INLINE __forceinline
    00023 #else
    00024 #define FORCE_INLINE inline
    00025 #endif
    00026
    00063 template <class DATATYPE, class MAPPING=Containers::HashMap >
    00064 class GAUDI_API KeyedContainer: public ObjectContainerBase
    00065 {
    00066   friend struct GaudiDict::KeyedContainerDict<DATATYPE>;
    00067
    00068 public:
    00070   typedef DATATYPE                                  contained_type;
    00072   typedef MAPPING                                   container_type;
    00073
    00080
    00081   typedef typename std::vector<contained_type*>     seq_type;
    00083   typedef typename contained_type::key_type         key_type;
    00085   typedef typename seq_type::value_type             value_type;
    00087   typedef typename seq_type::reference              reference;
    00089   typedef typename seq_type::const_reference        const_reference;
    00091   typedef typename seq_type::iterator               iterator;
    00093   typedef typename seq_type::const_iterator         const_iterator;
    00095   typedef typename seq_type::reverse_iterator       reverse_iterator;
    00099   typedef typename seq_type::const_reverse_iterator const_reverse_iterator;
    00101 private:
    00105   typedef typename Containers::traits<container_type, contained_type> traits;
    00106
    00110
    00111   container_type m_cont;
    00113   seq_type       m_sequential;
    00115   seq_type*      m_random;
    00116
    00118 #ifdef CHECK_KEYED_CONTAINER
    00119   value_type i_object(const key_type& k) const  {
    00120     if ( 0 == m_cont.isDirect() )  {
    00121       if ( traits::checkBounds(m_random, k) )  {
    00122         value_type p = *(m_random->begin()+traits::hash(k));
    00123         if ( traits::checkKey(p, k) ) {
    00124           return p;
    00125         }
    00126       }
    00127       return 0;
    00128     }
    00129     value_type p = value_type(m_cont.object(traits::hash(k)));
    00130     return traits::checkKey(p, k) ? p : 0;
    00131   }
    00132 #else
    00133   FORCE_INLINE value_type i_object(const key_type& k) const  {
    00134     return 0==m_cont.isDirect()
    00135       ? value_type(*(m_random->begin()+traits::hash(k)))
    00136       : value_type(m_cont.object(traits::hash(k)));
    00137   }
    00138 #endif
    00140   long i_erase(const_reference v, const key_type& k)   {
    00141     value_type p = value_type(m_cont.erase(traits::hash(k), v));
    00142     if ( p )    {
    00143       if ( p->parent() == this )  {
    00144         p->setParent(0);
    00145       }
    00146     }
    00147     return traits::release(p) <= 0 ? (long) Containers::OBJ_ERASED
    00148                                    : (long) Containers::OBJ_DELETED;
    00149   }
    00150
    00152   struct _InsertRelease {
    00153     KeyedContainer<DATATYPE,MAPPING>* m_obj;
    00154     _InsertRelease(KeyedContainer<DATATYPE,MAPPING>* p) : m_obj(p) {}
    00155     void operator()(value_type p) {
    00156       m_obj->insert(p);
    00157       traits::release(p);
    00158     }
    00159   };
    00160
    00162   struct _RemoveRelease {
    00163     ObjectContainerBase* m_obj;
    00164     _RemoveRelease(ObjectContainerBase* p) : m_obj(p) {}
    00165     void operator()(value_type p) {
    00166       const ObjectContainerBase* par = p->parent();
    00167       if ( par == m_obj )  {
    00168         p->setParent(0);
    00169       }
    00170       traits::release(p);
    00171     }
    00172   };
    00174
    00175 public:
    00179
    00180   KeyedContainer(void)
    00181   {
    00182     // avoid problems with strict-aliasing rules
    00183     seq_type** rptr = &m_random;
    00184     seq_type*  sptr = &m_sequential;
    00185     m_cont.setup((void*)sptr,(void**)rptr);
    00186   }
    00188   virtual ~KeyedContainer();
    00190
    00196
    00197   virtual const CLID& clID() const      {              return this->classID(); }
    00199   static const CLID& classID()          {
    00200     static CLID clid = contained_type::classID() + container_type::classID();
    00201     return clid;
    00202   }
    00204
    00221
    00222   virtual size_type numberOfObjects() const   {  return m_sequential.size();       }
    00234   virtual long add(ContainedObject* pObject);
    00235
    00248   virtual long remove(ContainedObject* pObject);
    00249
    00253   virtual ContainedObject* containedObject(long key_value) const  {
    00254     return i_object( traits::makeKey( key_value ) );
    00255   }
    00259   virtual long index(const ContainedObject* p) const;
    00265   virtual size_type containedObjects(std::vector<ContainedObject*>& v) const;
    00267
    00273
    00274   size_type size() const                {      return m_sequential.size();    }
    00276   bool empty() const                    {      return m_sequential.empty();   }
    00278   void reserve(size_type value)         {      m_cont.reserve(value);          }
    00280   void clear()                          {      erase(begin(), end());          }
    00286   virtual const std::vector<const ContainedObject*>* containedObjects() const;
    00288   virtual void configureDirectAccess();
    00290
    00304
    00305   iterator begin()                      {      return m_sequential.begin();   }
    00307   const_iterator begin()  const         {      return m_sequential.begin();   }
    00309   iterator end()                        {      return m_sequential.end();     }
    00311   const_iterator end()  const           {      return m_sequential.end();     }
    00313   reverse_iterator rbegin()             {      return m_sequential.rbegin();  }
    00315   const_reverse_iterator rbegin() const {      return m_sequential.rbegin();  }
    00317   reverse_iterator rend()               {      return m_sequential.rend();    }
    00319   const_reverse_iterator rend() const   {      return m_sequential.rend();    }
    00321
    00339   value_type object(const key_type& kval) const     {  return i_object(kval);  }
    00340
    00350   value_type operator()(const key_type& kval) const {  return i_object(kval);  }
    00352
    00375   long erase(const key_type& kval)  { return i_erase(0, kval);  }
    00376
    00397   long erase(const value_type val) {
    00398     return (val) ? i_erase(val, val->key()) : (long) Containers::OBJ_NOT_FOUND;
    00399   }
    00400
    00421   long erase(iterator pos)   {                return erase(*pos);              }
    00422
    00431   void erase(iterator pos_start, iterator pos_stop, bool use_temp=false);
    00432
    00451   const key_type& insert(const value_type val, const key_type& kval);
    00452
    00474   const key_type& insert(const value_type val);
    00476 };
    00477
    00478
    00486 // Destructor
    00487 template <class DATATYPE, class MAPPING> inline
    00488 KeyedContainer<DATATYPE, MAPPING>::~KeyedContainer()
    00489 {
    00490   erase(begin(), end());
    00491   m_cont.clear();
    00492 }
    00493
    00494 // Configure direct access
    00495 template <class DATATYPE, class MAPPING> inline
    00496 void KeyedContainer<DATATYPE, MAPPING>::configureDirectAccess()
    00497 {
    00498   int count = 0;
    00499   m_cont.clearDirect();
    00500   typename seq_type::iterator i = m_sequential.begin();
    00501   typename seq_type::iterator s = m_sequential.end();
    00502   for ( ; i != s; i++ )  {
    00503     typename seq_type::value_type v = *i;
    00504     if ( v )  {
    00505       if ( !v->hasKey() ) {
    00506         traits::setKey(v, v->key());
    00507         traits::addRef(v);
    00508       }
    00509       long k0 = traits::hash(v->key());
    00510       if(m_cont.insertDirect(this, v, v, k0) == Containers::OBJ_INSERTED)   {
    00511       }
    00512     }
    00513     else  {
    00514       ++count;
    00515     }
    00516   }
    00517   if ( count > 0 )  {
    00518     Containers::cannotInsertToContainer();
    00519   }
    00520 }
    00521
    00522
    00523 // Retrieve the full content of the object container by reference.
    00524 template <class DATATYPE, class MAPPING> inline
    00525 const std::vector<const ContainedObject*>*
    00526 KeyedContainer<DATATYPE, MAPPING>::containedObjects() const  {
    00527   return (const std::vector<const ContainedObject*>*)
    00528     ((0==m_cont.isDirect()) ? m_random : &m_sequential);
    00529 }
    00530
    00531 template <class DATATYPE, class MAPPING> inline
    00532 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
    00533 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val,
    00534                                           const key_type& kval)
    00535 {
    00536   if ( val )    {
    00537     long k0 = traits::hash(kval);
    00538     if ( !val->hasKey() || (traits::hash(val->key()) == k0) )    {
    00539       if(m_cont.insert(this,val,val,k0) == Containers::OBJ_INSERTED)   {
    00540         if ( !val->hasKey() ) traits::setKey(val, kval);
    00541         traits::addRef(val);
    00542         return val->key();
    00543       }
    00544     }
    00545   }
    00546   // Cannot insert object...indicate bad object insertion...
    00547   Containers::cannotInsertToContainer();
    00548   return val->key();
    00549 }
    00550
    00551 // Insert object
    00552 template <class DATATYPE, class MAPPING> //inline
    00553 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
    00554 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val)
    00555 {
    00556   if ( 0 != val )   {
    00557     if ( val->hasKey() )   {
    00558       if (m_cont.insert(this,val,val,traits::hash(val->key()))
    00559           == Containers::OBJ_INSERTED)   {
    00560         traits::addRef(val);
    00561         return val->key();
    00562       }
    00563     }
    00564     long k0;
    00565     if ( m_cont.insert(this, val, val, &k0) == Containers::OBJ_INSERTED )   {
    00566       traits::setKey(val, traits::makeKey(k0));
    00567       traits::addRef(val);
    00568       return val->key();
    00569     }
    00570   }
    00571   // Cannot insert object...indicate bad object insertion...
    00572   Containers::cannotInsertToContainer();
    00573   return val->key();
    00574 }
    00575
    00576 template <class DATATYPE, class MAPPING> inline
    00577 long KeyedContainer<DATATYPE, MAPPING>::index(const ContainedObject* p) const
    00578 {
    00579   const contained_type* ptr = dynamic_cast<const contained_type*>(p);
    00580   if ( ptr ) return traits::identifier(ptr->key());
    00581   return -1;
    00582 }
    00583
    00584 // Retrieve the full content of the object container.
    00585 template <class DATATYPE, class MAPPING> inline
    00586 typename KeyedContainer<DATATYPE, MAPPING>::size_type KeyedContainer<DATATYPE, MAPPING>::containedObjects
    00587 (std::vector<ContainedObject*>& vec) const
    00588 {
    00589   typename seq_type::const_iterator i = m_sequential.begin();
    00590   typename seq_type::const_iterator s = m_sequential.end();
    00591   vec.clear();
    00592   vec.reserve(size());
    00593   for ( ; i != s; i++ )  {
    00594     ContainedObject* p = const_cast<typename seq_type::value_type>(*i);
    00595     vec.push_back(p);
    00596   }
    00597   return vec.size();
    00598 }
    00599
    00600 // ObjectContainerBase overload: Add an object to the container.
    00601 template <class DATATYPE, class MAPPING> inline
    00602 long KeyedContainer<DATATYPE, MAPPING>::add(ContainedObject* pObject)
    00603 {
    00604   return traits::identifier(insert(dynamic_cast<typename seq_type::value_type>(pObject)));
    00605 }
    00606
    00607 // ObjectContainerBase overload: Remove an object from the container.
    00608 template <class DATATYPE, class MAPPING> inline
    00609 long KeyedContainer<DATATYPE, MAPPING>::remove(ContainedObject* p)
    00610 {
    00611   contained_type* p1 = dynamic_cast<contained_type*>(p);
    00612   if ( p1 )    {  // Normal case; object still fully intact
    00613     return this->erase(p1);
    00614   }
    00615   else if ( p )   {
    00616     const ObjectContainerBase* par = p->parent();
    00617     // The following should never occur: object is in a funny state,
    00618     // Because the parent was explicitly set to NULL in the
    00619     // KeyeObject destructor.
    00620     // - It cannot be a KeyedObject:  It would not have a parent
    00621     // - Still the parent is present: We are not in the destructor
    00622     //                                of KeyedObject
    00623     if ( par )  {
    00624       Containers::invalidContainerOperation();
    00625     }
    00626     return m_cont.erase(0, p)==0 ? (long) Containers::OBJ_ERASED
    00627                                  : (long) Containers::OBJ_NOT_FOUND;
    00628   }
    00629   return (long) Containers::OBJ_NOT_FOUND;
    00630 }
    00631
    00632 template <class DATATYPE, class MAPPING> inline
    00633 void
    00634 KeyedContainer<DATATYPE, MAPPING>::erase(iterator start_pos,
    00635                                          iterator stop_pos,
    00636                                          bool use_tmp)
    00637 {
    00638   bool is_start = start_pos == m_sequential.begin();
    00639   bool is_stop  = stop_pos  == m_sequential.end();
    00640   if ( is_start && is_stop )  {
    00641     // Nothing special. Taken care of by Keyed object manager
    00642   }
    00643   else if ( is_start || is_stop || use_tmp )  {
    00644     std::vector<DATATYPE*> tmp(m_sequential.begin(), start_pos);
    00645     tmp.insert(tmp.end(), stop_pos, m_sequential.end());
    00646     std::for_each(tmp.begin(), tmp.end(), traits::addRef);
    00647     this->erase(m_sequential.begin(), m_sequential.end());
    00648     std::for_each(tmp.begin(), tmp.end(), _InsertRelease(this));
    00649     return;
    00650   }
    00651   std::for_each(start_pos, stop_pos, _RemoveRelease(this));
    00652   seq_type *sptr = &m_sequential; // avoid problems with strict-aliasing rules
    00653   std::vector<void*>* v = (std::vector<void*>*)sptr;
    00654   std::vector<void*>::iterator i1 =
    00655     v->begin() + std::distance(m_sequential.begin(), start_pos);
    00656   std::vector<void*>::iterator i2 =
    00657     v->begin() + std::distance(m_sequential.begin(), stop_pos);
    00658   m_cont.erase(i1, i2);
    00659 }
    00660
    00661 #undef FORCE_INLINE
    00662 #endif // GAUDIKERNEL_KEYEDCONTAINER_H