BWAPI
|
00001 #pragma once 00002 #include <list> 00003 #include <cassert> 00004 00005 template <class T> class ConstSafeListAdaptor; 00006 template <class T> class SafeListAdaptor; 00007 00012 class SafeListBase 00013 { 00014 public: 00015 struct ConstFunctionReturn 00016 { 00017 ConstFunctionReturn() 00018 : breakIteration(false) {} 00019 ConstFunctionReturn(bool _breakIteration) 00020 : breakIteration(_breakIteration) {} 00021 bool breakIteration; 00022 }; 00023 00024 struct FunctionReturn : ConstFunctionReturn 00025 { 00026 FunctionReturn() 00027 : ConstFunctionReturn(), deleteCurrent(false) {} 00028 FunctionReturn(bool _deleteCurrent, bool _breakIteration) 00029 : ConstFunctionReturn(_breakIteration), deleteCurrent(_deleteCurrent) {} 00030 FunctionReturn(ConstFunctionReturn r) 00031 : ConstFunctionReturn(r), deleteCurrent(false) {} 00032 bool deleteCurrent; 00033 }; 00034 }; 00035 00044 template <class T> 00045 class SafeList : public SafeListBase 00046 { 00047 protected: 00048 friend class ConstSafeListAdaptor<T>; 00049 friend class SafeListAdaptor<T>; 00054 class Wrapper 00055 { 00056 public: 00057 Wrapper(T t) 00058 : m_t(t), m_deleted(false) {} 00062 bool isDeleted() const { return m_deleted; } 00063 operator T&() { return m_t; } 00064 operator const T&() const { return m_t; } 00065 bool operator==(const Wrapper& other) const { return m_t == other.m_t; } 00066 bool operator!=(const Wrapper& other) const { return m_t != other.m_t; } 00067 protected: 00068 friend class SafeList; 00072 T m_t; 00076 mutable bool m_deleted; 00077 }; 00078 00079 public: 00080 typedef typename std::list<Wrapper>::iterator iterator; 00081 typedef typename std::list<Wrapper>::const_iterator const_iterator; 00082 00086 SafeList() 00087 : m_size(0) 00088 , m_nbCurrentIterations(0) 00089 { 00090 } 00091 00092 SafeList(const SafeList& other) 00093 : m_size(0) 00094 , m_nbCurrentIterations(0) 00095 { 00096 for (std::list<Wrapper>::const_iterator it = other.m_list.begin(); it != other.m_list.end(); ++it) 00097 { 00098 if (!it->isDeleted()) 00099 add(*it); 00100 } 00101 } 00102 00108 iterator add(const T& t) 00109 { 00110 ++m_size; 00111 return m_list.insert(m_list.end(), t); 00112 } 00113 00122 template <class Function> 00123 Function do_while(Function function) 00124 { 00125 Iteration iteration(*this); 00126 00127 bool breakIteration = false; 00128 for (std::list<Wrapper>::iterator it = m_list.begin(); !breakIteration && it != m_list.end(); ++it) 00129 { 00130 if (!(*it).m_deleted) 00131 { 00132 FunctionReturn result = function((*it).m_t); 00133 if (result.deleteCurrent) 00134 { 00135 (*it).m_deleted = true; 00136 --m_size; 00137 } 00138 breakIteration = result.breakIteration; 00139 } 00140 } 00141 00142 return function; 00143 } 00144 00152 template <class Function> 00153 Function do_while(Function function) const 00154 { 00155 Iteration iteration(*this); 00156 00157 bool breakIteration = false; 00158 for (std::list<Wrapper>::const_iterator it = m_list.begin(); !breakIteration && it != m_list.end(); ++it) 00159 { 00160 if (!(*it).m_deleted) 00161 { 00162 ConstFunctionReturn result = function((*it).m_t); 00163 breakIteration = result.breakIteration; 00164 } 00165 } 00166 00167 return function; 00168 } 00169 00178 template <class Function> 00179 Function for_each(Function function) 00180 { 00181 Iteration iteration(*this); 00182 00183 if (!m_list.empty()) 00184 { 00185 std::list<Wrapper>::iterator stop = m_list.end(); 00186 --stop; 00187 std::list<Wrapper>::iterator it = m_list.begin(); 00188 bool breakIteration = false; 00189 do 00190 { 00191 if (!(*it).m_deleted) 00192 { 00193 FunctionReturn result = function((*it).m_t); 00194 if (result.deleteCurrent) 00195 { 00196 (*it).m_deleted = true; 00197 --m_size; 00198 } 00199 breakIteration = result.breakIteration; 00200 } 00201 } while (!breakIteration && it++ != stop); 00202 } 00203 00204 return function; 00205 } 00206 00214 template <class Function> 00215 Function for_each(Function function) const 00216 { 00217 Iteration iteration(*this); 00218 00219 if (!m_list.empty()) 00220 { 00221 std::list<Wrapper>::const_iterator stop = m_list.end(); 00222 --stop; 00223 std::list<Wrapper>::const_iterator it = m_list.begin(); 00224 bool breakIteration = false; 00225 do 00226 { 00227 if (!(*it).m_deleted) 00228 { 00229 ConstFunctionReturn result = function((*it).m_t); 00230 breakIteration = result.breakIteration; 00231 } 00232 } while (!breakIteration && it++ != stop); 00233 } 00234 00235 return function; 00236 } 00237 00242 void erase(iterator position) 00243 { 00244 assert(!(*position).m_deleted); 00245 (*position).m_deleted = true; 00246 --m_size; 00247 if (m_nbCurrentIterations == 0) 00248 { 00249 m_list.erase(position); 00250 } 00251 } 00252 00256 size_t size() const 00257 { 00258 assert(m_nbCurrentIterations != 0 || m_size == m_list.size()); // m_list includes deleted elements if m_nbCurrentIterations > 0 00259 return m_size; 00260 } 00261 00265 bool empty() const 00266 { 00267 return size() == 0; 00268 } 00269 00270 protected: 00271 SafeList& operator=(const SafeList& other) const; 00272 00276 class Iteration 00277 { 00278 public: 00279 Iteration(const SafeList& safeList) 00280 : m_safeList(safeList) 00281 { 00282 m_safeList.iterationStarted(*this); 00283 } 00284 ~Iteration() 00285 { 00286 m_safeList.iterationEnded(*this); 00287 } 00288 private: 00289 Iteration(const Iteration&); 00290 Iteration& operator=(const Iteration&); 00291 00292 const SafeList& m_safeList; 00293 }; 00294 friend class Iteration; 00295 00301 void iterationStarted(Iteration& iteration) const 00302 { 00303 unused(iteration); 00304 00305 ++m_nbCurrentIterations; 00306 } 00307 00314 void iterationEnded(Iteration& iteration) const 00315 { 00316 unused(iteration); 00317 00318 if (--m_nbCurrentIterations == 0) 00319 { 00320 std::list<Wrapper>::iterator it = m_list.begin(); 00321 while (it != m_list.end()) 00322 { 00323 std::list<Wrapper>::iterator next = it; 00324 ++next; 00325 if ((*it).m_deleted) 00326 { 00327 m_list.erase(it); 00328 } 00329 it = next; 00330 } 00331 } 00332 } 00333 00338 mutable std::list<Wrapper> m_list; 00342 mutable size_t m_nbCurrentIterations; 00348 size_t m_size; 00349 };