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