00001
00002 #ifndef GAUDIKERNEL_TRANSIENTFASTCONTAINER_H
00003 #define GAUDIKERNEL_TRANSIENTFASTCONTAINER_H 1
00004
00005
00006 #include "GaudiKernel/DataObject.h"
00007 #include <vector>
00008 #include <stdexcept>
00009 #include <typeinfo>
00010 #include <functional>
00011
00012
00021 class TransientFastContainerBase: public DataObject {
00022 public:
00024 virtual ~TransientFastContainerBase();
00026 virtual void clear() = 0;
00028 virtual void free() = 0;
00030 virtual const std::type_info &containedType() const = 0;
00031 };
00032
00033
00042 template <class T>
00043 struct DefaultObjectCleaner: public std::unary_function<T*,T*>{
00046 inline T* operator() (T* obj ) const {
00047 obj->T::~T();
00048 return new(obj) T();
00049 }
00053 inline T* operator() (T* obj, const T &rhs ) const {
00054 obj->T::~T();
00055 return new(obj) T(rhs);
00056 }
00058 inline T* destruct(T* obj) const {
00059 obj->T::~T();
00060 return obj;
00061 }
00062
00063 };
00064
00065
00082 template <class T, class CLEANER = DefaultObjectCleaner<T> >
00083 class TransientFastContainer: public TransientFastContainerBase {
00084 public:
00085
00086 typedef T contained_type;
00087 typedef contained_type* value_type;
00088
00089 typedef value_type pointer;
00090 typedef const value_type const_pointer;
00091
00092 typedef value_type reference;
00093 typedef const value_type const_reference;
00094
00095 typedef std::vector<value_type> storage_type;
00096
00097 typedef typename storage_type::size_type size_type;
00098
00099 typedef typename storage_type::iterator iterator;
00100 typedef typename storage_type::const_iterator const_iterator;
00101
00102 typedef CLEANER cleaner_type;
00103
00105 TransientFastContainer(size_type n=0);
00106
00108 virtual ~TransientFastContainer( );
00109
00110
00111
00113 virtual void clear();
00114
00116 virtual void free();
00117
00119 virtual const std::type_info &containedType() const { return typeid(contained_type); }
00120
00121
00122
00125 inline pointer New() { return ( m_counter++ < m_current_size ) ? m_cleaner(*(m_end++)) : i_new(); }
00126
00129 inline pointer Add(const T &rhs) { return ( m_counter++ < m_current_size ) ? m_cleaner(*(m_end++),rhs) : i_new(rhs); }
00130
00133 inline pointer NewPointer()
00134 { return ( m_counter++ < m_current_size ) ? m_cleaner.destruct(*(m_end++)) : m_cleaner.destruct(i_new()); }
00135
00137 inline iterator begin() { return m_storage.begin(); }
00139 inline const_iterator begin() const { return m_storage.begin(); }
00140
00142 inline iterator end() { return m_end; }
00144 inline const_iterator end() const { return m_end; }
00145
00147 inline size_type size() const { return m_counter; }
00148
00150 inline pointer operator[] (size_type index)
00151 { return (index < size()) ? m_storage[index] : throw std::out_of_range("index out of range"), (pointer)NULL; }
00153 inline const contained_type* operator[] (size_type index) const
00154 { return (index < size()) ? m_storage[index] : throw std::out_of_range("index out of range"), (const_pointer)NULL; }
00155
00157 inline pointer at(size_type index) { return operator[] (index); }
00159 inline const contained_type* at(size_type index) const { return operator[] (index); }
00160
00161 private:
00162
00164 pointer i_new();
00165
00167 pointer i_new(const T &rhs);
00168
00170 size_type m_counter;
00171
00173 size_type m_current_size;
00174
00176 storage_type m_storage;
00177
00179 iterator m_end;
00180
00182 cleaner_type m_cleaner;
00183 };
00184
00185 template <class T, class CLEANER>
00186 TransientFastContainer<T,CLEANER>::TransientFastContainer(size_type n):
00187 TransientFastContainerBase(),
00188 m_counter(0),
00189 m_current_size(0),
00190 m_storage(),
00191 m_end(m_storage.begin()),
00192 m_cleaner()
00193 {
00194 if (n>0) {
00195 m_storage.reserve(n);
00196 for(;n>0;--n) New();
00197 clear();
00198 }
00199 }
00200
00201 template <class T, class CLEANER>
00202 TransientFastContainer<T,CLEANER>::~TransientFastContainer()
00203 {
00204 free();
00205 }
00206
00207
00208 template <class T, class CLEANER>
00209 void TransientFastContainer<T,CLEANER>::clear() {
00210 m_counter = 0;
00211 m_end = m_storage.begin();
00212 }
00213
00214 template <class T, class CLEANER>
00215 void TransientFastContainer<T,CLEANER>::free() {
00216 for( typename storage_type::iterator i = m_storage.begin();
00217 i != m_storage.end();
00218 ++i ) {
00219 delete *i;
00220 }
00221 m_storage.clear();
00222 m_counter = m_current_size = 0;
00223 m_end = m_storage.begin();
00224 }
00225
00226 template <class T, class CLEANER>
00227 typename TransientFastContainer<T,CLEANER>::pointer TransientFastContainer<T,CLEANER>::i_new() {
00228
00229 ++m_current_size;
00230 pointer ptr = new T();
00231 m_storage.push_back(ptr);
00232 m_end = m_storage.end();
00233 return ptr;
00234 }
00235
00236 template <class T, class CLEANER>
00237 typename TransientFastContainer<T,CLEANER>::pointer TransientFastContainer<T,CLEANER>::i_new(const T &rhs) {
00238
00239 ++m_current_size;
00240 pointer ptr = new T(rhs);
00241 m_storage.push_back(ptr);
00242 m_end = m_storage.end();
00243 return ptr;
00244 }
00245
00246 #endif // GAUDIKERNEL_TRANSIENTFASTCONTAINER_H