this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Christian Schulte <schulte@gecode.org> 5 * 6 * Copyright: 7 * Christian Schulte, 2009 8 * 9 * This file is part of Gecode, the generic constraint 10 * development environment: 11 * http://www.gecode.org 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining 14 * a copy of this software and associated documentation files (the 15 * "Software"), to deal in the Software without restriction, including 16 * without limitation the rights to use, copy, modify, merge, publish, 17 * distribute, sublicense, and/or sell copies of the Software, and to 18 * permit persons to whom the Software is furnished to do so, subject to 19 * the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be 22 * included in all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 * 32 */ 33 34#include <cmath> 35 36namespace Gecode { namespace Kernel { 37 38 /// Global propagator information 39 class GPI { 40 public: 41 /// Class for storing propagator information 42 class Info { 43 public: 44 /// Propagator identifier 45 unsigned int pid; 46 /// Group identifier 47 unsigned int gid; 48 /// The afc value 49 double afc; 50 /// Initialize 51 void init(unsigned int pid, unsigned int gid); 52 }; 53 private: 54 /// Block of propagator information 55 class Block : public HeapAllocated { 56 public: 57 /// Number of propagator information entries in a block 58 static const int n_info = 8192; 59 /// Info entries 60 Info info[n_info]; 61 /// Next block 62 Block* next; 63 /// Number of free blocks 64 int free; 65 /// Initialize 66 Block(void); 67 /// Rescale used afc values in entries 68 void rescale(void); 69 }; 70 /// The current block 71 Block* b; 72 /// The inverse decay factor 73 double invd; 74 /// Next free propagator id 75 std::atomic<unsigned int> npid; 76 /// Whether to unshare 77 bool us; 78 /// The first block 79 Block fst; 80 /// Mutex to synchronize globally shared access 81 GECODE_KERNEL_EXPORT static Support::Mutex m; 82 public: 83 /// Initialize 84 GPI(void); 85 /// Set decay factor to \a d 86 void decay(double d); 87 /// Return decay factor 88 double decay(void) const; 89 /// Increment failure count 90 void fail(Info& c); 91 /// Allocate info for existing propagator with pid \a p 92 Info* allocate(unsigned int p, unsigned int gid); 93 /// Allocate new actor info 94 Info* allocate(unsigned int gid); 95 /// Return next free propagator id 96 unsigned int pid(void) const; 97 /// Provide access to unshare info and set to true 98 bool unshare(void); 99 /// Delete 100 ~GPI(void); 101 }; 102 103 104 forceinline void 105 GPI::Info::init(unsigned int pid0, unsigned int gid0) { 106 pid=pid0; gid=gid0; afc=1.0; 107 } 108 109 110 forceinline 111 GPI::Block::Block(void) 112 : next(nullptr), free(n_info) {} 113 114 forceinline void 115 GPI::Block::rescale(void) { 116 for (int i=free; i < n_info; i++) 117 info[i].afc *= Kernel::Config::rescale; 118 } 119 120 121 forceinline 122 GPI::GPI(void) 123 : b(&fst), invd(1.0), npid(0U), us(false) {} 124 125 forceinline void 126 GPI::fail(Info& c) { 127 m.acquire(); 128 c.afc = invd * (c.afc + 1.0); 129 if (c.afc > Kernel::Config::rescale_limit) 130 for (Block* i = b; i != nullptr; i = i->next) 131 i->rescale(); 132 m.release(); 133 } 134 135 forceinline double 136 GPI::decay(void) const { 137 double d; 138 const_cast<GPI&>(*this).m.acquire(); 139 d = 1.0 / invd; 140 const_cast<GPI&>(*this).m.release(); 141 return d; 142 } 143 144 forceinline unsigned int 145 GPI::pid(void) const { 146 return npid.load(std::memory_order_acquire); 147 } 148 149 forceinline bool 150 GPI::unshare(void) { 151 bool u; 152 m.acquire(); 153 u = us; us = true; 154 m.release(); 155 return u; 156 } 157 158 forceinline void 159 GPI::decay(double d) { 160 m.acquire(); 161 invd = 1.0 / d; 162 m.release(); 163 } 164 165 forceinline GPI::Info* 166 GPI::allocate(unsigned int p, unsigned int gid) { 167 Info* c; 168 m.acquire(); 169 if (b->free == 0) { 170 Block* n = new Block; 171 n->next = b; b = n; 172 } 173 c = &b->info[--b->free]; 174 m.release(); 175 c->init(p,gid); 176 return c; 177 } 178 179 forceinline GPI::Info* 180 GPI::allocate(unsigned int gid) { 181 Info* c; 182 m.acquire(); 183 if (b->free == 0) { 184 Block* n = new Block; 185 n->next = b; b = n; 186 } 187 c = &b->info[--b->free]; 188 m.release(); 189 c->init(npid.fetch_add(std::memory_order::memory_order_seq_cst),gid); 190 return c; 191 } 192 193 forceinline 194 GPI::~GPI(void) { 195 Block* n = b; 196 while (n != &fst) { 197 Block* d = n; 198 n = n->next; 199 delete d; 200 } 201 } 202 203}} 204 205// STATISTICS: kernel-prop