00001 00023 #ifndef GALOIS_FIXEDSIZERING_H 00024 #define GALOIS_FIXEDSIZERING_H 00025 00026 #include "Galois/config.h" 00027 #include "Galois/optional.h" 00028 #include "Galois/LazyArray.h" 00029 00030 #include <boost/iterator/iterator_facade.hpp> 00031 #include <boost/utility.hpp> 00032 00033 #include GALOIS_CXX11_STD_HEADER(utility) 00034 00035 namespace Galois { 00036 00038 template<typename T, unsigned chunksize = 64> 00039 class FixedSizeBag: private boost::noncopyable { 00040 LazyArray<T, chunksize> datac; 00041 unsigned count; 00042 00043 T* at(unsigned i) { return &datac[i]; } 00044 const T* at(unsigned i) const { return &datac[i]; } 00045 00046 bool precondition() const { 00047 return count <= chunksize; 00048 } 00049 00050 public: 00051 typedef T value_type; 00052 typedef T* pointer; 00053 typedef const T* const_pointer; 00054 typedef T& reference; 00055 typedef const T& const_reference; 00056 typedef pointer iterator; 00057 typedef const_pointer const_iterator; 00058 00059 FixedSizeBag(): count(0) { } 00060 00061 ~FixedSizeBag() { 00062 clear(); 00063 } 00064 00065 unsigned size() const { 00066 assert(precondition()); 00067 return count; 00068 } 00069 00070 bool empty() const { 00071 assert(precondition()); 00072 return count == 0; 00073 } 00074 00075 bool full() const { 00076 assert(precondition()); 00077 return count == chunksize; 00078 } 00079 00080 void clear() { 00081 assert(precondition()); 00082 for (unsigned x = 0; x < count; ++x) 00083 datac.destroy(x); 00084 count = 0; 00085 } 00086 00087 template<typename U> 00088 pointer push_front(U&& val) { return push_back(std::forward<U>(val)); } 00089 00090 template<typename... Args> 00091 pointer emplace_front(Args&&... args) { return emplace_back(std::forward<Args>(args)...); } 00092 00093 template<typename U> 00094 pointer push_back(U&& val) { 00095 if (full()) return 0; 00096 unsigned end = count; 00097 ++count; 00098 return datac.construct(end, std::forward<U>(val)); 00099 } 00100 00101 template<typename... Args> 00102 pointer emplace_back(Args&&... args) { 00103 if (full()) return 0; 00104 unsigned end = count; 00105 ++count; 00106 return datac.emplace(end, std::forward<Args>(args)...); 00107 } 00108 00109 reference front() { return back(); } 00110 const_reference front() const { return back(); } 00111 Galois::optional<value_type> extract_front() { return extract_back(); } 00112 00113 void pop_front() { 00114 pop_back(); 00115 } 00116 00117 reference back() { 00118 assert(precondition()); 00119 assert(!empty()); 00120 return *at(count - 1); 00121 } 00122 00123 const_reference back() const { 00124 assert(precondition()); 00125 assert(!empty()); 00126 return *at(count - 1); 00127 } 00128 00129 Galois::optional<value_type> extract_back() { 00130 if (!empty()) { 00131 Galois::optional<value_type> retval(back()); 00132 pop_back(); 00133 return retval; 00134 } 00135 return Galois::optional<value_type>(); 00136 } 00137 00138 void pop_back() { 00139 assert(precondition()); 00140 assert(!empty()); 00141 unsigned end = (count - 1); 00142 datac.destroy(end); 00143 --count; 00144 } 00145 00146 iterator begin() { return &datac[0]; } 00147 iterator end() { return &datac[count]; } 00148 const_iterator begin() const { return &datac[0]; } 00149 const_iterator end() const { return &datac[count]; } 00150 }; 00151 00153 template<typename T, unsigned chunksize = 64> 00154 class FixedSizeRing: private boost::noncopyable { 00155 LazyArray<T, chunksize> datac; 00156 unsigned start; 00157 unsigned count; 00158 00159 T* at(unsigned i) { return &datac[i]; } 00160 const T* at(unsigned i) const { return &datac[i]; } 00161 00162 bool precondition() const { 00163 return count <= chunksize && start <= chunksize; 00164 } 00165 00166 template<typename U, bool isForward> 00167 class Iterator: public boost::iterator_facade<Iterator<U,isForward>, U, boost::forward_traversal_tag> { 00168 friend class boost::iterator_core_access; 00169 U* base; 00170 unsigned cur; 00171 unsigned count; 00172 00173 template<typename OtherTy, bool OtherIsForward> 00174 bool equal(const Iterator<OtherTy, OtherIsForward>& o) const { 00175 return base + cur == o.base + o.cur && count == o.count; 00176 } 00177 00178 U& dereference() const { return base[cur]; } 00179 00180 void increment() { 00181 if (--count == 0) { 00182 base = 0; cur = 0; 00183 } else { 00184 cur = isForward ? (cur + 1) % chunksize : (cur + chunksize - 1) % chunksize; 00185 } 00186 } 00187 00188 public: 00189 Iterator(): base(0), cur(0), count(0) { } 00190 00191 template<typename OtherTy, bool OtherIsForward> 00192 Iterator(const Iterator<OtherTy, OtherIsForward>& o): base(o.base), cur(o.cur), count(o.count) { } 00193 00194 Iterator(U* b, unsigned c, unsigned co): base(b), cur(c), count(co) { 00195 if (count == 0) { 00196 base = 0; 00197 cur = 0; 00198 } 00199 } 00200 }; 00201 00202 public: 00203 typedef T value_type; 00204 typedef T* pointer; 00205 typedef T& reference; 00206 typedef const T& const_reference; 00207 typedef Iterator<T, true> iterator; 00208 typedef Iterator<const T, true> const_iterator; 00209 typedef Iterator<T, false> reverse_iterator; 00210 typedef Iterator<const T, false> const_reverse_iterator; 00211 00212 FixedSizeRing(): start(0), count(0) { } 00213 00214 ~FixedSizeRing() { 00215 clear(); 00216 } 00217 00218 unsigned size() const { 00219 assert(precondition()); 00220 return count; 00221 } 00222 00223 bool empty() const { 00224 assert(precondition()); 00225 return count == 0; 00226 } 00227 00228 bool full() const { 00229 assert(precondition()); 00230 return count == chunksize; 00231 } 00232 00233 reference getAt(unsigned x) { 00234 assert(precondition()); 00235 assert(!empty()); 00236 return *at((start + x) % chunksize); 00237 } 00238 00239 const_reference getAt(unsigned x) const { 00240 assert(precondition()); 00241 assert(!empty()); 00242 return *at((start + x) % chunksize); 00243 } 00244 00245 void clear() { 00246 assert(precondition()); 00247 for (unsigned x = 0; x < count; ++x) 00248 datac.destroy((start + x) % chunksize); 00249 count = 0; 00250 start = 0; 00251 } 00252 00253 template<typename U> 00254 pointer push_front(U&& val) { 00255 if (full()) return 0; 00256 start = (start + chunksize - 1) % chunksize; 00257 ++count; 00258 return datac.construct(start, std::forward<U>(val)); 00259 } 00260 00261 template<typename... Args> 00262 pointer emplace_front(Args&&... args) { 00263 if (full()) return 0; 00264 start = (start + chunksize - 1) % chunksize; 00265 ++count; 00266 return datac.emplace(start, std::forward<Args>(args)...); 00267 } 00268 00269 template<typename U> 00270 pointer push_back(U&& val) { 00271 if (full()) return 0; 00272 unsigned end = (start + count) % chunksize; 00273 ++count; 00274 return datac.construct(end, std::forward<U>(val)); 00275 } 00276 00277 template<typename... Args> 00278 pointer emplace_back(Args&&... args) { 00279 if (full()) return 0; 00280 unsigned end = (start + count) % chunksize; 00281 ++count; 00282 return datac.emplace(end, std::forward<Args>(args)...); 00283 } 00284 00285 reference front() { 00286 assert(precondition()); 00287 assert(!empty()); 00288 return *at(start); 00289 } 00290 00291 const_reference front() const { 00292 assert(precondition()); 00293 assert(!empty()); 00294 return *at(start); 00295 } 00296 00297 Galois::optional<value_type> extract_front() { 00298 if (!empty()) { 00299 Galois::optional<value_type> retval(front()); 00300 pop_front(); 00301 return retval; 00302 } 00303 return Galois::optional<value_type>(); 00304 } 00305 00306 void pop_front() { 00307 assert(precondition()); 00308 assert(!empty()); 00309 datac.destroy(start); 00310 start = (start + 1) % chunksize; 00311 --count; 00312 } 00313 00314 reference back() { 00315 assert(precondition()); 00316 assert(!empty()); 00317 return *at((start + count - 1) % chunksize); 00318 } 00319 00320 const_reference back() const { 00321 assert(precondition()); 00322 assert(!empty()); 00323 return *at((start + count - 1) % chunksize); 00324 } 00325 00326 Galois::optional<value_type> extract_back() { 00327 if (!empty()) { 00328 Galois::optional<value_type> retval(back()); 00329 pop_back(); 00330 return retval; 00331 } 00332 return Galois::optional<value_type>(); 00333 } 00334 00335 void pop_back() { 00336 assert(precondition()); 00337 assert(!empty()); 00338 unsigned end = (start + count - 1) % chunksize; 00339 datac.destroy(end); 00340 --count; 00341 } 00342 00343 iterator begin() { return iterator(&datac[0], start, count); } 00344 iterator end() { return iterator(); } 00345 const_iterator begin() const { return const_iterator(&datac[0], start, count); } 00346 const_iterator end() const { return const_iterator(); } 00347 00348 reverse_iterator rbegin() { return reverse_iterator(&datac[0], (start + count - 1) % chunksize, count); } 00349 reverse_iterator rend() { return reverse_iterator(); } 00350 const_iterator rbegin() const { const_reverse_iterator(&datac[0], (start + count - 1) % chunksize, count); } 00351 const_iterator rend() const { const_reverse_iterator(); } 00352 }; 00353 00354 } 00355 00356 #endif