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