BWAPI
SPAR/AIModule/SparAIModule/Utils/SafeMultiset.h
Go to the documentation of this file.
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(&current);
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(&current);
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 };
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines