Gaudi Framework, version v21r9

Home   Generated: 3 May 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

Generated at Mon May 3 12:14:18 2010 for Gaudi Framework, version v21r9 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004