SkEvent.cpp revision 80bacfeb4bda06541e8695bd502229727bccfeab
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
12void 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
25SkEvent::SkEvent()
26{
27    initialize("", 0, 0);
28}
29
30SkEvent::SkEvent(const SkEvent& src)
31{
32    *this = src;
33    if (((size_t) fType & 1) == 0)
34        setType(src.fType);
35}
36
37SkEvent::SkEvent(const SkString& type, SkEventSinkID targetID)
38{
39    initialize(type.c_str(), type.size(), targetID);
40}
41
42SkEvent::SkEvent(const char type[], SkEventSinkID targetID)
43{
44    SkASSERT(type);
45    initialize(type, strlen(type), targetID);
46}
47
48SkEvent::~SkEvent()
49{
50    if (((size_t) fType & 1) == 0)
51        sk_free((void*) fType);
52}
53
54static 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
62void 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
77bool SkEvent::isType(const SkString& str) const
78{
79    return this->isType(str.c_str(), str.size());
80}
81
82bool 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
94void 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 {
107useCharStar:
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
115void SkEvent::setType(const SkString& type)
116{
117    setType(type.c_str());
118}
119
120////////////////////////////////////////////////////////////////////////////
121
122#include "SkParse.h"
123
124void 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
271class SkEvent_Globals {
272public:
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
286static 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
294void 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
317void 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
335bool 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
355SkEvent* 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
373bool 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
384SkMSec 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
418bool 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
432void 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
473int 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
490void SkEvent::Init() {}
491
492void 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
510