00001
00024 #ifndef GALOIS_WORKLIST_CHUNKED_H
00025 #define GALOIS_WORKLIST_CHUNKED_H
00026
00027 #include "Galois/FixedSizeRing.h"
00028 #include "Galois/Runtime/ll/PaddedLock.h"
00029 #include "Galois/WorkList/WorkListHelpers.h"
00030 #include "WLCompileCheck.h"
00031
00032 namespace Galois {
00033 namespace WorkList {
00034
00035
00036 template<bool, template<typename> class PS, typename TQ>
00037 struct squeue {
00038 PS<TQ> queues;
00039 TQ& get(int i) { return *queues.getRemote(i); }
00040 TQ& get() { return *queues.getLocal(); }
00041 int myEffectiveID() { return Runtime::LL::getTID(); }
00042 int size() { return Runtime::activeThreads; }
00043 };
00044
00045 template<template<typename> class PS, typename TQ>
00046 struct squeue<false, PS, TQ> {
00047 TQ queue;
00048 TQ& get(int i) { return queue; }
00049 TQ& get() { return queue; }
00050 int myEffectiveID() { return 0; }
00051 int size() { return 0; }
00052 };
00053
00055 template<typename T, template<typename, bool> class QT, bool Distributed, bool IsStack, int ChunkSize, bool Concurrent>
00056 struct ChunkedMaster : private boost::noncopyable {
00057 template<bool _concurrent>
00058 struct rethread { typedef ChunkedMaster<T, QT, Distributed, IsStack, ChunkSize, _concurrent> type; };
00059
00060 template<typename _T>
00061 struct retype { typedef ChunkedMaster<_T, QT, Distributed, IsStack, ChunkSize, Concurrent> type; };
00062
00063 template<int _chunk_size>
00064 struct with_chunk_size { typedef ChunkedMaster<T, QT, Distributed, IsStack, _chunk_size, Concurrent> type; };
00065
00066 private:
00067 class Chunk : public FixedSizeRing<T, ChunkSize>, public QT<Chunk, Concurrent>::ListNode {};
00068
00069 Runtime::MM::FixedSizeAllocator heap;
00070
00071 struct p {
00072 Chunk* cur;
00073 Chunk* next;
00074 p(): cur(0), next(0) { }
00075 };
00076
00077 typedef QT<Chunk, Concurrent> LevelItem;
00078
00079 squeue<Concurrent, Runtime::PerThreadStorage, p> data;
00080 squeue<Distributed, Runtime::PerPackageStorage, LevelItem> Q;
00081
00082 Chunk* mkChunk() {
00083 return new (heap.allocate(sizeof(Chunk))) Chunk();
00084 }
00085
00086 void delChunk(Chunk* C) {
00087 C->~Chunk();
00088 heap.deallocate(C);
00089 }
00090
00091 void pushChunk(Chunk* C) {
00092 LevelItem& I = Q.get();
00093 I.push(C);
00094 }
00095
00096 Chunk* popChunkByID(unsigned int i) {
00097 LevelItem& I = Q.get(i);
00098 return I.pop();
00099 }
00100
00101 Chunk* popChunk() {
00102 int id = Q.myEffectiveID();
00103 Chunk* r = popChunkByID(id);
00104 if (r)
00105 return r;
00106
00107 for (int i = id + 1; i < (int) Q.size(); ++i) {
00108 r = popChunkByID(i);
00109 if (r)
00110 return r;
00111 }
00112
00113 for (int i = 0; i < id; ++i) {
00114 r = popChunkByID(i);
00115 if (r)
00116 return r;
00117 }
00118
00119 return 0;
00120 }
00121
00122 template<typename... Args>
00123 T* emplacei(p& n, Args&&... args) {
00124 T* retval = 0;
00125 if (n.next && (retval = n.next->emplace_back(std::forward<Args>(args)...)))
00126 return retval;
00127 if (n.next)
00128 pushChunk(n.next);
00129 n.next = mkChunk();
00130 retval = n.next->emplace_back(std::forward<Args>(args)...);
00131 assert(retval);
00132 return retval;
00133 }
00134
00135 public:
00136 typedef T value_type;
00137
00138 ChunkedMaster() : heap(sizeof(Chunk)) { }
00139
00140 void flush() {
00141 p& n = data.get();
00142 if (n.next)
00143 pushChunk(n.next);
00144 n.next = 0;
00145 }
00146
00154 template<typename... Args>
00155 value_type* emplace(Args&&... args) {
00156 p& n = data.get();
00157 return emplacei(n, std::forward<Args>(args)...);
00158 }
00159
00165 value_type* peek() {
00166 p& n = data.get();
00167 if (IsStack) {
00168 if (n.next && !n.next->empty())
00169 return &n.next->back();
00170 if (n.next)
00171 delChunk(n.next);
00172 n.next = popChunk();
00173 if (n.next && !n.next->empty())
00174 return &n.next->back();
00175 return NULL;
00176 } else {
00177 if (n.cur && !n.cur->empty())
00178 return &n.cur->front();
00179 if (n.cur)
00180 delChunk(n.cur);
00181 n.cur = popChunk();
00182 if (!n.cur) {
00183 n.cur = n.next;
00184 n.next = 0;
00185 }
00186 if (n.cur && !n.cur->empty())
00187 return &n.cur->front();
00188 return NULL;
00189 }
00190 }
00191
00197 void pop_peeked() {
00198 p& n = data.get();
00199 if (IsStack) {
00200 n.next->pop_back();
00201 return;
00202 } else {
00203 n.cur->pop_front();
00204 return;
00205 }
00206 }
00207
00208 void push(const value_type& val) {
00209 p& n = data.get();
00210 emplacei(n, val);
00211 }
00212
00213 template<typename Iter>
00214 void push(Iter b, Iter e) {
00215 p& n = data.get();
00216 while (b != e)
00217 emplacei(n, *b++);
00218 }
00219
00220 template<typename RangeTy>
00221 void push_initial(const RangeTy& range) {
00222 auto rp = range.local_pair();
00223 push(rp.first, rp.second);
00224 }
00225
00226 Galois::optional<value_type> pop() {
00227 p& n = data.get();
00228 Galois::optional<value_type> retval;
00229 if (IsStack) {
00230 if (n.next && (retval = n.next->extract_back()))
00231 return retval;
00232 if (n.next)
00233 delChunk(n.next);
00234 n.next = popChunk();
00235 if (n.next)
00236 return n.next->extract_back();
00237 return Galois::optional<value_type>();
00238 } else {
00239 if (n.cur && (retval = n.cur->extract_front()))
00240 return retval;
00241 if (n.cur)
00242 delChunk(n.cur);
00243 n.cur = popChunk();
00244 if (!n.cur) {
00245 n.cur = n.next;
00246 n.next = 0;
00247 }
00248 if (n.cur)
00249 return n.cur->extract_front();
00250 return Galois::optional<value_type>();
00251 }
00252 }
00253 };
00254
00260 template<int ChunkSize=64, typename T = int, bool Concurrent=true>
00261 class ChunkedFIFO : public ChunkedMaster<T, ConExtLinkedQueue, false, false, ChunkSize, Concurrent> {};
00262 GALOIS_WLCOMPILECHECK(ChunkedFIFO)
00263
00264
00269 template<int ChunkSize=64, typename T = int, bool Concurrent=true>
00270 class ChunkedLIFO : public ChunkedMaster<T, ConExtLinkedStack, false, true, ChunkSize, Concurrent> {};
00271 GALOIS_WLCOMPILECHECK(ChunkedLIFO)
00272
00273
00278 template<int ChunkSize=64, typename T = int, bool Concurrent=true>
00279 class dChunkedFIFO : public ChunkedMaster<T, ConExtLinkedQueue, true, false, ChunkSize, Concurrent> {};
00280 GALOIS_WLCOMPILECHECK(dChunkedFIFO)
00281
00282
00287 template<int ChunkSize=64, typename T = int, bool Concurrent=true>
00288 class dChunkedLIFO : public ChunkedMaster<T, ConExtLinkedStack, true, true, ChunkSize, Concurrent> {};
00289 GALOIS_WLCOMPILECHECK(dChunkedLIFO)
00290
00291
00297 template<int ChunkSize=64, typename T = int, bool Concurrent=true>
00298 class dChunkedBag : public ChunkedMaster<T, ConExtLinkedQueue, true, true, ChunkSize, Concurrent> {};
00299 GALOIS_WLCOMPILECHECK(dChunkedBag)
00300
00301
00302 }
00303 }
00304
00305 #endif