BWAPI
|
00001 #pragma once 00002 #include <set> 00003 #include <queue> 00004 #include <cassert> 00005 00010 class SafeMultisetBase 00011 { 00012 public: 00013 struct ConstFunctionReturn 00014 { 00015 ConstFunctionReturn() 00016 : breakIteration(false) {} 00017 ConstFunctionReturn(bool _breakIteration) 00018 : breakIteration(_breakIteration) {} 00019 bool breakIteration; 00020 }; 00021 00022 struct FunctionReturn : ConstFunctionReturn 00023 { 00024 FunctionReturn() 00025 : ConstFunctionReturn(), deleteCurrent(false) {} 00026 FunctionReturn(bool _deleteCurrent, bool _breakIteration) 00027 : ConstFunctionReturn(_breakIteration), deleteCurrent(_deleteCurrent) {} 00028 FunctionReturn(ConstFunctionReturn r) 00029 : ConstFunctionReturn(r), deleteCurrent(false) {} 00030 bool deleteCurrent; 00031 }; 00032 }; 00033 00041 template <class T, class Compare = std::less<T>> 00042 class SafeMultiset : public SafeMultisetBase 00043 { 00044 public: 00049 class Wrapper 00050 { 00051 public: 00052 Wrapper(T t) 00053 : m_t(t), m_deleted(false) {} 00057 bool isDeleted() const { return m_deleted; } 00058 operator T&() { return m_t; } 00059 operator const T&() const { return m_t; } 00060 protected: 00061 friend class SafeMultiset; 00065 T m_t; 00069 bool m_deleted; 00070 }; 00071 00072 protected: 00076 class CompareWrapper 00077 { 00078 public: 00079 CompareWrapper(const Compare& compare) 00080 : m_compare(compare) {} 00081 bool operator()(const Wrapper& wrapper1, const Wrapper& wrapper2) const 00082 { 00083 return m_compare(wrapper1.m_t, wrapper2.m_t); 00084 } 00085 private: 00086 const Compare& m_compare; 00087 }; 00088 00089 public: 00090 typedef typename std::multiset<Wrapper, CompareWrapper>::iterator iterator; 00091 00096 SafeMultiset(const Compare& compare = Compare()) 00097 : m_compare(compare) 00098 , m_multiset(CompareWrapper(m_compare)) 00099 , m_size(0) 00100 , m_first(NULL) 00101 { 00102 } 00103 00104 //iterator insert(iterator position, const T& t) 00105 //{ 00106 // ++m_size; 00107 // iterator it = m_multiset.insert(position, t); 00108 // for (ThresholdPriorityQueue* queue = m_first; queue != NULL; queue = queue->getNext()) 00109 // { 00110 // queue->push(&(*it)); 00111 // } 00112 // return it; 00113 //} 00114 00121 iterator insert(const T& t) 00122 { 00123 ++m_size; 00124 iterator it = m_multiset.insert(t); 00125 for (Iteration* iteration = m_first; iteration != NULL; iteration = iteration->getNext()) 00126 { 00127 iteration->pushNewElement(&(*it)); 00128 } 00129 return it; 00130 } 00131 00141 template <class Function> 00142 Function do_while(Function function) 00143 { 00144 Iteration iteration(*this); 00145 00146 bool breakIteration = false; 00147 for (std::multiset<Wrapper, CompareWrapper>::iterator it = m_multiset.begin(); !breakIteration && it != m_multiset.end(); ++it) 00148 { 00149 Wrapper& current = *it; 00150 if (!current.m_deleted) 00151 { 00152 iteration.setElementsAdditionThreshold(¤t); 00153 FunctionReturn result = function(current); 00154 if (result.deleteCurrent) 00155 { 00156 current.m_deleted = true; 00157 --m_size; 00158 } 00159 bool breakIteration = result.breakIteration; 00160 // Iterate over newly created higher priority elements if any 00161 while (!breakIteration && iteration.hasNewElements()) 00162 { 00163 Wrapper* wrapper = iteration.popNewElement(); 00164 assert(CompareWrapper(m_compare)(*wrapper, current)); 00165 if (!wrapper->m_deleted) 00166 { 00167 FunctionReturn result = function(*wrapper); 00168 if (result.deleteCurrent) 00169 { 00170 wrapper->m_deleted = true; 00171 --m_size; 00172 } 00173 breakIteration = result.breakIteration; 00174 } 00175 } 00176 } 00177 } 00178 return function; 00179 } 00180 00189 template <class Function> 00190 Function do_while(Function function) const 00191 { 00192 Iteration iteration(*this); 00193 00194 bool breakIteration = false; 00195 for (std::multiset<Wrapper, CompareWrapper>::const_iterator it = m_multiset.begin(); !breakIteration && it != m_multiset.end(); ++it) 00196 { 00197 const Wrapper& current = *it; 00198 if (!current.m_deleted) 00199 { 00200 iteration.setElementsAdditionThreshold(¤t); 00201 ConstFunctionReturn result = function(current); 00202 bool breakIteration = result.breakIteration; 00203 // Iterate over newly created higher priority elements if any 00204 while (!breakIteration && iteration.hasNewElements()) 00205 { 00206 Wrapper* wrapper = iteration.popNewElement(); 00207 assert(CompareWrapper(m_compare)(*wrapper, current)); 00208 if (!wrapper->m_deleted) 00209 { 00210 ConstFunctionReturn result = function(*wrapper); 00211 breakIteration = result.breakIteration; 00212 } 00213 } 00214 } 00215 } 00216 return function; 00217 } 00218 00223 void erase(iterator position) 00224 { 00225 assert(!(*position).m_deleted); 00226 (*position).m_deleted = true; 00227 --m_size; 00228 if (m_first == NULL) 00229 { 00230 m_multiset.erase(position); 00231 } 00232 } 00233 00237 size_t size() const 00238 { 00239 assert(m_first != NULL || m_size == m_multiset.size()); 00240 return m_size; 00241 } 00242 00246 bool empty() const 00247 { 00248 return size() == 0; 00249 } 00250 00251 protected: 00252 SafeMultiset(const SafeMultiset& other); 00253 SafeMultiset& operator=(const SafeMultiset& other) const; 00254 00263 class Iteration 00264 { 00265 public: 00266 Iteration(const SafeMultiset& safeMultiset) 00267 : m_safeMultiset(safeMultiset) 00268 , m_compare(safeMultiset.m_compare) 00269 , m_newElements(ComparePtrWrapper(m_compare)) 00270 , m_threshold(NULL) 00271 , m_next(NULL) 00272 { 00273 m_safeMultiset.iterationStarted(*this); 00274 } 00275 ~Iteration() 00276 { 00277 m_safeMultiset.iterationEnded(*this); 00278 } 00282 Iteration* getNext() 00283 { 00284 return m_next; 00285 } 00290 void setNext(Iteration* next) 00291 { 00292 m_next = next; 00293 } 00298 void setElementsAdditionThreshold(const Wrapper* threshold) 00299 { 00300 m_threshold = threshold; 00301 } 00305 bool hasNewElements() const 00306 { 00307 return !m_newElements.empty(); 00308 } 00314 bool pushNewElement(Wrapper* element) 00315 { 00316 assert(m_threshold != NULL); 00317 bool add = m_compare(*element, *m_threshold); // if new >= current, the new element will be inserted after the current one 00318 if (add) 00319 m_newElements.push(element); 00320 return add; 00321 } 00326 Wrapper* popNewElement() 00327 { 00328 Wrapper* element = m_newElements.top(); 00329 m_newElements.pop(); 00330 return element; 00331 } 00332 private: 00333 Iteration(const Iteration&); 00334 Iteration& operator=(const Iteration&); 00335 00336 protected: 00337 class ComparePtrWrapper 00338 { 00339 public: 00343 ComparePtrWrapper(const CompareWrapper& compare) 00344 : m_compare(compare) {} 00345 bool operator()(const Wrapper* wrapper1, const Wrapper* wrapper2) const 00346 { 00347 return !m_compare(*wrapper1, *wrapper2); 00348 } 00349 private: 00350 const CompareWrapper& m_compare; 00351 }; 00352 00356 const SafeMultiset& m_safeMultiset; 00360 const CompareWrapper m_compare; 00365 std::priority_queue<Wrapper*, std::vector<Wrapper*>, ComparePtrWrapper> m_newElements; 00369 const Wrapper* m_threshold; 00373 Iteration* m_next; 00374 }; 00375 friend class Iteration; 00376 00382 void iterationStarted(Iteration& iteration) const 00383 { 00384 iteration.setNext(m_first); 00385 m_first = &iteration; 00386 } 00387 00394 void iterationEnded(Iteration& iteration) const 00395 { 00396 m_first = iteration.getNext(); 00397 if (m_first == NULL) 00398 { 00399 std::multiset<Wrapper, CompareWrapper>::iterator it = m_multiset.begin(); 00400 while (it != m_multiset.end()) 00401 { 00402 std::multiset<Wrapper, CompareWrapper>::iterator next = it; 00403 ++next; 00404 if ((*it).m_deleted) 00405 { 00406 m_multiset.erase(it); 00407 } 00408 it = next; 00409 } 00410 } 00411 } 00412 00416 const Compare m_compare; 00420 mutable std::multiset<Wrapper, CompareWrapper> m_multiset; 00425 mutable Iteration* m_first; 00431 size_t m_size; 00432 };