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, 2017 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 namespace Gecode { namespace Search { 35 36 /// Recorder for engine events (for access control) 37 class WrapTraceRecorder { 38 public: 39 /// Register engine 40 static void engine(SearchTracer* tracer, 41 SearchTracer::EngineType t, unsigned int n); 42 }; 43 44 /// Simple recorder for a search tracer 45 class TraceRecorder { 46 protected: 47 /// The actual tracer 48 SearchTracer& tracer; 49 /// The engine id 50 unsigned int _eid; 51 /// The worker id 52 unsigned int _wid; 53 /// The next free node id 54 unsigned int _nid; 55 public: 56 /// Class for storing identifiers 57 class ID { 58 protected: 59 /// The actual identifier 60 unsigned int _id; 61 public: 62 /// Do not initialize 63 ID(void); 64 /// Initialize 65 ID(unsigned int id); 66 /// Access 67 operator unsigned int(void) const; 68 }; 69 /// Initialize 70 TraceRecorder(SearchTracer* t); 71 /// Register engine 72 void engine(SearchTracer::EngineType t, unsigned int n); 73 /// Register worker 74 void worker(void); 75 /// Generate new node id 76 unsigned int nid(void); 77 /// Return worker id 78 unsigned int wid(void) const; 79 /// The workers goes to a next round (restart or next iteration in LDS) 80 void round(void); 81 /// The engine skips an edge 82 void skip(const SearchTracer::EdgeInfo& ei); 83 /// The engine creates a new node with information \a ei and \a ni 84 void node(const SearchTracer::EdgeInfo& ei, 85 const SearchTracer::NodeInfo& ni); 86 /// The worker is done 87 void done(void); 88 /// Whether this is a real tracer 89 operator bool(void) const; 90 }; 91 92 /// Recorder for a search tracer with edge information 93 class EdgeTraceRecorder : public TraceRecorder { 94 protected: 95 /// Edge information 96 SearchTracer::EdgeInfo _ei; 97 public: 98 /// Initialize 99 EdgeTraceRecorder(SearchTracer* t); 100 /// Invalidate edge information 101 void invalidate(void); 102 /// Provide access to edge information 103 SearchTracer::EdgeInfo* ei(void); 104 }; 105 106 /// Empty trace recorder 107 class NoTraceRecorder { 108 public: 109 /// Class for storing node identifiers 110 class ID { 111 public: 112 /// Do not initialize 113 ID(void); 114 /// Initialize 115 ID(unsigned int id); 116 /// Access 117 operator unsigned int(void) const; 118 }; 119 /// Initialize 120 NoTraceRecorder(SearchTracer* t); 121 /// Register engine 122 void engine(SearchTracer::EngineType t, unsigned int n); 123 /// Register worker 124 void worker(void); 125 /// Return worker id 126 unsigned int wid(void) const; 127 /// Generate new node id 128 unsigned int nid(void); 129 /// Invalidate edge information 130 void invalidate(void); 131 /// Provide access to edge information 132 SearchTracer::EdgeInfo* ei(void); 133 /// The workers goes to a next round (restart or next iteration in LDS) 134 void round(void); 135 /// The engine skips an edge 136 void skip(const SearchTracer::EdgeInfo& ei); 137 /// The engine creates a new node with information \a ei and \a ni 138 void node(const SearchTracer::EdgeInfo& ei, 139 const SearchTracer::NodeInfo& ni); 140 /// The worker is done 141 void done(void); 142 /// Whether this is a real tracer 143 operator bool(void) const; 144 }; 145 146 147 /* 148 * Recorder for engine events 149 * 150 */ 151 forceinline void engine(SearchTracer * tracer,SearchTracer::EngineType t,unsigned int n)152 WrapTraceRecorder::engine(SearchTracer* tracer, 153 SearchTracer::EngineType t, unsigned int n) { 154 if (tracer) tracer->engine(t,n); 155 } 156 157 158 /* 159 * Simple trace recorder for a search tracer 160 * 161 */ 162 forceinline ID(void)163 TraceRecorder::ID::ID(void) {} 164 165 forceinline ID(unsigned int id)166 TraceRecorder::ID::ID(unsigned int id) : _id(id) {} 167 168 forceinline operator unsigned int(void) const169 TraceRecorder::ID::operator unsigned int(void) const { 170 return _id; 171 } 172 173 forceinline TraceRecorder(SearchTracer * t)174 TraceRecorder::TraceRecorder(SearchTracer* t) 175 : tracer(*t), _eid(0U), _wid(0U), _nid(0U) {} 176 177 forceinline void engine(SearchTracer::EngineType t,unsigned int n)178 TraceRecorder::engine(SearchTracer::EngineType t, unsigned int n) { 179 tracer.engine(t,n); 180 } 181 182 forceinline void worker(void)183 TraceRecorder::worker(void) { 184 tracer.worker(_wid,_eid); 185 } 186 187 forceinline unsigned int nid(void)188 TraceRecorder::nid(void) { 189 return _nid++; 190 } 191 192 forceinline unsigned int wid(void) const193 TraceRecorder::wid(void) const { 194 return _wid; 195 } 196 197 forceinline void round(void)198 TraceRecorder::round(void) { 199 tracer._round(_eid); 200 } 201 202 forceinline void skip(const SearchTracer::EdgeInfo & ei)203 TraceRecorder::skip(const SearchTracer::EdgeInfo& ei) { 204 tracer._skip(ei); 205 } 206 207 forceinline void node(const SearchTracer::EdgeInfo & ei,const SearchTracer::NodeInfo & ni)208 TraceRecorder::node(const SearchTracer::EdgeInfo& ei, 209 const SearchTracer::NodeInfo& ni) { 210 tracer._node(ei,ni); 211 } 212 213 forceinline void done(void)214 TraceRecorder::done(void) { 215 tracer.worker(); 216 } 217 218 forceinline operator bool(void) const219 TraceRecorder::operator bool(void) const { 220 return true; 221 } 222 223 224 /* 225 * Recorder for a search tracer with edge information 226 * 227 */ 228 forceinline EdgeTraceRecorder(SearchTracer * t)229 EdgeTraceRecorder::EdgeTraceRecorder(SearchTracer* t) 230 : TraceRecorder(t) {} 231 232 forceinline void invalidate(void)233 EdgeTraceRecorder::invalidate(void) { 234 _ei.invalidate(); 235 } 236 237 forceinline SearchTracer::EdgeInfo* ei(void)238 EdgeTraceRecorder::ei(void) { 239 return &_ei; 240 } 241 242 243 /* 244 * Empty trace recorder 245 * 246 */ 247 forceinline ID(void)248 NoTraceRecorder::ID::ID(void) {} 249 250 forceinline ID(unsigned int)251 NoTraceRecorder::ID::ID(unsigned int) {} 252 253 forceinline operator unsigned int(void) const254 NoTraceRecorder::ID::operator unsigned int(void) const { 255 return 0U; 256 } 257 258 forceinline NoTraceRecorder(SearchTracer *)259 NoTraceRecorder::NoTraceRecorder(SearchTracer*) {} 260 261 forceinline void engine(SearchTracer::EngineType,unsigned int)262 NoTraceRecorder::engine(SearchTracer::EngineType, unsigned int) {} 263 264 forceinline void worker(void)265 NoTraceRecorder::worker(void) {} 266 267 forceinline unsigned int wid(void) const268 NoTraceRecorder::wid(void) const { 269 return 0U; 270 } 271 272 forceinline unsigned int nid(void)273 NoTraceRecorder::nid(void) { 274 return 0U; 275 } 276 277 forceinline void invalidate(void)278 NoTraceRecorder::invalidate(void) {} 279 280 forceinline SearchTracer::EdgeInfo* ei(void)281 NoTraceRecorder::ei(void) { 282 return nullptr; 283 } 284 285 forceinline void round(void)286 NoTraceRecorder::round(void) {} 287 288 forceinline void skip(const SearchTracer::EdgeInfo &)289 NoTraceRecorder::skip(const SearchTracer::EdgeInfo&) {} 290 291 forceinline void node(const SearchTracer::EdgeInfo &,const SearchTracer::NodeInfo &)292 NoTraceRecorder::node(const SearchTracer::EdgeInfo&, 293 const SearchTracer::NodeInfo&) { 294 } 295 296 forceinline void done(void)297 NoTraceRecorder::done(void) { 298 } 299 300 forceinline operator bool(void) const301 NoTraceRecorder::operator bool(void) const { 302 return false; 303 } 304 305 }} 306 307 // STATISTICS: search-trace 308