10
10
#include " caliper/SnapshotRecord.h"
11
11
12
12
#include " caliper/common/Log.h"
13
+ #include " caliper/common/Node.h"
13
14
#include " caliper/common/OutputStream.h"
14
15
15
16
#include " caliper/reader/Expand.h"
@@ -53,21 +54,45 @@ class ValidatorService
53
54
{
54
55
std::map< Attribute, std::vector<Variant> > m_region_stack;
55
56
bool m_error_found;
57
+ Node m_root_node;
58
+
59
+ void push (Caliper* c, const Attribute& attr, const Variant& value) {
60
+ Variant v_copy = value;
61
+
62
+ if (!attr.store_as_value ())
63
+ v_copy = c->make_tree_entry (attr, value, &m_root_node)->data ();
64
+
65
+ m_region_stack[attr].push_back (v_copy);
66
+ }
67
+
68
+ Variant pop (const Attribute& attr) {
69
+ Variant ret;
70
+
71
+ auto it = m_region_stack.find (attr);
72
+ if (it == m_region_stack.end ())
73
+ return ret;
74
+ if (it->second .empty ())
75
+ return ret;
76
+
77
+ ret = it->second .back ();
78
+ it->second .pop_back ();
79
+
80
+ if (it->second .empty ())
81
+ m_region_stack.erase (it);
82
+
83
+ return ret;
84
+ }
56
85
57
86
public:
58
87
59
- bool check_begin (const Attribute& attr, const Variant& value) {
88
+ bool check_begin (Caliper* c, const Attribute& attr, const Variant& value) {
60
89
if (m_error_found)
61
90
return true ;
62
91
63
- m_region_stack[attr]. push_back ( value);
92
+ push (c, attr, value);
64
93
65
- if (attr.is_nested ()) {
66
- cali_id_t id = attr.id ();
67
- Variant v_id (CALI_TYPE_UINT, &id, sizeof (cali_id_t ));
68
-
69
- m_region_stack[s_class_nested_attr].push_back (Variant (attr.id ()));
70
- }
94
+ if (attr.is_nested ())
95
+ push (c, s_class_nested_attr, Variant (attr.id ()));
71
96
72
97
return false ;
73
98
}
@@ -76,9 +101,9 @@ class ValidatorService
76
101
if (m_error_found)
77
102
return true ;
78
103
79
- auto it = m_region_stack. find (attr);
104
+ Variant v_stack_val = pop (attr);
80
105
81
- if (it == m_region_stack. end () || it-> second .empty ()) {
106
+ if (v_stack_val .empty ()) {
82
107
// We currently can't actually check this situation because
83
108
// the Caliper runtime prevents events being executed in
84
109
// "empty stack" situations :-/
@@ -93,17 +118,8 @@ class ValidatorService
93
118
} else {
94
119
Variant v_stack_attr;
95
120
96
- if (attr.is_nested ()) {
97
- auto n_it = m_region_stack.find (s_class_nested_attr);
98
-
99
- if (n_it != m_region_stack.end () && !n_it->second .empty ()) {
100
- v_stack_attr = n_it->second .back ();
101
- n_it->second .pop_back ();
102
- }
103
- }
104
-
105
- Variant v_stack_val = it->second .back ();
106
- it->second .pop_back ();
121
+ if (attr.is_nested ())
122
+ v_stack_attr = pop (s_class_nested_attr);
107
123
108
124
if (attr.is_nested () && attr.id () != v_stack_attr.to_id ()) {
109
125
m_error_found = true ;
@@ -132,15 +148,18 @@ class ValidatorService
132
148
133
149
bool check_final () {
134
150
for (auto const &p : m_region_stack) {
135
- if (p.second .size () > 0 ) {
151
+ if (p.first == s_class_nested_attr)
152
+ continue ;
153
+
154
+ if (!p.second .empty ()) {
136
155
std::ostringstream os;
137
156
138
157
os << " validator: Regions not closed: "
139
158
<< p.first .name () << " =" ;
140
159
141
160
int cv = 0 ;
142
- for (auto const & v : p.second )
143
- os << (cv++ > 0 ? " /" : " " ) << v;
161
+ for (const Variant& v : p.second )
162
+ os << (cv++ > 0 ? " /" : " " ) << v. to_string () ;
144
163
145
164
Log (0 ).stream () << os.str () << std::endl;
146
165
@@ -152,7 +171,7 @@ class ValidatorService
152
171
}
153
172
154
173
StackValidator ()
155
- : m_error_found(false )
174
+ : m_error_found(false ), m_root_node(CALI_INV_ID, CALI_INV_ID, Variant())
156
175
{ }
157
176
}; // class StackValidator
158
177
@@ -162,39 +181,29 @@ class ValidatorService
162
181
163
182
std::atomic<int > global_errors;
164
183
165
- struct ThreadData {
166
- std::vector<StackValidator*> exp_validators;
184
+ Attribute thread_stack_attr;
167
185
168
- ~ThreadData () {
169
- for (StackValidator* v : exp_validators)
170
- if (v) {
171
- v->check_final ();
172
- delete v;
173
- }
174
- }
186
+ std::vector<StackValidator*> thread_stacks;
187
+ std::mutex thread_stacks_mutex;
175
188
176
- StackValidator* get_validator (Channel* chn) {
177
- size_t expI = chn->id ();
178
- StackValidator* v = nullptr ;
179
189
180
- if (expI < exp_validators.size ())
181
- v = exp_validators[expI];
190
+ StackValidator* aquire_thread_stack (Caliper* c, Channel* chn) {
191
+ StackValidator* tstack =
192
+ static_cast <StackValidator*>(c->get (thread_stack_attr).value ().get_ptr ());
182
193
183
- if (!v ) {
184
- v = new StackValidator;
194
+ if (!tstack ) {
195
+ tstack = new StackValidator;
185
196
186
- if (exp_validators.size () <= expI)
187
- exp_validators.resize (expI + 1 );
197
+ c->set (thread_stack_attr, Variant (cali_make_variant_from_ptr (tstack)));
188
198
189
- exp_validators[expI] = v;
190
- }
199
+ std::lock_guard<std::mutex>
200
+ g (thread_stacks_mutex);
191
201
192
- return v ;
202
+ thread_stacks. push_back (tstack) ;
193
203
}
194
- };
195
-
196
- static thread_local ThreadData sT ;
197
204
205
+ return tstack;
206
+ }
198
207
199
208
void finalize_cb (Caliper*, Channel* chn) {
200
209
{
@@ -208,10 +217,19 @@ class ValidatorService
208
217
proc_stack = nullptr ;
209
218
}
210
219
211
- // StackValidator* v = sT.get_validator(chn);
220
+ {
221
+ std::lock_guard<std::mutex>
222
+ g (thread_stacks_mutex);
223
+
224
+ for (StackValidator* v : thread_stacks) {
225
+ if (v->check_final ())
226
+ ++global_errors;
227
+
228
+ delete v;
229
+ }
212
230
213
- // if (v && v->check_final())
214
- // ++global_errors;
231
+ thread_stacks. clear ();
232
+ }
215
233
216
234
if (global_errors.load () > 0 )
217
235
Log (0 ).stream () << " validator: Annotation nesting errors found"
@@ -226,12 +244,12 @@ class ValidatorService
226
244
std::lock_guard<std::mutex>
227
245
g (proc_stack_mutex);
228
246
229
- if (proc_stack->check_begin (attr, value))
247
+ if (proc_stack->check_begin (c, attr, value))
230
248
++global_errors;
231
249
} else {
232
- StackValidator* v = sT . get_validator ( chn);
250
+ StackValidator* v = aquire_thread_stack (c, chn);
233
251
234
- if (v && v->check_begin (attr, value))
252
+ if (v && v->check_begin (c, attr, value))
235
253
++global_errors;
236
254
}
237
255
}
@@ -244,23 +262,31 @@ class ValidatorService
244
262
if (proc_stack->check_end (c, chn, attr, value))
245
263
++global_errors;
246
264
} else {
247
- StackValidator* v = sT . get_validator ( chn);
265
+ StackValidator* v = aquire_thread_stack (c, chn);
248
266
249
267
if (v && v->check_end (c, chn, attr, value))
250
268
++global_errors;
251
269
}
252
270
}
253
271
254
- ValidatorService (Caliper* c, Channel*)
272
+ ValidatorService (Caliper* c, Channel* chn )
255
273
: proc_stack(new StackValidator), global_errors(0 )
256
- { }
274
+ {
275
+ thread_stack_attr =
276
+ c->create_attribute (std::string (" validator.stack." )+std::to_string (chn->id ()),
277
+ CALI_TYPE_PTR,
278
+ CALI_ATTR_SCOPE_THREAD |
279
+ CALI_ATTR_ASVALUE |
280
+ CALI_ATTR_SKIP_EVENTS |
281
+ CALI_ATTR_HIDDEN);
282
+ }
257
283
258
284
public:
259
285
260
286
static void validator_register (Caliper* c, Channel* chn) {
261
287
if (s_class_nested_attr == Attribute::invalid)
262
288
s_class_nested_attr =
263
- c->create_attribute (" validator.nested" , CALI_TYPE_UINT, CALI_ATTR_DEFAULT );
289
+ c->create_attribute (" validator.nested" , CALI_TYPE_UINT, CALI_ATTR_ASVALUE | CALI_ATTR_HIDDEN );
264
290
265
291
ValidatorService* instance = new ValidatorService (c, chn);
266
292
@@ -283,8 +309,6 @@ class ValidatorService
283
309
284
310
};
285
311
286
- thread_local ValidatorService::ThreadData ValidatorService::sT ;
287
-
288
312
Attribute ValidatorService::s_class_nested_attr { Attribute::invalid };
289
313
290
314
} // namespace [anonymous]
0 commit comments