|
1 |
|
2 /* |
|
3 * Copyright 2006 The Android Open Source Project |
|
4 * |
|
5 * Use of this source code is governed by a BSD-style license that can be |
|
6 * found in the LICENSE file. |
|
7 */ |
|
8 |
|
9 |
|
10 #include "SkEvent.h" |
|
11 |
|
12 void SkEvent::initialize(const char* type, size_t typeLen, |
|
13 SkEventSinkID targetID) { |
|
14 fType = NULL; |
|
15 setType(type, typeLen); |
|
16 f32 = 0; |
|
17 fTargetID = targetID; |
|
18 fTargetProc = NULL; |
|
19 #ifdef SK_DEBUG |
|
20 fTime = 0; |
|
21 fNextEvent = NULL; |
|
22 #endif |
|
23 } |
|
24 |
|
25 SkEvent::SkEvent() |
|
26 { |
|
27 initialize("", 0, 0); |
|
28 } |
|
29 |
|
30 SkEvent::SkEvent(const SkEvent& src) |
|
31 { |
|
32 *this = src; |
|
33 if (((size_t) fType & 1) == 0) |
|
34 setType(src.fType); |
|
35 } |
|
36 |
|
37 SkEvent::SkEvent(const SkString& type, SkEventSinkID targetID) |
|
38 { |
|
39 initialize(type.c_str(), type.size(), targetID); |
|
40 } |
|
41 |
|
42 SkEvent::SkEvent(const char type[], SkEventSinkID targetID) |
|
43 { |
|
44 SkASSERT(type); |
|
45 initialize(type, strlen(type), targetID); |
|
46 } |
|
47 |
|
48 SkEvent::~SkEvent() |
|
49 { |
|
50 if (((size_t) fType & 1) == 0) |
|
51 sk_free((void*) fType); |
|
52 } |
|
53 |
|
54 static size_t makeCharArray(char* buffer, size_t compact) |
|
55 { |
|
56 size_t bits = (size_t) compact >> 1; |
|
57 memcpy(buffer, &bits, sizeof(compact)); |
|
58 buffer[sizeof(compact)] = 0; |
|
59 return strlen(buffer); |
|
60 } |
|
61 |
|
62 void SkEvent::getType(SkString* str) const |
|
63 { |
|
64 if (str) |
|
65 { |
|
66 if ((size_t) fType & 1) // not a pointer |
|
67 { |
|
68 char chars[sizeof(size_t) + 1]; |
|
69 size_t len = makeCharArray(chars, (size_t) fType); |
|
70 str->set(chars, len); |
|
71 } |
|
72 else |
|
73 str->set(fType); |
|
74 } |
|
75 } |
|
76 |
|
77 bool SkEvent::isType(const SkString& str) const |
|
78 { |
|
79 return this->isType(str.c_str(), str.size()); |
|
80 } |
|
81 |
|
82 bool SkEvent::isType(const char type[], size_t typeLen) const |
|
83 { |
|
84 if (typeLen == 0) |
|
85 typeLen = strlen(type); |
|
86 if ((size_t) fType & 1) { // not a pointer |
|
87 char chars[sizeof(size_t) + 1]; |
|
88 size_t len = makeCharArray(chars, (size_t) fType); |
|
89 return len == typeLen && strncmp(chars, type, typeLen) == 0; |
|
90 } |
|
91 return strncmp(fType, type, typeLen) == 0 && fType[typeLen] == 0; |
|
92 } |
|
93 |
|
94 void SkEvent::setType(const char type[], size_t typeLen) |
|
95 { |
|
96 if (typeLen == 0) |
|
97 typeLen = strlen(type); |
|
98 if (typeLen <= sizeof(fType)) { |
|
99 size_t slot = 0; |
|
100 memcpy(&slot, type, typeLen); |
|
101 if (slot << 1 >> 1 != slot) |
|
102 goto useCharStar; |
|
103 slot <<= 1; |
|
104 slot |= 1; |
|
105 fType = (char*) slot; |
|
106 } else { |
|
107 useCharStar: |
|
108 fType = (char*) sk_malloc_throw(typeLen + 1); |
|
109 SkASSERT(((size_t) fType & 1) == 0); |
|
110 memcpy(fType, type, typeLen); |
|
111 fType[typeLen] = 0; |
|
112 } |
|
113 } |
|
114 |
|
115 void SkEvent::setType(const SkString& type) |
|
116 { |
|
117 setType(type.c_str()); |
|
118 } |
|
119 |
|
120 //////////////////////////////////////////////////////////////////////////// |
|
121 |
|
122 #include "SkParse.h" |
|
123 |
|
124 void SkEvent::inflate(const SkDOM& dom, const SkDOM::Node* node) |
|
125 { |
|
126 const char* name = dom.findAttr(node, "type"); |
|
127 if (name) |
|
128 this->setType(name); |
|
129 |
|
130 const char* value; |
|
131 if ((value = dom.findAttr(node, "fast32")) != NULL) |
|
132 { |
|
133 int32_t n; |
|
134 if (SkParse::FindS32(value, &n)) |
|
135 this->setFast32(n); |
|
136 } |
|
137 |
|
138 for (node = dom.getFirstChild(node); node; node = dom.getNextSibling(node)) |
|
139 { |
|
140 if (strcmp(dom.getName(node), "data")) |
|
141 { |
|
142 SkDEBUGCODE(SkDebugf("SkEvent::inflate unrecognized subelement <%s>\n", dom.getName(node));) |
|
143 continue; |
|
144 } |
|
145 |
|
146 name = dom.findAttr(node, "name"); |
|
147 if (name == NULL) |
|
148 { |
|
149 SkDEBUGCODE(SkDebugf("SkEvent::inflate missing required \"name\" attribute in <data> subelement\n");) |
|
150 continue; |
|
151 } |
|
152 |
|
153 if ((value = dom.findAttr(node, "s32")) != NULL) |
|
154 { |
|
155 int32_t n; |
|
156 if (SkParse::FindS32(value, &n)) |
|
157 this->setS32(name, n); |
|
158 } |
|
159 else if ((value = dom.findAttr(node, "scalar")) != NULL) |
|
160 { |
|
161 SkScalar x; |
|
162 if (SkParse::FindScalar(value, &x)) |
|
163 this->setScalar(name, x); |
|
164 } |
|
165 else if ((value = dom.findAttr(node, "string")) != NULL) |
|
166 this->setString(name, value); |
|
167 #ifdef SK_DEBUG |
|
168 else |
|
169 { |
|
170 SkDebugf("SkEvent::inflate <data name=\"%s\"> subelement missing required type attribute [S32 | scalar | string]\n", name); |
|
171 } |
|
172 #endif |
|
173 } |
|
174 } |
|
175 |
|
176 #ifdef SK_DEBUG |
|
177 |
|
178 #ifndef SkScalarToFloat |
|
179 #define SkScalarToFloat(x) ((x) / 65536.f) |
|
180 #endif |
|
181 |
|
182 void SkEvent::dump(const char title[]) |
|
183 { |
|
184 if (title) |
|
185 SkDebugf("%s ", title); |
|
186 |
|
187 SkString etype; |
|
188 this->getType(&etype); |
|
189 SkDebugf("event<%s> fast32=%d", etype.c_str(), this->getFast32()); |
|
190 |
|
191 const SkMetaData& md = this->getMetaData(); |
|
192 SkMetaData::Iter iter(md); |
|
193 SkMetaData::Type mtype; |
|
194 int count; |
|
195 const char* name; |
|
196 |
|
197 while ((name = iter.next(&mtype, &count)) != NULL) |
|
198 { |
|
199 SkASSERT(count > 0); |
|
200 |
|
201 SkDebugf(" <%s>=", name); |
|
202 switch (mtype) { |
|
203 case SkMetaData::kS32_Type: // vector version??? |
|
204 { |
|
205 int32_t value; |
|
206 md.findS32(name, &value); |
|
207 SkDebugf("%d ", value); |
|
208 } |
|
209 break; |
|
210 case SkMetaData::kScalar_Type: |
|
211 { |
|
212 const SkScalar* values = md.findScalars(name, &count, NULL); |
|
213 SkDebugf("%f", SkScalarToFloat(values[0])); |
|
214 for (int i = 1; i < count; i++) |
|
215 SkDebugf(", %f", SkScalarToFloat(values[i])); |
|
216 SkDebugf(" "); |
|
217 } |
|
218 break; |
|
219 case SkMetaData::kString_Type: |
|
220 { |
|
221 const char* value = md.findString(name); |
|
222 SkASSERT(value); |
|
223 SkDebugf("<%s> ", value); |
|
224 } |
|
225 break; |
|
226 case SkMetaData::kPtr_Type: // vector version??? |
|
227 { |
|
228 void* value; |
|
229 md.findPtr(name, &value); |
|
230 SkDebugf("%p ", value); |
|
231 } |
|
232 break; |
|
233 case SkMetaData::kBool_Type: // vector version??? |
|
234 { |
|
235 bool value; |
|
236 md.findBool(name, &value); |
|
237 SkDebugf("%s ", value ? "true" : "false"); |
|
238 } |
|
239 break; |
|
240 default: |
|
241 SkDEBUGFAIL("unknown metadata type returned from iterator"); |
|
242 break; |
|
243 } |
|
244 } |
|
245 SkDebugf("\n"); |
|
246 } |
|
247 #endif |
|
248 |
|
249 /////////////////////////////////////////////////////////////////////////////////////// |
|
250 |
|
251 #ifdef SK_DEBUG |
|
252 // #define SK_TRACE_EVENTSx |
|
253 #endif |
|
254 |
|
255 #ifdef SK_TRACE_EVENTS |
|
256 static void event_log(const char s[]) |
|
257 { |
|
258 SkDEBUGF(("%s\n", s)); |
|
259 } |
|
260 |
|
261 #define EVENT_LOG(s) event_log(s) |
|
262 #define EVENT_LOGN(s, n) do { SkString str(s); str.append(" "); str.appendS32(n); event_log(str.c_str()); } while (0) |
|
263 #else |
|
264 #define EVENT_LOG(s) |
|
265 #define EVENT_LOGN(s, n) |
|
266 #endif |
|
267 |
|
268 #include "SkThread.h" |
|
269 #include "SkTime.h" |
|
270 |
|
271 class SkEvent_Globals { |
|
272 public: |
|
273 SkEvent_Globals() { |
|
274 fEventQHead = NULL; |
|
275 fEventQTail = NULL; |
|
276 fDelayQHead = NULL; |
|
277 SkDEBUGCODE(fEventCounter = 0;) |
|
278 } |
|
279 |
|
280 SkMutex fEventMutex; |
|
281 SkEvent* fEventQHead, *fEventQTail; |
|
282 SkEvent* fDelayQHead; |
|
283 SkDEBUGCODE(int fEventCounter;) |
|
284 }; |
|
285 |
|
286 static SkEvent_Globals& getGlobals() { |
|
287 // leak this, so we don't incure any shutdown perf hit |
|
288 static SkEvent_Globals* gGlobals = new SkEvent_Globals; |
|
289 return *gGlobals; |
|
290 } |
|
291 |
|
292 /////////////////////////////////////////////////////////////////////////////// |
|
293 |
|
294 void SkEvent::postDelay(SkMSec delay) { |
|
295 if (!fTargetID && !fTargetProc) { |
|
296 delete this; |
|
297 return; |
|
298 } |
|
299 |
|
300 if (delay) { |
|
301 this->postTime(SkTime::GetMSecs() + delay); |
|
302 return; |
|
303 } |
|
304 |
|
305 SkEvent_Globals& globals = getGlobals(); |
|
306 |
|
307 globals.fEventMutex.acquire(); |
|
308 bool wasEmpty = SkEvent::Enqueue(this); |
|
309 globals.fEventMutex.release(); |
|
310 |
|
311 // call outside of us holding the mutex |
|
312 if (wasEmpty) { |
|
313 SkEvent::SignalNonEmptyQueue(); |
|
314 } |
|
315 } |
|
316 |
|
317 void SkEvent::postTime(SkMSec time) { |
|
318 if (!fTargetID && !fTargetProc) { |
|
319 delete this; |
|
320 return; |
|
321 } |
|
322 |
|
323 SkEvent_Globals& globals = getGlobals(); |
|
324 |
|
325 globals.fEventMutex.acquire(); |
|
326 SkMSec queueDelay = SkEvent::EnqueueTime(this, time); |
|
327 globals.fEventMutex.release(); |
|
328 |
|
329 // call outside of us holding the mutex |
|
330 if ((int32_t)queueDelay != ~0) { |
|
331 SkEvent::SignalQueueTimer(queueDelay); |
|
332 } |
|
333 } |
|
334 |
|
335 bool SkEvent::Enqueue(SkEvent* evt) { |
|
336 SkEvent_Globals& globals = getGlobals(); |
|
337 // gEventMutex acquired by caller |
|
338 |
|
339 SkASSERT(evt); |
|
340 |
|
341 bool wasEmpty = globals.fEventQHead == NULL; |
|
342 |
|
343 if (globals.fEventQTail) |
|
344 globals.fEventQTail->fNextEvent = evt; |
|
345 globals.fEventQTail = evt; |
|
346 if (globals.fEventQHead == NULL) |
|
347 globals.fEventQHead = evt; |
|
348 evt->fNextEvent = NULL; |
|
349 |
|
350 SkDEBUGCODE(++globals.fEventCounter); |
|
351 |
|
352 return wasEmpty; |
|
353 } |
|
354 |
|
355 SkEvent* SkEvent::Dequeue() { |
|
356 SkEvent_Globals& globals = getGlobals(); |
|
357 globals.fEventMutex.acquire(); |
|
358 |
|
359 SkEvent* evt = globals.fEventQHead; |
|
360 if (evt) { |
|
361 SkDEBUGCODE(--globals.fEventCounter); |
|
362 |
|
363 globals.fEventQHead = evt->fNextEvent; |
|
364 if (globals.fEventQHead == NULL) { |
|
365 globals.fEventQTail = NULL; |
|
366 } |
|
367 } |
|
368 globals.fEventMutex.release(); |
|
369 |
|
370 return evt; |
|
371 } |
|
372 |
|
373 bool SkEvent::QHasEvents() { |
|
374 SkEvent_Globals& globals = getGlobals(); |
|
375 |
|
376 // this is not thread accurate, need a semaphore for that |
|
377 return globals.fEventQHead != NULL; |
|
378 } |
|
379 |
|
380 #ifdef SK_TRACE_EVENTS |
|
381 static int gDelayDepth; |
|
382 #endif |
|
383 |
|
384 SkMSec SkEvent::EnqueueTime(SkEvent* evt, SkMSec time) { |
|
385 SkEvent_Globals& globals = getGlobals(); |
|
386 // gEventMutex acquired by caller |
|
387 |
|
388 SkEvent* curr = globals.fDelayQHead; |
|
389 SkEvent* prev = NULL; |
|
390 |
|
391 while (curr) { |
|
392 if (SkMSec_LT(time, curr->fTime)) { |
|
393 break; |
|
394 } |
|
395 prev = curr; |
|
396 curr = curr->fNextEvent; |
|
397 } |
|
398 |
|
399 evt->fTime = time; |
|
400 evt->fNextEvent = curr; |
|
401 if (prev == NULL) { |
|
402 globals.fDelayQHead = evt; |
|
403 } else { |
|
404 prev->fNextEvent = evt; |
|
405 } |
|
406 |
|
407 SkMSec delay = globals.fDelayQHead->fTime - SkTime::GetMSecs(); |
|
408 if ((int32_t)delay <= 0) { |
|
409 delay = 1; |
|
410 } |
|
411 return delay; |
|
412 } |
|
413 |
|
414 /////////////////////////////////////////////////////////////////////////////// |
|
415 |
|
416 #include "SkEventSink.h" |
|
417 |
|
418 bool SkEvent::ProcessEvent() { |
|
419 SkEvent* evt = SkEvent::Dequeue(); |
|
420 SkAutoTDelete<SkEvent> autoDelete(evt); |
|
421 bool again = false; |
|
422 |
|
423 EVENT_LOGN("ProcessEvent", (int32_t)evt); |
|
424 |
|
425 if (evt) { |
|
426 (void)SkEventSink::DoEvent(*evt); |
|
427 again = SkEvent::QHasEvents(); |
|
428 } |
|
429 return again; |
|
430 } |
|
431 |
|
432 void SkEvent::ServiceQueueTimer() |
|
433 { |
|
434 SkEvent_Globals& globals = getGlobals(); |
|
435 |
|
436 globals.fEventMutex.acquire(); |
|
437 |
|
438 bool wasEmpty = false; |
|
439 SkMSec now = SkTime::GetMSecs(); |
|
440 SkEvent* evt = globals.fDelayQHead; |
|
441 |
|
442 while (evt) |
|
443 { |
|
444 if (SkMSec_LT(now, evt->fTime)) |
|
445 break; |
|
446 |
|
447 #ifdef SK_TRACE_EVENTS |
|
448 --gDelayDepth; |
|
449 SkDebugf("dequeue-delay %s (%d)", evt->getType(), gDelayDepth); |
|
450 const char* idStr = evt->findString("id"); |
|
451 if (idStr) |
|
452 SkDebugf(" (%s)", idStr); |
|
453 SkDebugf("\n"); |
|
454 #endif |
|
455 |
|
456 SkEvent* next = evt->fNextEvent; |
|
457 if (SkEvent::Enqueue(evt)) |
|
458 wasEmpty = true; |
|
459 evt = next; |
|
460 } |
|
461 globals.fDelayQHead = evt; |
|
462 |
|
463 SkMSec time = evt ? evt->fTime - now : 0; |
|
464 |
|
465 globals.fEventMutex.release(); |
|
466 |
|
467 if (wasEmpty) |
|
468 SkEvent::SignalNonEmptyQueue(); |
|
469 |
|
470 SkEvent::SignalQueueTimer(time); |
|
471 } |
|
472 |
|
473 int SkEvent::CountEventsOnQueue() { |
|
474 SkEvent_Globals& globals = getGlobals(); |
|
475 globals.fEventMutex.acquire(); |
|
476 |
|
477 int count = 0; |
|
478 const SkEvent* evt = globals.fEventQHead; |
|
479 while (evt) { |
|
480 count += 1; |
|
481 evt = evt->fNextEvent; |
|
482 } |
|
483 globals.fEventMutex.release(); |
|
484 |
|
485 return count; |
|
486 } |
|
487 |
|
488 /////////////////////////////////////////////////////////////////////////////// |
|
489 |
|
490 void SkEvent::Init() {} |
|
491 |
|
492 void SkEvent::Term() { |
|
493 SkEvent_Globals& globals = getGlobals(); |
|
494 |
|
495 SkEvent* evt = globals.fEventQHead; |
|
496 while (evt) { |
|
497 SkEvent* next = evt->fNextEvent; |
|
498 delete evt; |
|
499 evt = next; |
|
500 } |
|
501 |
|
502 evt = globals.fDelayQHead; |
|
503 while (evt) { |
|
504 SkEvent* next = evt->fNextEvent; |
|
505 delete evt; |
|
506 evt = next; |
|
507 } |
|
508 } |