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 
initialize(const char * type,size_t typeLen,SkEventSinkID targetID)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 
SkEvent()25 SkEvent::SkEvent()
26 {
27     initialize("", 0, 0);
28 }
29 
SkEvent(const SkEvent & src)30 SkEvent::SkEvent(const SkEvent& src)
31 {
32     *this = src;
33     if (((size_t) fType & 1) == 0)
34         setType(src.fType);
35 }
36 
SkEvent(const SkString & type,SkEventSinkID targetID)37 SkEvent::SkEvent(const SkString& type, SkEventSinkID targetID)
38 {
39     initialize(type.c_str(), type.size(), targetID);
40 }
41 
SkEvent(const char type[],SkEventSinkID targetID)42 SkEvent::SkEvent(const char type[], SkEventSinkID targetID)
43 {
44     SkASSERT(type);
45     initialize(type, strlen(type), targetID);
46 }
47 
~SkEvent()48 SkEvent::~SkEvent()
49 {
50     if (((size_t) fType & 1) == 0)
51         sk_free((void*) fType);
52 }
53 
makeCharArray(char * buffer,size_t compact)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 
getType(SkString * str) const62 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 
isType(const SkString & str) const77 bool SkEvent::isType(const SkString& str) const
78 {
79     return this->isType(str.c_str(), str.size());
80 }
81 
isType(const char type[],size_t typeLen) const82 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 
setType(const char type[],size_t typeLen)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 
setType(const SkString & type)115 void SkEvent::setType(const SkString& type)
116 {
117     setType(type.c_str());
118 }
119 
120 ////////////////////////////////////////////////////////////////////////////
121 
122 #include "SkParse.h"
123 
inflate(const SkDOM & dom,const SkDOM::Node * node)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 
dump(const char title[])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
event_log(const char s[])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:
SkEvent_Globals()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 
getGlobals()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 
postDelay(SkMSec delay)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 
postTime(SkMSec time)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 
Enqueue(SkEvent * evt)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 
Dequeue()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 
QHasEvents()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 
EnqueueTime(SkEvent * evt,SkMSec time)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 
ProcessEvent()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 
ServiceQueueTimer()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 
CountEventsOnQueue()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 
Init()490 void SkEvent::Init() {}
491 
Term()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 }
509