Generated on Wed Nov 1 15:04:49 2006 for Gecode by doxygen 1.4.5

static-pqueue.hh

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Christian Schulte <schulte@gecode.org>
00004  *     Guido Tack <tack@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2002
00008  *     Guido Tack, 2004
00009  *
00010  *  Last modified:
00011  *     $Date: 2006-08-04 16:05:34 +0200 (Fri, 04 Aug 2006) $ by $Author: schulte $
00012  *     $Revision: 3514 $
00013  *
00014  *  This file is part of Gecode, the generic constraint
00015  *  development environment:
00016  *     http://www.gecode.org
00017  *
00018  *  See the file "LICENSE" for information on usage and
00019  *  redistribution of this file, and for a
00020  *     DISCLAIMER OF ALL WARRANTIES.
00021  *
00022  */
00023 
00024 #ifndef __GECODE_SUPPORT_PQUEUE_HH__
00025 #define __GECODE_SUPPORT_PQUEUE_HH__
00026 
00027 #include "gecode/kernel.hh"
00028 
00029 #include <cassert>
00030 #include <algorithm>
00031 
00032 /*
00033  * The shared queue
00034  *
00035  */
00036 
00037 namespace Gecode { namespace Support {
00038 
00050   template <class T, class Less>
00051   class PQueue  {
00052   private:
00054     class SharedPQueue  {
00055     public:
00057       int n;
00059       int size;
00061       unsigned int ref;
00063       Less l;
00065       T pq[1];
00066 
00068       static SharedPQueue* allocate(int n, const Less& l);
00070       void fixdown(void);
00072       void fixup(int n);
00073     };
00075     SharedPQueue* spq;
00076 
00077   public:
00079     PQueue(void);
00081     PQueue(int n, const Less& l);
00083     void init(int, const Less&);
00085     PQueue(const PQueue& p);
00087     const PQueue& operator=(const PQueue&);
00089     ~PQueue(void);
00090 
00092     bool empty(void) const;
00094     void insert(const T& x);
00096     void remove(void);
00098     T& top(void);
00100     void fix(void);
00101 
00103     void update(const PQueue<T,Less>& p, bool share);
00104   };
00105 
00106   template <class T, class Less>
00107   forceinline typename PQueue<T,Less>::SharedPQueue*
00108   PQueue<T,Less>::SharedPQueue::allocate(int n, const Less& l) {
00109     SharedPQueue* spq
00110       = reinterpret_cast<SharedPQueue*>
00111       (Memory::malloc(sizeof(SharedPQueue) + (n-1)*sizeof(T)));
00112     spq->size = n;
00113     spq->n    = 0;
00114     spq->ref  = 1;
00115     spq->l    = l;
00116     return spq;
00117   }
00118 
00119   template <class T, class Less>
00120   forceinline void
00121   PQueue<T,Less>::SharedPQueue::fixdown(void) {
00122     int k = 0;
00123     while ((k << 1) < n) {
00124       int j = k << 1;
00125       if (j < n-1 && l(pq[j],pq[j+1]))
00126         j++;
00127       if (!l(pq[k],pq[j]))
00128         break;
00129       std::swap(pq[k], pq[j]);
00130       k = j;
00131     }
00132   }
00133 
00134   template <class T, class Less>
00135   forceinline void
00136   PQueue<T,Less>::SharedPQueue::fixup(int k) {
00137     while (k > 0 && l(pq[k >> 1],pq[k])) {
00138       std::swap(pq[k],pq[k >> 1]);
00139       k >>= 1;
00140     }
00141   }
00142 
00143   template <class T, class Less>
00144   forceinline
00145   PQueue<T,Less>::PQueue(void)
00146     : spq(NULL) {}
00147 
00148   template <class T, class Less>
00149   forceinline
00150   PQueue<T,Less>::PQueue(int n, const Less& l)
00151     : spq(SharedPQueue::allocate(n,l)) {}
00152 
00153   template <class T, class Less>
00154   forceinline void
00155   PQueue<T,Less>::init(int n, const Less& l) {
00156     spq = SharedPQueue::allocate(n,l);
00157   }
00158 
00159   template <class T, class Less>
00160   forceinline
00161   PQueue<T,Less>::PQueue(const PQueue<T,Less>& p)
00162     : spq(p.spq) {
00163     if (spq != NULL)
00164       spq->ref++;
00165   }
00166 
00167   template <class T, class Less>
00168   forceinline const PQueue<T,Less>&
00169   PQueue<T,Less>::operator =(const PQueue<T,Less>& p) {
00170     if (this != &p) {
00171       if ((spq != NULL) && (--spq->ref == 0))
00172         Memory::free(spq);
00173       spq = p.spq;
00174       if (spq != NULL)
00175         spq->ref++;
00176     }
00177     return *this;
00178   }
00179 
00180   template <class T, class Less>
00181   forceinline void
00182   PQueue<T,Less>::update(const PQueue<T,Less>& p, bool share) {
00183     if (share) {
00184       spq = p.spq;
00185       if (spq != NULL)
00186         spq->ref++;
00187     } else {
00188       if (p.spq != NULL) {
00189         spq = allocate(p.spq->n,p.spq->l);
00190       } else {
00191         spq = NULL;
00192       }
00193     }
00194   }
00195 
00196   template <class T, class Less>
00197   forceinline
00198   PQueue<T,Less>::~PQueue(void) {
00199     if ((spq != NULL) && (--spq->ref == 0))
00200       Memory::free(spq);
00201   }
00202 
00203   template <class T, class Less>
00204   forceinline bool
00205   PQueue<T,Less>::empty(void) const {
00206     return (spq == NULL) || (spq->n == 0);
00207   }
00208 
00209 
00210   template <class T, class Less>
00211   forceinline void
00212   PQueue<T,Less>::insert(const T& x) {
00213     spq->pq[spq->n++] = x;
00214     spq->fixup(spq->n-1);
00215   }
00216 
00217   template <class T, class Less>
00218   forceinline void
00219   PQueue<T,Less>::remove(void) {
00220     spq->pq[0] = spq->pq[--spq->n];
00221     spq->fixdown();
00222   }
00223 
00224   template <class T, class Less>
00225   forceinline T&
00226   PQueue<T,Less>::top(void) {
00227     return spq->pq[0];
00228   }
00229 
00230   template <class T, class Less>
00231   forceinline void
00232   PQueue<T,Less>::fix(void) {
00233     spq->fixdown();
00234   }
00235 
00236 }}
00237 
00238 #endif
00239 
00240 // STATISTICS: support-any