| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

In This Package:

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
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

Generated on Mon Apr 11 19:56:58 2011 for GaudiKernel by doxygen 1.4.7