00001
00023 #ifndef GALOIS_RUNTIME_WORKLISTHELPERS_H
00024 #define GALOIS_RUNTIME_WORKLISTHELPERS_H
00025
00026 namespace GaloisRuntime {
00027 namespace WorkList {
00028
00029 template<typename T, unsigned chunksize = 64, bool concurrent = true>
00030 class FixedSizeRing :private boost::noncopyable, private PaddedLock<concurrent> {
00031 using PaddedLock<concurrent>::lock;
00032 using PaddedLock<concurrent>::unlock;
00033 unsigned start;
00034 unsigned end;
00035 T data[chunksize];
00036
00037 bool _i_empty() const {
00038 return start == end;
00039 }
00040
00041 bool _i_full() const {
00042 return (end + 1) % chunksize == start;
00043 }
00044
00045 inline void assertSE() const {
00046 assert(start <= chunksize);
00047 assert(end <= chunksize);
00048 }
00049
00050 public:
00051
00052 template<bool newconcurrent>
00053 struct rethread {
00054 typedef FixedSizeRing<T, chunksize, newconcurrent> WL;
00055 };
00056
00057 typedef T value_type;
00058
00059 FixedSizeRing() :start(0), end(0) { assertSE(); }
00060
00061 bool empty() const {
00062 lock();
00063 assertSE();
00064 bool retval = _i_empty();
00065 assertSE();
00066 unlock();
00067 return retval;
00068 }
00069
00070 bool full() const {
00071 lock();
00072 assertSE();
00073 bool retval = _i_full();
00074 assertSE();
00075 unlock();
00076 return retval;
00077 }
00078
00079 bool push_front(value_type val) {
00080 lock();
00081 assertSE();
00082 if (_i_full()) {
00083 unlock();
00084 return false;
00085 }
00086 start += chunksize - 1;
00087 start %= chunksize;
00088 data[start] = val;
00089 assertSE();
00090 unlock();
00091 return true;
00092 }
00093
00094 bool push_back(value_type val) {
00095 lock();
00096 assertSE();
00097 if (_i_full()) {
00098 unlock();
00099 return false;
00100 }
00101 data[end] = val;
00102 end += 1;
00103 end %= chunksize;
00104 assertSE();
00105 unlock();
00106 return true;
00107 }
00108
00109 std::pair<bool, value_type> pop_front() {
00110 lock();
00111 assertSE();
00112 if (_i_empty()) {
00113 unlock();
00114 return std::make_pair(false, value_type());
00115 }
00116 value_type retval = data[start];
00117 ++start;
00118 start %= chunksize;
00119 assertSE();
00120 unlock();
00121 return std::make_pair(true, retval);
00122 }
00123
00124 std::pair<bool, value_type> pop_back() {
00125 lock();
00126 assertSE();
00127 if (_i_empty()) {
00128 unlock();
00129 return std::make_pair(false, value_type());
00130 }
00131 end += chunksize - 1;
00132 end %= chunksize;
00133 value_type retval = data[end];
00134 assertSE();
00135 unlock();
00136 return std::make_pair(true, retval);
00137 }
00138 };
00139
00140 template<typename T, bool concurrent>
00141 class ConExtLinkedStack {
00142 PtrLock<T*, concurrent> head;
00143
00144 public:
00145
00146 class ListNode {
00147 T* NextPtr;
00148 public:
00149 ListNode() :NextPtr(0) {}
00150 T*& getNextPtr() { return NextPtr; }
00151 };
00152
00153 bool empty() const {
00154 return !head.getValue();
00155 }
00156
00157 void push(T* C) {
00158 T* oldhead(0);
00159 do {
00160 oldhead = head.getValue();
00161 C->getNextPtr() = oldhead;
00162 } while (!head.CAS(oldhead, C));
00163 }
00164
00165 T* pop() {
00166
00167 if (empty()) return 0;
00168
00169
00170 head.lock();
00171 T* C = head.getValue();
00172 if (!C) {
00173 head.unlock();
00174 return 0;
00175 }
00176 head.unlock_and_set(C->getNextPtr());
00177 C->getNextPtr() = 0;
00178 return C;
00179 }
00180 };
00181
00182
00183 template<typename T, bool concurrent>
00184 class ConExtLinkedQueue {
00185
00186 PtrLock<T*,concurrent> head;
00187 T* tail;
00188
00189 public:
00190 class ListNode {
00191 T* NextPtr;
00192 public:
00193 ListNode() :NextPtr(0) {}
00194 T*& getNextPtr() { return NextPtr; }
00195 };
00196
00197 ConExtLinkedQueue() :tail(0) { }
00198
00199 bool empty() const {
00200 return !tail;
00201 }
00202
00203 void push(T* C) {
00204 head.lock();
00205
00206 C->getNextPtr() = 0;
00207 if (tail) {
00208 tail->getNextPtr() = C;
00209 tail = C;
00210 head.unlock();
00211 } else {
00212 assert(!head.getValue());
00213 tail = C;
00214 head.unlock_and_set(C);
00215 }
00216 }
00217
00218 T* pop() {
00219
00220 if (empty()) return 0;
00221
00222 head.lock();
00223 T* C = head.getValue();
00224 if (!C) {
00225 head.unlock();
00226 return 0;
00227 }
00228 if (tail == C) {
00229 tail = 0;
00230 assert(!C->getNextPtr());
00231 head.unlock_and_clear();
00232 } else {
00233 head.unlock_and_set(C->getNextPtr());
00234 C->getNextPtr() = 0;
00235 }
00236 return C;
00237 }
00238 };
00239
00240 class DummyPartitioner {
00241 unsigned getNum() const {
00242 return 1;
00243 }
00244 template<typename T>
00245 unsigned operator()(T& item) { return 0; }
00246 };
00247
00248 class DummyIndexer {
00249 public:
00250 template<typename T>
00251 unsigned operator()(const T& x) { return 0; }
00252 };
00253
00254
00255 }
00256 }
00257
00258
00259 #endif