gpi.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 #include <cmath>
00035
00036 namespace Gecode { namespace Kernel {
00037
00039 class GPI {
00040 public:
00042 class Info {
00043 public:
00045 unsigned int pid;
00047 unsigned int gid;
00049 double afc;
00051 void init(unsigned int pid, unsigned int gid);
00052 };
00053 private:
00055 class Block : public HeapAllocated {
00056 public:
00058 static const int n_info = 8192;
00060 Info info[n_info];
00062 Block* next;
00064 int free;
00066 Block(void);
00068 void rescale(void);
00069 };
00071 Block* b;
00073 double invd;
00075 unsigned int pid;
00077 bool us;
00079 Block fst;
00081 GECODE_KERNEL_EXPORT static Support::Mutex m;
00082 public:
00084 GPI(void);
00086 void decay(double d);
00088 double decay(void) const;
00090 void fail(Info& c);
00092 Info* allocate(unsigned int p, unsigned int gid);
00094 Info* allocate(unsigned int gid);
00096 bool unshare(void);
00098 ~GPI(void);
00099 };
00100
00101
00102 forceinline void
00103 GPI::Info::init(unsigned int pid0, unsigned int gid0) {
00104 pid=pid0; gid=gid0; afc=1.0;
00105 }
00106
00107
00108 forceinline
00109 GPI::Block::Block(void)
00110 : next(NULL), free(n_info) {}
00111
00112 forceinline void
00113 GPI::Block::rescale(void) {
00114 for (int i=free; i < n_info; i++)
00115 info[i].afc *= Kernel::Config::rescale;
00116 }
00117
00118
00119 forceinline
00120 GPI::GPI(void)
00121 : b(&fst), invd(1.0), pid(0U), us(false) {}
00122
00123 forceinline void
00124 GPI::fail(Info& c) {
00125 m.acquire();
00126 c.afc = invd * (c.afc + 1.0);
00127 if (c.afc > Kernel::Config::rescale_limit)
00128 for (Block* i = b; i != NULL; i = i->next)
00129 i->rescale();
00130 m.release();
00131 }
00132
00133 forceinline double
00134 GPI::decay(void) const {
00135 double d;
00136 const_cast<GPI&>(*this).m.acquire();
00137 d = 1.0 / invd;
00138 const_cast<GPI&>(*this).m.release();
00139 return d;
00140 }
00141
00142 forceinline bool
00143 GPI::unshare(void) {
00144 bool u;
00145 m.acquire();
00146 u = us; us = true;
00147 m.release();
00148 return u;
00149 }
00150
00151 forceinline void
00152 GPI::decay(double d) {
00153 m.acquire();
00154 invd = 1.0 / d;
00155 m.release();
00156 }
00157
00158 forceinline GPI::Info*
00159 GPI::allocate(unsigned int p, unsigned int gid) {
00160 Info* c;
00161 m.acquire();
00162 if (b->free == 0) {
00163 Block* n = new Block;
00164 n->next = b; b = n;
00165 }
00166 c = &b->info[--b->free];
00167 m.release();
00168 c->init(p,gid);
00169 return c;
00170 }
00171
00172 forceinline GPI::Info*
00173 GPI::allocate(unsigned int gid) {
00174 Info* c;
00175 m.acquire();
00176 if (b->free == 0) {
00177 Block* n = new Block;
00178 n->next = b; b = n;
00179 }
00180 c = &b->info[--b->free];
00181 c->init(pid++,gid);
00182 m.release();
00183 return c;
00184 }
00185
00186 forceinline
00187 GPI::~GPI(void) {
00188 Block* n = b;
00189 while (n != &fst) {
00190 Block* d = n;
00191 n = n->next;
00192 delete d;
00193 }
00194 }
00195
00196 }}
00197
00198