| # Gaudi Framework, version v22r0 |

Home |  | Generated: 9 Feb 2011

# 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;
    00291   virtual StatusCode update();
    00293
    00307
    00308   iterator begin()                      {      return m_sequential.begin();   }
    00310   const_iterator begin()  const         {      return m_sequential.begin();   }
    00312   iterator end()                        {      return m_sequential.end();     }
    00314   const_iterator end()  const           {      return m_sequential.end();     }
    00316   reverse_iterator rbegin()             {      return m_sequential.rbegin();  }
    00318   const_reverse_iterator rbegin() const {      return m_sequential.rbegin();  }
    00320   reverse_iterator rend()               {      return m_sequential.rend();    }
    00322   const_reverse_iterator rend() const   {      return m_sequential.rend();    }
    00324
    00342   value_type object(const key_type& kval) const     {  return i_object(kval);  }
    00343
    00353   value_type operator()(const key_type& kval) const {  return i_object(kval);  }
    00355
    00378   long erase(const key_type& kval)  { return i_erase(0, kval);  }
    00379
    00400   long erase(const value_type val) {
    00401     return (val) ? i_erase(val, val->key()) : (long) Containers::OBJ_NOT_FOUND;
    00402   }
    00403
    00424   long erase(iterator pos)   {                return erase(*pos);              }
    00425
    00434   void erase(iterator pos_start, iterator pos_stop, bool use_temp=false);
    00435
    00454   const key_type& insert(const value_type val, const key_type& kval);
    00455
    00477   const key_type& insert(const value_type val);
    00479 };
    00480
    00481
    00489 // Destructor
    00490 template <class DATATYPE, class MAPPING> inline
    00491 KeyedContainer<DATATYPE, MAPPING>::~KeyedContainer()
    00492 {
    00493   erase(begin(), end());
    00494   m_cont.clear();
    00495 }
    00496
    00497 // Configure direct access
    00498 template <class DATATYPE, class MAPPING> inline
    00499 StatusCode KeyedContainer<DATATYPE, MAPPING>::update()
    00500 {
    00501   int count = 0;
    00502   m_cont.clearDirect();
    00503   typename seq_type::iterator i = m_sequential.begin();
    00504   typename seq_type::iterator s = m_sequential.end();
    00505   for ( ; i != s; i++ )  {
    00506     typename seq_type::value_type v = *i;
    00507     if ( v )  {
    00508       if ( !v->hasKey() ) {
    00509         traits::setKey(v, v->key());
    00510         traits::addRef(v);
    00511       }
    00512       long k0 = traits::hash(v->key());
    00513       if(m_cont.insertDirect(this, v, v, k0) == Containers::OBJ_INSERTED)   {
    00514       }
    00515     }
    00516     else  {
    00517       ++count;
    00518     }
    00519   }
    00520   if ( count > 0 )  {
    00521     Containers::cannotInsertToContainer();
    00522   }
    00523   return StatusCode::SUCCESS;
    00524 }
    00525
    00526
    00527 // Retrieve the full content of the object container by reference.
    00528 template <class DATATYPE, class MAPPING> inline
    00529 const std::vector<const ContainedObject*>*
    00530 KeyedContainer<DATATYPE, MAPPING>::containedObjects() const  {
    00531   return (const std::vector<const ContainedObject*>*)
    00532     ((0==m_cont.isDirect()) ? m_random : &m_sequential);
    00533 }
    00534
    00535 template <class DATATYPE, class MAPPING> inline
    00536 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
    00537 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val,
    00538                                           const key_type& kval)
    00539 {
    00540   if ( val )    {
    00541     long k0 = traits::hash(kval);
    00542     if ( !val->hasKey() || (traits::hash(val->key()) == k0) )    {
    00543       if(m_cont.insert(this,val,val,k0) == Containers::OBJ_INSERTED)   {
    00544         if ( !val->hasKey() ) traits::setKey(val, kval);
    00545         traits::addRef(val);
    00546         return val->key();
    00547       }
    00548     }
    00549   }
    00550   // Cannot insert object...indicate bad object insertion...
    00551   Containers::cannotInsertToContainer();
    00552   return val->key();
    00553 }
    00554
    00555 // Insert object
    00556 template <class DATATYPE, class MAPPING> //inline
    00557 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
    00558 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val)
    00559 {
    00560   if ( 0 != val )   {
    00561     if ( val->hasKey() )   {
    00562       if (m_cont.insert(this,val,val,traits::hash(val->key()))
    00563           == Containers::OBJ_INSERTED)   {
    00564         traits::addRef(val);
    00565         return val->key();
    00566       }
    00567     }
    00568     long k0;
    00569     if ( m_cont.insert(this, val, val, &k0) == Containers::OBJ_INSERTED )   {
    00570       traits::setKey(val, traits::makeKey(k0));
    00571       traits::addRef(val);
    00572       return val->key();
    00573     }
    00574   }
    00575   // Cannot insert object...indicate bad object insertion...
    00576   Containers::cannotInsertToContainer();
    00577   return val->key();
    00578 }
    00579
    00580 template <class DATATYPE, class MAPPING> inline
    00581 long KeyedContainer<DATATYPE, MAPPING>::index(const ContainedObject* p) const
    00582 {
    00583   const contained_type* ptr = dynamic_cast<const contained_type*>(p);
    00584   if ( ptr ) return traits::identifier(ptr->key());
    00585   return -1;
    00586 }
    00587
    00588 // Retrieve the full content of the object container.
    00589 template <class DATATYPE, class MAPPING> inline
    00590 typename KeyedContainer<DATATYPE, MAPPING>::size_type KeyedContainer<DATATYPE, MAPPING>::containedObjects
    00591 (std::vector<ContainedObject*>& vec) const
    00592 {
    00593   typename seq_type::const_iterator i = m_sequential.begin();
    00594   typename seq_type::const_iterator s = m_sequential.end();
    00595   vec.clear();
    00596   vec.reserve(size());
    00597   for ( ; i != s; i++ )  {
    00598     ContainedObject* p = const_cast<typename seq_type::value_type>(*i);
    00599     vec.push_back(p);
    00600   }
    00601   return vec.size();
    00602 }
    00603
    00604 // ObjectContainerBase overload: Add an object to the container.
    00605 template <class DATATYPE, class MAPPING> inline
    00606 long KeyedContainer<DATATYPE, MAPPING>::add(ContainedObject* pObject)
    00607 {
    00608   return traits::identifier(insert(dynamic_cast<typename seq_type::value_type>(pObject)));
    00609 }
    00610
    00611 // ObjectContainerBase overload: Remove an object from the container.
    00612 template <class DATATYPE, class MAPPING> inline
    00613 long KeyedContainer<DATATYPE, MAPPING>::remove(ContainedObject* p)
    00614 {
    00615   contained_type* p1 = dynamic_cast<contained_type*>(p);
    00616   if ( p1 )    {  // Normal case; object still fully intact
    00617     return this->erase(p1);
    00618   }
    00619   else if ( p )   {
    00620     const ObjectContainerBase* par = p->parent();
    00621     // The following should never occur: object is in a funny state,
    00622     // Because the parent was explicitly set to NULL in the
    00623     // KeyeObject destructor.
    00624     // - It cannot be a KeyedObject:  It would not have a parent
    00625     // - Still the parent is present: We are not in the destructor
    00626     //                                of KeyedObject
    00627     if ( par )  {
    00628       Containers::invalidContainerOperation();
    00629     }
    00630     return m_cont.erase(0, p)==0 ? (long) Containers::OBJ_ERASED
    00631                                  : (long) Containers::OBJ_NOT_FOUND;
    00632   }
    00633   return (long) Containers::OBJ_NOT_FOUND;
    00634 }
    00635
    00636 template <class DATATYPE, class MAPPING> inline
    00637 void
    00638 KeyedContainer<DATATYPE, MAPPING>::erase(iterator start_pos,
    00639                                          iterator stop_pos,
    00640                                          bool use_tmp)
    00641 {
    00642   bool is_start = start_pos == m_sequential.begin();
    00643   bool is_stop  = stop_pos  == m_sequential.end();
    00644   if ( is_start && is_stop )  {
    00645     // Nothing special. Taken care of by Keyed object manager
    00646   }
    00647   else if ( is_start || is_stop || use_tmp )  {
    00648     std::vector<DATATYPE*> tmp(m_sequential.begin(), start_pos);
    00649     tmp.insert(tmp.end(), stop_pos, m_sequential.end());
    00650     std::for_each(tmp.begin(), tmp.end(), traits::addRef);
    00651     this->erase(m_sequential.begin(), m_sequential.end());
    00652     std::for_each(tmp.begin(), tmp.end(), _InsertRelease(this));
    00653     return;
    00654   }
    00655   std::for_each(start_pos, stop_pos, _RemoveRelease(this));
    00656   seq_type *sptr = &m_sequential; // avoid problems with strict-aliasing rules
    00657   std::vector<void*>* v = (std::vector<void*>*)sptr;
    00658   std::vector<void*>::iterator i1 =
    00659     v->begin() + std::distance(m_sequential.begin(), start_pos);
    00660   std::vector<void*>::iterator i2 =
    00661     v->begin() + std::distance(m_sequential.begin(), stop_pos);
    00662   m_cont.erase(i1, i2);
    00663 }
    00664
    00665 #undef FORCE_INLINE
    00666 #endif // GAUDIKERNEL_KEYEDCONTAINER_H

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines