]> git.cworth.org Git - apitrace/blob - common/trace_callset.hpp
Use skiplist-based FastCallSet within trace::CallSet
[apitrace] / common / trace_callset.hpp
1 /**************************************************************************
2  *
3  * Copyright 2012 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 /*
27  * Representation of call sets.
28  *
29  * Grammar:
30  *
31  *     set = '@' filename
32  *         | range ( ',' ? range ) *
33  *
34  *     range = interval ( '/' frequency )
35  *
36  *     interval = '*'
37  *              | number
38  *              | start_number '-' end_number
39  *
40  *     frequency = divisor
41  *               | "frame"
42  *               | "rendertarget" | "fbo"
43  *               | "render | "draw"
44  *
45  */
46
47 #ifndef _TRACE_CALLSET_HPP_
48 #define _TRACE_CALLSET_HPP_
49
50
51 #include <limits>
52 #include <list>
53
54 #include "trace_model.hpp"
55 #include "trace_fast_callset.hpp"
56
57 namespace trace {
58
59     // Aliases for call flags
60     enum {
61         FREQUENCY_NONE         = 0,
62         FREQUENCY_FRAME        = CALL_FLAG_END_FRAME,
63         FREQUENCY_RENDERTARGET = CALL_FLAG_END_FRAME | CALL_FLAG_SWAP_RENDERTARGET,
64         FREQUENCY_RENDER       = CALL_FLAG_RENDER,
65         FREQUENCY_ALL          = 0xffffffff
66     };
67
68     // A linear range of calls
69     class CallRange
70     {
71     public:
72         CallNo start;
73         CallNo stop;
74         CallNo step;
75         CallFlags freq;
76
77         CallRange(CallNo callNo) :
78             start(callNo),
79             stop(callNo),
80             step(1),
81             freq(FREQUENCY_ALL)
82         {}
83
84         CallRange(CallNo _start, CallNo _stop, CallNo _step = 1, CallFlags _freq = FREQUENCY_ALL) :
85             start(_start),
86             stop(_stop),
87             step(_step),
88             freq(_freq)
89         {}
90
91         bool
92         contains(CallNo callNo, CallFlags callFlags) const {
93             return callNo >= start &&
94                    callNo <= stop &&
95                    ((callNo - start) % step) == 0 &&
96                    ((callFlags & freq) ||
97                     freq == FREQUENCY_ALL);
98         }
99     };
100
101
102     // A collection of call ranges
103     class CallSet
104     {
105     private:
106         CallRange limits;
107
108     public:
109         FastCallSet fast_call_set;
110
111         // TODO: use binary tree to speed up lookups, (less important
112         // now that we are using FastCallSet for ranges without step
113         // or freq).
114         typedef std::list< CallRange > RangeList;
115         RangeList ranges;
116
117         CallSet(): limits(std::numeric_limits<CallNo>::min(), std::numeric_limits<CallNo>::max()) {}
118
119         CallSet(CallFlags freq);
120
121         CallSet(const char *str);
122
123         // Not empty set
124         inline bool
125         empty() const {
126             return fast_call_set.empty() && ranges.empty();
127         }
128
129         void
130         addRange(const CallRange & range) {
131             if (range.start <= range.stop &&
132                 range.freq != FREQUENCY_NONE) {
133
134                 if (empty()) {
135                     limits.start = range.start;
136                     limits.stop = range.stop;
137                 } else {
138                     if (range.start < limits.start)
139                         limits.start = range.start;
140                     if (range.stop > limits.stop)
141                         limits.stop = range.stop;
142                 }
143
144                 /* Optimize by using fast_call_set whenever possible */
145                 if (range.step == 1 && range.freq == FREQUENCY_ALL) {
146                     fast_call_set.add(range.start, range.stop);
147                 } else {
148                     RangeList::iterator it = ranges.begin();
149                     while (it != ranges.end() && it->start < range.start) {
150                         ++it;
151                     }
152
153                     ranges.insert(it, range);
154                 }
155             }
156         }
157
158         inline bool
159         contains(CallNo callNo, CallFlags callFlags = FREQUENCY_ALL) const {
160             if (empty()) {
161                 return false;
162             }
163             if (fast_call_set.contains(callNo))
164                 return true;
165             RangeList::const_iterator it;
166             for (it = ranges.begin(); it != ranges.end() && it->start <= callNo; ++it) {
167                 if (it->contains(callNo, callFlags)) {
168                     return true;
169                 }
170             }
171             return false;
172         }
173
174         inline bool
175         contains(const trace::Call &call) {
176             return contains(call.no, call.flags);
177         }
178
179         CallNo getFirst() {
180             return limits.start;
181         }
182
183         CallNo getLast() {
184             return limits.stop;
185         }
186     };
187
188
189     CallSet parse(const char *string);
190
191
192 } /* namespace trace */
193
194
195 #endif /* _TRACE_CALLSET_HPP_ */