Changeset 30765 in vbox
- Timestamp:
- Jul 9, 2010 2:12:58 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/EventImpl.cpp
r30739 r30765 63 63 #include <VBox/com/array.h> 64 64 65 class ListenerRecord; 66 65 67 struct VBoxEvent::Data 66 68 { … … 350 352 static const int NumEvents = LastEvent - FirstEvent; 351 353 352 class ListenerRecord; 353 typedef std::list<ListenerRecord*> EventMap[NumEvents]; 354 /** 355 * Class replacing std::list and able to provide required stability 356 * during iteration. It's acheived by delaying structural modifications 357 * to the list till the moment particular element is no longer used by 358 * current iterators. 359 */ 360 class EventMapRecord 361 { 362 private: 363 /** 364 * We have to be double linked, as structural modifications in list are delayed 365 * till element removed, so we have to know our previous one to update its next 366 */ 367 EventMapRecord* mNext; 368 EventMapRecord* mPrev; 369 ListenerRecord* mRef; /* must be weak reference */ 370 int32_t mRefCnt; 371 bool mAlive; 372 public: 373 EventMapRecord(ListenerRecord* aRef) 374 : 375 mNext(0), 376 mPrev(0), 377 mRef(aRef), 378 mRefCnt(1), 379 mAlive(true) 380 {} 381 382 EventMapRecord(EventMapRecord& aOther) 383 { 384 mNext = aOther.mNext; 385 mPrev = aOther.mPrev; 386 mRef = aOther.mRef; 387 mRefCnt = aOther.mRefCnt; 388 mAlive = aOther.mAlive; 389 } 390 391 ~EventMapRecord() 392 { 393 if (mNext) 394 mNext->mPrev = mPrev; 395 if (mPrev) 396 mPrev->mNext = mNext; 397 } 398 399 void addRef() 400 { 401 ASMAtomicIncS32(&mRefCnt); 402 } 403 404 void release() 405 { 406 if (ASMAtomicDecS32(&mRefCnt) <= 0) delete this; 407 } 408 409 // Called when an element is no longer needed 410 void kill() 411 { 412 mAlive = false; 413 release(); 414 } 415 416 ListenerRecord* ref() 417 { 418 return mAlive ? mRef : 0; 419 } 420 421 friend class EventMapList; 422 }; 423 424 425 class EventMapList 426 { 427 EventMapRecord* mHead; 428 uint32_t mSize; 429 public: 430 EventMapList() 431 : 432 mHead(0), 433 mSize(0) 434 {} 435 ~EventMapList() 436 { 437 EventMapRecord* aCur = mHead; 438 while (aCur) 439 { 440 EventMapRecord* aNext = aCur->mNext; 441 aCur->release(); 442 aCur = aNext; 443 } 444 } 445 446 /* 447 * Elements have to be added to the front of the list, to make sure 448 * that iterators doesn't see newly added listeners, and iteration 449 * will always complete. 450 */ 451 void add(ListenerRecord* aRec) 452 { 453 EventMapRecord* aNew = new EventMapRecord(aRec); 454 aNew->mNext = mHead; 455 if (mHead) 456 mHead->mPrev = aNew; 457 mHead = aNew; 458 mSize++; 459 } 460 461 /* 462 * Mark element as removed, actual removal could be delayed until 463 * all consumers release it too. This helps to keep list stable 464 * enough for iterators to allow long and probably intrusive callbacks. 465 */ 466 void remove(ListenerRecord* aRec) 467 { 468 EventMapRecord* aCur = mHead; 469 while (aCur) 470 { 471 EventMapRecord* aNext = aCur->mNext; 472 if (aCur->ref() == aRec) 473 { 474 if (aCur == mHead) 475 mHead = aNext; 476 aCur->kill(); 477 mSize--; 478 // break? 479 } 480 aCur = aNext; 481 } 482 } 483 484 uint32_t size() const 485 { 486 return mSize; 487 } 488 489 struct iterator 490 { 491 EventMapRecord* mCur; 492 493 iterator() 494 : mCur(0) 495 {} 496 497 explicit 498 iterator(EventMapRecord* aCur) 499 : mCur(aCur) 500 { 501 // Prevent element removal, till we're at it 502 if (mCur) 503 mCur->addRef(); 504 } 505 506 ~iterator() 507 { 508 if (mCur) 509 mCur->release(); 510 } 511 512 ListenerRecord* 513 operator*() const 514 { 515 return mCur->ref(); 516 } 517 518 EventMapList::iterator& 519 operator++() 520 { 521 EventMapRecord* aPrev = mCur; 522 do { 523 mCur = mCur->mNext; 524 } while (mCur && !mCur->mAlive); 525 526 // now we can safely release previous element 527 aPrev->release(); 528 529 // And grab the new current 530 if (mCur) 531 mCur->addRef(); 532 533 return *this; 534 } 535 536 bool 537 operator==(const EventMapList::iterator& aOther) const 538 { 539 return mCur == aOther.mCur; 540 } 541 542 bool 543 operator!=(const EventMapList::iterator& aOther) const 544 { 545 return mCur != aOther.mCur; 546 } 547 }; 548 549 iterator begin() 550 { 551 return iterator(mHead); 552 } 553 554 iterator end() 555 { 556 return iterator(0); 557 } 558 }; 559 560 typedef EventMapList EventMap[NumEvents]; 354 561 typedef std::map<IEvent*, int32_t> PendingEventsMap; 355 562 typedef std::deque<ComPtr<IEvent> > PassiveQueue; … … 394 601 }; 395 602 396 /* Handy class with semantics close to ComPtr, but for ListenerRecord */ 397 class ListenerRecordHolder 603 /* Handy class with semantics close to ComPtr, but for list records */ 604 template<typename Held> 605 class RecordHolder 398 606 { 399 607 public: 400 ListenerRecordHolder(ListenerRecord* lr)608 RecordHolder(Held* lr) 401 609 : 402 610 held(lr) … … 404 612 addref(); 405 613 } 406 ListenerRecordHolder(const ListenerRecordHolder& that)614 RecordHolder(const RecordHolder& that) 407 615 : 408 616 held(that.held) … … 410 618 addref(); 411 619 } 412 ListenerRecordHolder()620 RecordHolder() 413 621 : 414 622 held(0) 415 623 { 416 624 } 417 ~ ListenerRecordHolder()625 ~RecordHolder() 418 626 { 419 627 release(); 420 628 } 421 629 422 ListenerRecord* obj()630 Held* obj() 423 631 { 424 632 return held; 425 633 } 426 634 427 ListenerRecordHolder &operator=(const ListenerRecordHolder &that)635 RecordHolder &operator=(const RecordHolder &that) 428 636 { 429 637 safe_assign(that.held); … … 431 639 } 432 640 private: 433 ListenerRecord* held;641 Held* held; 434 642 435 643 void addref() … … 443 651 held->release(); 444 652 } 445 void safe_assign ( ListenerRecord *that_p)653 void safe_assign (Held *that_p) 446 654 { 447 655 if (that_p) … … 452 660 }; 453 661 454 typedef std::map<IEventListener*, ListenerRecordHolder> Listeners;662 typedef std::map<IEventListener*, RecordHolder<ListenerRecord> > Listeners; 455 663 456 664 struct EventSource::Data … … 508 716 if (implies(interested, candidate)) 509 717 { 510 (*aEvMap)[j - FirstEvent]. push_back(this);718 (*aEvMap)[j - FirstEvent].add(this); 511 719 } 512 720 } … … 605 813 AssertMsg(!mActive, ("must be passive\n")); 606 814 815 // retain listener record 816 RecordHolder<ListenerRecord> holder(this); 817 607 818 ::RTCritSectEnter(&mcsQLock); 608 if (mQueue.empty()) 609 { 610 // retain listener record 611 ListenerRecordHolder holder(this); 819 if (mQueue.empty()) { 612 820 ::RTCritSectLeave(&mcsQLock); 613 821 // Speed up common case … … 708 916 709 917 com::SafeArray<VBoxEventType_T> interested(ComSafeArrayInArg (aInterested)); 710 ListenerRecordHolderlrh(new ListenerRecord(aListener, interested, aActive, this));918 RecordHolder<ListenerRecord> lrh(new ListenerRecord(aListener, interested, aActive, this)); 711 919 m->mListeners.insert(Listeners::value_type(aListener, lrh)); 712 920 } … … 776 984 AssertComRCReturn(hrc, VERR_ACCESS_DENIED); 777 985 778 std::list<ListenerRecord*>& listeners = m->mEvMap[(int)evType-FirstEvent];986 EventMapList& listeners = m->mEvMap[(int)evType-FirstEvent]; 779 987 780 988 /* Anyone interested in this event? */ … … 795 1003 pit = m->mPendingMap.find(aEvent); 796 1004 } 797 for( std::list<ListenerRecord*>::const_iterator it = listeners.begin();1005 for(EventMapList::iterator it = listeners.begin(); 798 1006 it != listeners.end(); ++it) 799 1007 { 800 1008 HRESULT cbRc; 801 1009 // keep listener record reference, in case someone will remove it while in callback 802 ListenerRecordHolderrecord(*it);1010 RecordHolder<ListenerRecord> record(*it); 803 1011 804 1012 /**
Note:
See TracChangeset
for help on using the changeset viewer.