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