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