global-afc.hpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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
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
00299 Block* b = c->cur;
00300 while (b != NULL) {
00301 Block* d = b; b=b->next;
00302 heap.rfree(d);
00303 }
00304
00305 Object* d = c; c = c->parent;
00306 delete d;
00307 }
00308 m->release();
00309
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
00364
00365
00366
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