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

Generated at Wed Feb 9 16:24:51 2011 for Gaudi Framework, version v22r0 by Doxygen version 1.6.2 written by Dimitri van Heesch, © 1997-2004