00001 // This file's extension implies that it's C, but it's really -*- C++ -*-. 00002 // $Id$ 00011 #ifndef CXXUTILS_POINTER_LIST_H 00012 #define CXXUTILS_POINTER_LIST_H 00013 00014 00015 #include "boost/static_assert.hpp" 00016 #include <iterator> 00017 00018 00019 namespace CxxUtils { 00020 00021 00051 class pointer_list_base 00052 { 00053 public: 00062 struct list_block 00063 { 00064 public: 00065 typedef unsigned long ulong; 00066 00068 typedef void* value_type; 00069 00072 value_type m_data[1]; 00073 00076 static size_t size (size_t nelt); 00077 }; 00078 00079 00091 class allocator 00092 { 00093 public: 00103 allocator (size_t nelt, 00104 size_t nblock, 00105 unsigned long end_mask, 00106 unsigned long end_offs); 00107 00109 ~allocator(); 00110 00112 list_block* allocate(); 00113 00116 size_t nelt() const; 00117 00119 size_t nchunks() const; 00120 00122 bool at_end (const void* p) const; 00123 00124 00125 private: 00127 void refill(); 00128 00130 struct chunk 00131 { 00133 chunk* m_next; 00134 00136 list_block* m_blocks; 00137 }; 00138 00140 size_t m_nelt; 00141 00143 size_t m_nblock; 00144 00146 chunk* m_chunks; 00147 00149 size_t m_nthis; 00150 00152 size_t m_nchunks; 00153 00155 unsigned long m_end_mask; 00156 00158 unsigned long m_end_offs; 00159 }; 00160 00161 00163 typedef allocator pool_type; 00164 00166 typedef list_block::value_type value_type; 00167 00169 pointer_list_base (pool_type& pool); 00170 00172 void push_back (value_type p); 00173 00175 size_t size() const; 00176 00180 void clear(); 00181 00183 bool empty() const; 00184 00185 00186 protected: 00188 list_block* m_head; 00189 00191 value_type* m_insert; 00192 00194 size_t m_size; 00195 00197 allocator& m_pool; 00198 00200 void firstblock (); 00201 00204 void nextblock (); 00205 00207 list_block* getblock(); 00208 }; 00209 00210 00236 template <size_t NELT = 15> 00237 class pointer_list 00238 : public pointer_list_base 00239 { 00240 public: 00242 typedef pointer_list_base::value_type value_type; 00243 00244 00251 class allocator 00252 : public pointer_list_base::allocator 00253 { 00254 public: 00256 BOOST_STATIC_ASSERT (((NELT+1) & NELT) == 0); 00257 00259 static const unsigned long END_OFFS = NELT * sizeof(value_type); 00260 static const unsigned long END_MASK = END_OFFS | (sizeof(value_type)-1); 00261 00266 allocator (size_t nblock = 100); 00267 00268 00270 static bool at_end_static (const void* p); 00271 }; 00272 00273 00277 class iterator 00278 : public std::iterator<std::forward_iterator_tag, value_type> 00279 { 00280 public: 00281 typedef typename std::iterator<std::forward_iterator_tag, value_type> 00282 base; 00283 typedef typename base::iterator_category iterator_category; 00284 typedef typename base::difference_type difference_type; 00285 typedef typename base::pointer pointer; 00286 typedef typename base::reference reference; 00287 00289 bool operator== (const iterator& other) const; 00290 00292 bool operator!= (const iterator& other) const; 00293 00295 reference operator*() const; 00296 00298 iterator& operator++(); 00299 00301 iterator operator++(int); 00302 00303 00304 private: 00306 iterator (value_type* p); 00307 00309 value_type* m_p; 00310 00311 friend class pointer_list; 00312 }; 00313 00314 typedef allocator pool_type; 00315 00317 pointer_list (pool_type& pool); 00318 00320 iterator begin(); 00321 00323 iterator end(); 00324 00326 void erase (iterator it); 00327 }; 00328 00329 00330 } // namespace CxxUtils 00331 00332 00333 #include "CxxUtils/pointer_list.icc" 00334 00335 00336 #endif // not CXXUTILS_POINTER_LIST_H