Generated on Fri Mar 20 15:56:17 2015 for Gecode by doxygen 1.6.3

global-afc.hpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2009
00008  *
00009  *  Last modified:
00010  *     $Date: 2013-07-01 06:38:48 +0200 (Mon, 01 Jul 2013) $ by $Author: tack $
00011  *     $Revision: 13740 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 #include <cmath>
00039 
00040 namespace Gecode {
00041 
00043   class GlobalAFC {
00044   public:
00046     class Counter {
00047     public:
00049       double c;
00051       unsigned long int t;
00053       void init(void);
00054     };
00055   private:
00057     class Block {
00058     public:
00060       Block* next;
00062       Counter c[1];
00064       static Block* allocate(unsigned int n, Block* p=NULL);
00065     };
00067     class DecayManager {
00068     protected:
00070       double d;
00072       static const unsigned int n_dpow = 8U;
00074       double dpow[n_dpow];
00076       unsigned long int t;
00078       void decay(Counter& c);
00079     public:
00081       DecayManager(void);
00083       void decay(double d);
00085       double decay(void) const;
00087       void inc(Counter& c);
00089       void set(Counter& c, double a);
00091       double val(Counter& c);
00093       static void* operator new(size_t s);
00095       static void  operator delete(void* p);
00096     };
00098     static const unsigned int size_min = 32;
00100     static const unsigned int size_max = 32 * 1024;
00102     class Object {
00103     public:
00105       Support::FastMutex* mutex;
00107       DecayManager* decay;
00109       Object* parent;
00111       unsigned int use_cnt;
00113       unsigned int size;
00115       unsigned int free;
00117       Block* cur;
00119       Object(Support::FastMutex* m, Object* p=NULL);
00121       static void* operator new(size_t s);
00123       static void  operator delete(void* p);
00124     };
00126     void* mo;
00128     Object* object(void) const;
00130     bool local(void) const;
00132     void local(Object* o);
00134     void global(void* mo);
00135   public:
00137     GlobalAFC(void);
00139     GlobalAFC(const GlobalAFC& ga);
00141     ~GlobalAFC(void);
00143     void decay(double d);
00145     double decay(void) const;
00147     void fail(Counter& c);
00149     void set(Counter& c, double a);
00151     double afc(Counter& c);
00153     Counter& allocate(void);
00154   };
00155 
00156 
00157 
00158   forceinline void
00159   GlobalAFC::Counter::init(void) {
00160     c=1.0; t=0UL;
00161   }
00162 
00163   forceinline void
00164   GlobalAFC::DecayManager::decay(double d0) {
00165     d = d0;
00166     if (d != 1.0) {
00167       double p = d;
00168       unsigned int i=0;
00169       do {
00170         dpow[i++]=p; p*=d;
00171       } while (i<n_dpow);
00172     }
00173   }
00174   forceinline
00175   GlobalAFC::DecayManager::DecayManager(void)
00176     : d(1.0), t(0UL) {}
00177 
00178   forceinline double
00179   GlobalAFC::DecayManager::decay(void) const {
00180     return d;
00181   }
00182   forceinline void
00183   GlobalAFC::DecayManager::decay(Counter& c) {
00184     assert((t >= c.t) && (d != 1.0));
00185     unsigned int n = t - c.t;
00186     if (n > 0) {
00187       if (n <= n_dpow) {
00188         c.c *= dpow[n-1];
00189       } else {
00190         c.c *= pow(d,static_cast<double>(n));
00191       }
00192       c.t = t;
00193     }
00194   }
00195   forceinline void
00196   GlobalAFC::DecayManager::inc(Counter& c) {
00197     if (d == 1.0) {
00198       c.c += 1.0;
00199     } else {
00200       decay(c);
00201       c.c += 1.0; c.t = ++t;
00202     }
00203   }
00204   forceinline double
00205   GlobalAFC::DecayManager::val(Counter& c) {
00206     if (d != 1.0)
00207       decay(c);
00208     return c.c;
00209   }
00210   forceinline void
00211   GlobalAFC::DecayManager::set(Counter& c, double a) {
00212     c.c = a;
00213   }
00214   forceinline void*
00215   GlobalAFC::DecayManager::operator new(size_t s) {
00216     return Gecode::heap.ralloc(s);
00217   }
00218   forceinline void
00219   GlobalAFC::DecayManager::operator delete(void* p) {
00220     Gecode::heap.rfree(p);
00221   }
00222 
00223 
00224   /*
00225    * Global AFC information
00226    *
00227    */
00228 
00229   forceinline void*
00230   GlobalAFC::Object::operator new(size_t s) {
00231     return Gecode::heap.ralloc(s);
00232   }
00233 
00234   forceinline void
00235   GlobalAFC::Object::operator delete(void* p) {
00236     Gecode::heap.rfree(p);
00237   }
00238 
00239   forceinline GlobalAFC::Block*
00240   GlobalAFC::Block::allocate(unsigned int n, GlobalAFC::Block* p) {
00241     Block* b = static_cast<Block*>(heap.ralloc(sizeof(Block)+
00242                                                (n-1)*sizeof(Counter)));
00243     b->next = p;
00244     return b;
00245   }
00246 
00247   forceinline
00248   GlobalAFC::Object::Object(Support::FastMutex* m, Object* p)
00249     : mutex(m), parent(p), use_cnt(1), size(size_min), free(size_min),
00250       cur(Block::allocate(size)) {
00251     if (parent == NULL) {
00252       decay = new DecayManager;
00253     } else {
00254       decay = parent->decay;
00255     }
00256   }
00257 
00258   forceinline GlobalAFC::Object*
00259   GlobalAFC::object(void) const {
00260     return static_cast<Object*>(Support::funmark(mo));
00261   }
00262   forceinline bool
00263   GlobalAFC::local(void) const {
00264     return !Support::marked(mo);
00265   }
00266   forceinline void
00267   GlobalAFC::local(Object* o) {
00268     assert(!Support::marked(o));
00269     mo = o;
00270   }
00271   forceinline void
00272   GlobalAFC::global(void* o) {
00273     mo = Support::fmark(o);
00274   }
00275 
00276   forceinline
00277   GlobalAFC::GlobalAFC(void) {
00278     // No synchronization needed as single thread is creating this object
00279     local(new Object(new Support::FastMutex));
00280   }
00281 
00282   forceinline
00283   GlobalAFC::GlobalAFC(const GlobalAFC& gpi) {
00284     global(gpi.mo);
00285     Object* o = object();
00286     o->mutex->acquire();
00287     o->use_cnt++;
00288     o->mutex->release();
00289   }
00290 
00291   forceinline
00292   GlobalAFC::~GlobalAFC(void) {
00293     Support::FastMutex* m = object()->mutex;
00294     m->acquire();
00295     Object* c = object();
00296     DecayManager* decay = c->decay;
00297     while ((c != NULL) && (--c->use_cnt == 0)) {
00298       // Delete all blocks for c
00299       Block* b = c->cur;
00300       while (b != NULL) {
00301         Block* d = b; b=b->next;
00302         heap.rfree(d);
00303       }
00304       // Delete object
00305       Object* d = c; c = c->parent;
00306       delete d; 
00307     }
00308     m->release();
00309     // All objects are deleted, so also delete mutex and decya info
00310     if (c == NULL) {
00311       delete decay;
00312       delete m;
00313     }
00314   }
00315 
00316   forceinline void
00317   GlobalAFC::fail(Counter& c) {
00318     Support::FastMutex& m = *object()->mutex;
00319     m.acquire();
00320     object()->decay->inc(c);
00321     m.release();
00322   }
00323 
00324   forceinline void
00325   GlobalAFC::set(Counter& c, double a) {
00326     Support::FastMutex& m = *object()->mutex;
00327     m.acquire();
00328     object()->decay->set(c,a);
00329     m.release();
00330   }
00331 
00332   forceinline double
00333   GlobalAFC::afc(Counter& c) {
00334     Support::FastMutex& m = *object()->mutex;
00335     double d;
00336     m.acquire();
00337     d = object()->decay->val(c);
00338     m.release();
00339     return d;
00340   }
00341 
00342   forceinline double
00343   GlobalAFC::decay(void) const {
00344     Support::FastMutex& m = *object()->mutex;
00345     double d;
00346     m.acquire();
00347     d = object()->decay->decay();
00348     m.release();
00349     return d;
00350   }
00351 
00352   forceinline void
00353   GlobalAFC::decay(double d) {
00354     Support::FastMutex& m = *object()->mutex;
00355     m.acquire();
00356     object()->decay->decay(d);
00357     m.release();
00358   }
00359 
00360   forceinline GlobalAFC::Counter&
00361   GlobalAFC::allocate(void) {
00362     /*
00363      * If there is no local object, create one.
00364      *
00365      * There is no synchronization needed as only ONE space has access
00366      * to the marked pointer AND the local object.
00367      */
00368     if (!local())
00369       local(new Object(object()->mutex,object()));
00370 
00371     assert(local());
00372 
00373     Object* o = object();
00374 
00375     if (o->free == 0) {
00376       if (2*o->size <= size_max)
00377         o->size *= 2;
00378       o->free = o->size;
00379       o->cur  = Block::allocate(o->size,o->cur);
00380     }
00381 
00382     Counter* c = &o->cur->c[--o->free];
00383     c->init();
00384 
00385     return *c;
00386   }
00387 
00388 }
00389 
00390 // STATISTICS: kernel-prop