| # Gaudi Framework, version v20r3
Generated: 24 Nov 2008

# 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 KeyedContainer
    00065 : public ObjectContainerBase
    00066 {
    00067   friend struct GaudiDict::KeyedContainerDict<DATATYPE>;
    00068
    00069 public:
    00071   typedef DATATYPE                                  contained_type;
    00073   typedef MAPPING                                   container_type;
    00074
    00081
    00082   typedef typename std::vector<contained_type*>     seq_type;
    00084   typedef typename contained_type::key_type         key_type;
    00086   typedef typename seq_type::value_type             value_type;
    00088   typedef typename seq_type::reference              reference;
    00090   typedef typename seq_type::const_reference        const_reference;
    00092   typedef typename seq_type::iterator               iterator;
    00094   typedef typename seq_type::const_iterator         const_iterator;
    00096   typedef typename seq_type::reverse_iterator       reverse_iterator;
    00100   typedef typename seq_type::const_reverse_iterator const_reverse_iterator;
    00102 private:
    00106   typedef typename Containers::traits<container_type, contained_type> traits;
    00107
    00111
    00112   container_type m_cont;
    00114   seq_type       m_sequential;
    00116   seq_type*      m_random;
    00117
    00119 #ifdef CHECK_KEYED_CONTAINER
    00120   value_type i_object(const key_type& k) const  {
    00121     if ( 0 == m_cont.isDirect() )  {
    00122       if ( traits::checkBounds(m_random, k) )  {
    00123         value_type p = *(m_random->begin()+traits::hash(k));
    00124         if ( traits::checkKey(p, k) ) {
    00125           return p;
    00126         }
    00127       }
    00128       return 0;
    00129     }
    00130     value_type p = value_type(m_cont.object(traits::hash(k)));
    00131     return traits::checkKey(p, k) ? p : 0;
    00132   }
    00133 #else
    00134   FORCE_INLINE value_type i_object(const key_type& k) const  {
    00135     return 0==m_cont.isDirect()
    00136       ? value_type(*(m_random->begin()+traits::hash(k)))
    00137       : value_type(m_cont.object(traits::hash(k)));
    00138   }
    00139 #endif
    00141   long i_erase(const_reference v, const key_type& k)   {
    00142     value_type p = value_type(m_cont.erase(traits::hash(k), v));
    00143     if ( p )    {
    00144       if ( p->parent() == this )  {
    00145         p->setParent(0);
    00146       }
    00147     }
    00148     return traits::release(p) <= 0 ? (long) Containers::OBJ_ERASED
    00149                                    : (long) Containers::OBJ_DELETED;
    00150   }
    00151
    00153   struct _InsertRelease {
    00154     KeyedContainer<DATATYPE,MAPPING>* m_obj;
    00155     _InsertRelease(KeyedContainer<DATATYPE,MAPPING>* p) : m_obj(p) {}
    00156     void operator()(value_type p) {
    00157       m_obj->insert(p);
    00158       traits::release(p);
    00159     }
    00160   };
    00161
    00163   struct _RemoveRelease {
    00164     ObjectContainerBase* m_obj;
    00165     _RemoveRelease(ObjectContainerBase* p) : m_obj(p) {}
    00166     void operator()(value_type p) {
    00167       const ObjectContainerBase* par = p->parent();
    00168       if ( par == m_obj )  {
    00169         p->setParent(0);
    00170       }
    00171       traits::release(p);
    00172     }
    00173   };
    00175
    00176 public:
    00180
    00181   KeyedContainer(void)
    00182   {
    00183     // avoid problems with strict-aliasing rules
    00184     seq_type** rptr = &m_random;
    00185     seq_type*  sptr = &m_sequential;
    00186     m_cont.setup((void*)sptr,(void**)rptr);
    00187   }
    00189   virtual ~KeyedContainer();
    00191
    00197
    00198   virtual const CLID& clID() const      {              return this->classID(); }
    00200   static const CLID& classID()          {
    00201     static CLID clid = contained_type::classID() + container_type::classID();
    00202     return clid;
    00203   }
    00205
    00222
    00223   virtual size_type numberOfObjects() const   {  return m_sequential.size();       }
    00235   virtual long add(ContainedObject* pObject);
    00236
    00249   virtual long remove(ContainedObject* pObject);
    00250
    00254   virtual ContainedObject* containedObject(long key_value) const  {
    00255     return i_object( traits::makeKey( key_value ) );
    00256   }
    00260   virtual long index(const ContainedObject* p) const;
    00266   virtual size_type containedObjects(std::vector<ContainedObject*>& v) const;
    00268
    00274
    00275   size_type size() const                {      return m_sequential.size();    }
    00277   bool empty() const                    {      return m_sequential.empty();   }
    00279   void reserve(size_type value)         {      m_cont.reserve(value);          }
    00281   void clear()                          {      erase(begin(), end());          }
    00287   virtual const std::vector<const ContainedObject*>* containedObjects() const;
    00289   virtual void configureDirectAccess();
    00291
    00305
    00306   iterator begin()                      {      return m_sequential.begin();   }
    00308   const_iterator begin()  const         {      return m_sequential.begin();   }
    00310   iterator end()                        {      return m_sequential.end();     }
    00312   const_iterator end()  const           {      return m_sequential.end();     }
    00314   reverse_iterator rbegin()             {      return m_sequential.rbegin();  }
    00316   const_reverse_iterator rbegin() const {      return m_sequential.rbegin();  }
    00318   reverse_iterator rend()               {      return m_sequential.rend();    }
    00320   const_reverse_iterator rend() const   {      return m_sequential.rend();    }
    00322
    00340   value_type object(const key_type& kval) const     {  return i_object(kval);  }
    00341
    00351   value_type operator()(const key_type& kval) const {  return i_object(kval);  }
    00353
    00376   long erase(const key_type& kval)  { return i_erase(0, kval);  }
    00377
    00398   long erase(const value_type val) {
    00399     return (val) ? i_erase(val, val->key()) : (long) Containers::OBJ_NOT_FOUND;
    00400   }
    00401
    00422   long erase(iterator pos)   {                return erase(*pos);              }
    00423
    00432   void erase(iterator pos_start, iterator pos_stop, bool use_temp=false);
    00433
    00452   const key_type& insert(const value_type val, const key_type& kval);
    00453
    00475   const key_type& insert(const value_type val);
    00477 };
    00478
    00479
    00487 // Destructor
    00488 template <class DATATYPE, class MAPPING> inline
    00489 KeyedContainer<DATATYPE, MAPPING>::~KeyedContainer()
    00490 {
    00491   erase(begin(), end());
    00492   m_cont.clear();
    00493 }
    00494
    00495 // Configure direct access
    00496 template <class DATATYPE, class MAPPING> inline
    00497 void KeyedContainer<DATATYPE, MAPPING>::configureDirectAccess()
    00498 {
    00499   int count = 0;
    00500   m_cont.clearDirect();
    00501   typename seq_type::iterator i = m_sequential.begin();
    00502   typename seq_type::iterator s = m_sequential.end();
    00503   for ( ; i != s; i++ )  {
    00504     typename seq_type::value_type v = *i;
    00505     if ( v )  {
    00506       if ( !v->hasKey() ) {
    00507         traits::setKey(v, v->key());
    00508         traits::addRef(v);
    00509       }
    00510       long k0 = traits::hash(v->key());
    00511       if(m_cont.insertDirect(this, v, v, k0) == Containers::OBJ_INSERTED)   {
    00512       }
    00513     }
    00514     else  {
    00515       ++count;
    00516     }
    00517   }
    00518   if ( count > 0 )  {
    00519     Containers::cannotInsertToContainer();
    00520   }
    00521 }
    00522
    00523
    00524 // Retrieve the full content of the object container by reference.
    00525 template <class DATATYPE, class MAPPING> inline
    00526 const std::vector<const ContainedObject*>*
    00527 KeyedContainer<DATATYPE, MAPPING>::containedObjects() const  {
    00528   return (const std::vector<const ContainedObject*>*)
    00529     ((0==m_cont.isDirect()) ? m_random : &m_sequential);
    00530 }
    00531
    00532 template <class DATATYPE, class MAPPING> inline
    00533 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
    00534 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val,
    00535                                           const key_type& kval)
    00536 {
    00537   if ( val )    {
    00538     long k0 = traits::hash(kval);
    00539     if ( !val->hasKey() || (traits::hash(val->key()) == k0) )    {
    00540       if(m_cont.insert(this,val,val,k0) == Containers::OBJ_INSERTED)   {
    00541         if ( !val->hasKey() ) traits::setKey(val, kval);
    00542         traits::addRef(val);
    00543         return val->key();
    00544       }
    00545     }
    00546   }
    00547   // Cannot insert object...indicate bad object insertion...
    00548   Containers::cannotInsertToContainer();
    00549   return val->key();
    00550 }
    00551
    00552 // Insert object
    00553 template <class DATATYPE, class MAPPING> //inline
    00554 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
    00555 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val)
    00556 {
    00557   if ( 0 != val )   {
    00558     if ( val->hasKey() )   {
    00559       if (m_cont.insert(this,val,val,traits::hash(val->key()))
    00560           == Containers::OBJ_INSERTED)   {
    00561         traits::addRef(val);
    00562         return val->key();
    00563       }
    00564     }
    00565     long k0;
    00566     if ( m_cont.insert(this, val, val, &k0) == Containers::OBJ_INSERTED )   {
    00567       traits::setKey(val, traits::makeKey(k0));
    00568       traits::addRef(val);
    00569       return val->key();
    00570     }
    00571   }
    00572   // Cannot insert object...indicate bad object insertion...
    00573   Containers::cannotInsertToContainer();
    00574   return val->key();
    00575 }
    00576
    00577 template <class DATATYPE, class MAPPING> inline
    00578 long KeyedContainer<DATATYPE, MAPPING>::index(const ContainedObject* p) const
    00579 {
    00580   const contained_type* ptr = dynamic_cast<const contained_type*>(p);
    00581   if ( ptr ) return traits::identifier(ptr->key());
    00582   return -1;
    00583 }
    00584
    00585 // Retrieve the full content of the object container.
    00586 template <class DATATYPE, class MAPPING> inline
    00587 typename KeyedContainer<DATATYPE, MAPPING>::size_type KeyedContainer<DATATYPE, MAPPING>::containedObjects
    00588 (std::vector<ContainedObject*>& vec) const
    00589 {
    00590   typename seq_type::const_iterator i = m_sequential.begin();
    00591   typename seq_type::const_iterator s = m_sequential.end();
    00592   vec.clear();
    00593   vec.reserve(size());
    00594   for ( ; i != s; i++ )  {
    00595     ContainedObject* p = const_cast<typename seq_type::value_type>(*i);
    00596     vec.push_back(p);
    00597   }
    00598   return vec.size();
    00599 }
    00600
    00601 // ObjectContainerBase overload: Add an object to the container.
    00602 template <class DATATYPE, class MAPPING> inline
    00603 long KeyedContainer<DATATYPE, MAPPING>::add(ContainedObject* pObject)
    00604 {
    00605   return traits::identifier(insert(dynamic_cast<typename seq_type::value_type>(pObject)));
    00606 }
    00607
    00608 // ObjectContainerBase overload: Remove an object from the container.
    00609 template <class DATATYPE, class MAPPING> inline
    00610 long KeyedContainer<DATATYPE, MAPPING>::remove(ContainedObject* p)
    00611 {
    00612   contained_type* p1 = dynamic_cast<contained_type*>(p);
    00613   if ( p1 )    {  // Normal case; object still fully intact
    00614     return this->erase(p1);
    00615   }
    00616   else if ( p )   {
    00617     const ObjectContainerBase* par = p->parent();
    00618     // The following should never occur: object is in a funny state,
    00619     // Because the parent was explicitly set to NULL in the
    00620     // KeyeObject destructor.
    00621     // - It cannot be a KeyedObject:  It would not have a parent
    00622     // - Still the parent is present: We are not in the destructor
    00623     //                                of KeyedObject
    00624     if ( par )  {
    00625       Containers::invalidContainerOperation();
    00626     }
    00627     return m_cont.erase(0, p)==0 ? (long) Containers::OBJ_ERASED
    00628                                  : (long) Containers::OBJ_NOT_FOUND;
    00629   }
    00630   return (long) Containers::OBJ_NOT_FOUND;
    00631 }
    00632
    00633 template <class DATATYPE, class MAPPING> inline
    00634 void
    00635 KeyedContainer<DATATYPE, MAPPING>::erase(iterator start_pos,
    00636                                          iterator stop_pos,
    00637                                          bool use_tmp)
    00638 {
    00639   bool is_start = start_pos == m_sequential.begin();
    00640   bool is_stop  = stop_pos  == m_sequential.end();
    00641   if ( is_start && is_stop )  {
    00642     // Nothing special. Taken care of by Keyed object manager
    00643   }
    00644   else if ( is_start || is_stop || use_tmp )  {
    00645     std::vector<DATATYPE*> tmp(m_sequential.begin(), start_pos);
    00646     tmp.insert(tmp.end(), stop_pos, m_sequential.end());
    00647     std::for_each(tmp.begin(), tmp.end(), traits::addRef);
    00648     this->erase(m_sequential.begin(), m_sequential.end());
    00649     std::for_each(tmp.begin(), tmp.end(), _InsertRelease(this));
    00650     return;
    00651   }
    00652   std::for_each(start_pos, stop_pos, _RemoveRelease(this));
    00653   seq_type *sptr = &m_sequential; // avoid problems with strict-aliasing rules
    00654   std::vector<void*>* v = (std::vector<void*>*)sptr;
    00655   std::vector<void*>::iterator i1 =
    00656     v->begin() + std::distance(m_sequential.begin(), start_pos);
    00657   std::vector<void*>::iterator i2 =
    00658     v->begin() + std::distance(m_sequential.begin(), stop_pos);
    00659   m_cont.erase(i1, i2);
    00660 }
    00661
    00662 #undef FORCE_INLINE
    00663 #endif // GAUDIKERNEL_KEYEDCONTAINER_H