00001
00023 #ifndef GALOIS_GDEQUE_H
00024 #define GALOIS_GDEQUE_H
00025
00026 #include "Galois/config.h"
00027 #include "Galois/FixedSizeRing.h"
00028 #include "Galois/Runtime/mm/Mem.h"
00029
00030 #include <boost/iterator/iterator_facade.hpp>
00031
00032 #include GALOIS_CXX11_STD_HEADER(algorithm)
00033 #include GALOIS_CXX11_STD_HEADER(utility)
00034
00035 namespace Galois {
00036
00038 template<typename T, unsigned ChunkSize=64, typename ContainerTy=FixedSizeRing<T, ChunkSize> >
00039 class gdeque: private boost::noncopyable {
00040 protected:
00041 struct Block: ContainerTy {
00042 Block* next;
00043 Block* prev;
00044 Block(): next(), prev() {}
00045 };
00046
00047 Block* first;
00048
00049 private:
00050 Block* last;
00051 unsigned num;
00052
00053 Galois::Runtime::MM::FixedSizeAllocator heap;
00054
00055 Block* alloc_block() {
00056 return new (heap.allocate(sizeof(Block))) Block();
00057 }
00058
00059 bool precondition() const {
00060 return (num == 0 && first == NULL && last == NULL)
00061 || (num > 0 && first != NULL && last != NULL);
00062 }
00063
00064 void free_block(Block* b) {
00065 b->~Block();
00066 heap.deallocate(b);
00067 }
00068
00069 void extend_first() {
00070 Block* b = alloc_block();
00071 b->next = first;
00072 if (b->next)
00073 b->next->prev = b;
00074 first = b;
00075 if (!last)
00076 last = b;
00077 }
00078
00079 void extend_last() {
00080 Block* b = alloc_block();
00081 b->prev = last;
00082 if (b->prev)
00083 b->prev->next = b;
00084 last = b;
00085 if (!first)
00086 first = b;
00087 }
00088
00089 void shrink_first() {
00090 Block* b = first;
00091 first = b->next;
00092 if (b->next)
00093 b->next->prev = 0;
00094 else
00095 last = 0;
00096 free_block(b);
00097 }
00098
00099 void shrink_last() {
00100 Block* b = last;
00101 last = b->prev;
00102 if (b->prev)
00103 b->prev->next = 0;
00104 else
00105 first = 0;
00106 free_block(b);
00107 }
00108
00109 public:
00110 template<typename U>
00111 struct Iterator: public boost::iterator_facade<Iterator<U>, U, boost::forward_traversal_tag> {
00112 friend class boost::iterator_core_access;
00113
00114 Block* b;
00115 unsigned offset;
00116
00117 private:
00118 void increment() {
00119 if (!b) return;
00120 ++offset;
00121 if (offset == b->size()) {
00122 b = b->next;
00123 offset = 0;
00124 }
00125 }
00126
00127 template<typename OtherTy>
00128 bool equal(const Iterator<OtherTy>& o) const { return b == o.b && offset == o.offset; }
00129
00130 U& dereference() const { return b->getAt(offset); }
00131
00132 public:
00133 Iterator(Block* _b = 0, unsigned _off = 0) :b(_b), offset(_off) { }
00134
00135 template<typename OtherTy>
00136 Iterator(const Iterator<OtherTy>& o): b(o.b), offset(o.offset) { }
00137 };
00138
00139 typedef T value_type;
00140 typedef T* pointer;
00141 typedef T& reference;
00142 typedef const T& const_reference;
00143 typedef Iterator<T> iterator;
00144 typedef Iterator<const T> const_iterator;
00145
00146 gdeque(): first(), last(), num(), heap(sizeof(Block)) { }
00147
00148 ~gdeque() { clear(); }
00149
00150 iterator begin() { assert(precondition()); return iterator(first); }
00151 iterator end() { assert(precondition()); return iterator(); }
00152 const_iterator begin() const { assert(precondition()); return const_iterator(first); }
00153 const_iterator end() const { assert(precondition()); return const_iterator(); }
00154
00155 size_t size() const {
00156 assert(precondition());
00157 return num;
00158 }
00159
00160 bool empty() const {
00161 assert(precondition());
00162 return num == 0;
00163 }
00164
00165 reference front() {
00166 assert(!empty());
00167 return first->front();
00168 }
00169
00170 const_reference front() const {
00171 assert(!empty());
00172 return first->front();
00173 }
00174
00175 reference back() {
00176 assert(!empty());
00177 return last->back();
00178 }
00179
00180 const_reference back() const {
00181 assert(!empty());
00182 return last->back();
00183 }
00184
00185 void pop_back() {
00186 assert(!empty());
00187 --num;
00188 last->pop_back();
00189 if (last->empty())
00190 shrink_last();
00191 }
00192
00193 void pop_front() {
00194 assert(!empty());
00195 --num;
00196 first->pop_front();
00197 if (first->empty())
00198 shrink_first();
00199 }
00200
00201 void clear() {
00202 assert(precondition());
00203 Block* b = first;
00204 while (b) {
00205 b->clear();
00206 Block* old = b;
00207 b = b->next;
00208 free_block(old);
00209 }
00210 first = last = NULL;
00211 num = 0;
00212 }
00213
00214
00215 iterator insert(iterator position, size_t n, const value_type& val) {
00216 assert(position == end());
00217 if (!n)
00218 return end();
00219
00220 push_back(val);
00221 iterator retval = iterator(last, last->size()-1);
00222 for (size_t x = 1; x < n; ++x)
00223 push_back(val);
00224 return retval;
00225 }
00226
00227 template<typename... Args>
00228 void emplace_back(Args&&... args) {
00229 assert(precondition());
00230 ++num;
00231 if (last && last->emplace_back(std::forward<Args>(args)...))
00232 return;
00233 extend_last();
00234 pointer p = last->emplace_back(std::forward<Args>(args)...);
00235 assert(p);
00236 }
00237
00238 void push_back(value_type&& v) {
00239 emplace_back(std::move(v));
00240 }
00241
00242 void push_back(const value_type& v) {
00243 emplace_back(v);
00244 }
00245
00246 template<typename... Args>
00247 void emplace_front(Args&&... args) {
00248 assert(precondition());
00249 ++num;
00250 if (first && first->emplace_front(std::forward<Args>(args)...))
00251 return;
00252 extend_first();
00253 pointer p = first->emplace_front(std::forward<Args>(args)...);
00254 assert(p);
00255 }
00256
00257 void push_front(value_type&& v) {
00258 emplace_front(std::move(v));
00259 }
00260
00261 void push_front(const value_type& v) {
00262 emplace_front(v);
00263 }
00264 };
00265
00266 }
00267 #endif