Generated on Tue Apr 18 10:22:06 2017 for Gecode by doxygen 1.6.3

gpi.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: 2017-04-01 20:27:10 +0200 (Sat, 01 Apr 2017) $ by $Author: schulte $
00011  *     $Revision: 15623 $
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 GPI {
00044   public:
00046     class Info {
00047     public:
00049       unsigned int pid;
00051       unsigned int gid;
00053       double afc;
00055       void init(unsigned int pid, unsigned int gid);
00056     };
00057   private:
00059     class Block : public HeapAllocated {
00060     public:
00062       static const int n_info = 8192;
00064       Info info[n_info];
00066       Block* next;
00068       int free;
00070       Block(void);
00072       void rescale(void);
00073     };
00075     class Object : public HeapAllocated {
00076     private:
00078       Block fst;
00080       Block* b;
00082       Support::Mutex m;
00084       double invd;
00086       unsigned int pid;
00088       unsigned int use_cnt;
00089     public:
00091       Object(void);
00093       void inc(void);
00095       void decay(double d);
00097       double decay(void) const;
00099       void fail(Info& c);
00101       Info* allocate(unsigned int gid);
00103       void dispose(void);
00104     };
00106     Object* o;
00107   public:
00109     GPI(void);
00111     GPI(const GPI& ga);
00113     ~GPI(void);
00115     void decay(double d);
00117     double decay(void) const;
00119     void fail(Info& c);
00121     Info* allocate(unsigned int gid);
00122   };
00123 
00124 
00125   forceinline void
00126   GPI::Info::init(unsigned int pid0, unsigned int gid0) {
00127     pid=pid0; gid=gid0; afc=1.0;
00128   }
00129 
00130 
00131   forceinline
00132   GPI::Block::Block(void)
00133     : next(NULL), free(n_info) {}
00134 
00135   forceinline void
00136   GPI::Block::rescale(void) {
00137     for (int i=free; i < n_info; i++)
00138       info[i].afc *= Kernel::Config::rescale;
00139   }
00140 
00141 
00142   forceinline
00143   GPI::Object::Object(void)
00144     : b(&fst), invd(1.0), pid(0U), use_cnt(1U) {}
00145 
00146   forceinline void
00147   GPI::Object::inc(void) {
00148     m.acquire();
00149     use_cnt++;
00150     m.release();
00151   }
00152 
00153   forceinline void
00154   GPI::Object::fail(Info& c) {
00155     m.acquire();
00156     c.afc = invd * (c.afc + 1.0);
00157     if (c.afc > Kernel::Config::rescale_limit)
00158       for (Block* i = b; i != NULL; i = i->next)
00159         i->rescale();
00160     m.release();
00161   }
00162 
00163   forceinline double
00164   GPI::Object::decay(void) const {
00165     double d;
00166     const_cast<GPI::Object&>(*this).m.acquire();
00167     d = 1.0 / invd;
00168     const_cast<GPI::Object&>(*this).m.release();
00169     return d;
00170   }
00171 
00172   forceinline void
00173   GPI::Object::decay(double d) {
00174     m.acquire();
00175     invd = 1.0 / d;
00176     m.release();
00177   }
00178 
00179   forceinline GPI::Info*
00180   GPI::Object::allocate(unsigned int gid) {
00181     Info* c;
00182     m.acquire();
00183     if (b->free == 0) {
00184       Block* n = new Block;
00185       n->next = b; b = n;
00186     }
00187     c = &b->info[--b->free];
00188     m.release();
00189     c->init(pid++,gid);
00190     return c;
00191   }
00192 
00193   forceinline void
00194   GPI::Object::dispose(void) {
00195     m.acquire();
00196     if (--use_cnt > 0) {
00197       m.release();
00198       return;
00199     }
00200     // We are on our own here!
00201     m.release();
00202     Block* n = b;
00203     while (n != &fst) {
00204       Block* d = n;
00205       n = n->next;
00206       delete d;
00207     }
00208     delete this;
00209   }
00210 
00211 
00212 
00213   forceinline
00214   GPI::GPI(void) : o(new Object) {}
00215 
00216   forceinline
00217   GPI::GPI(const GPI& gpi) : o(gpi.o) {
00218     o->inc();
00219   }
00220 
00221   forceinline
00222   GPI::~GPI(void) {
00223     o->dispose();
00224   }
00225 
00226   forceinline void
00227   GPI::fail(Info& c) {
00228     o->fail(c);
00229   }
00230 
00231   forceinline double
00232   GPI::decay(void) const {
00233     return o->decay();
00234   }
00235 
00236   forceinline void
00237   GPI::decay(double d) {
00238     o->decay(d);
00239   }
00240 
00241   forceinline GPI::Info*
00242   GPI::allocate(unsigned int gid) {
00243     return o->allocate(gid);
00244   }
00245 
00246 }
00247 
00248 // STATISTICS: kernel-prop