int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID, const GuestEventTypes &lstEvents, GuestWaitEvent **ppEvent) { AssertPtrReturn(ppEvent, VERR_INVALID_POINTER); uint32_t uContextID; int rc = generateContextID(uSessionID, uObjectID, &uContextID); if (RT_FAILURE(rc)) return rc; rc = RTCritSectEnter(&mWaitEventCritSect); if (RT_SUCCESS(rc)) { try { GuestWaitEvent *pEvent = new GuestWaitEvent(uContextID, lstEvents); AssertPtr(pEvent); LogFlowThisFunc(("New event=%p, CID=%RU32\n", pEvent, uContextID)); /* Insert event into matching event group. This is for faster per-group * lookup of all events later. */ for (GuestEventTypes::const_iterator itEvents = lstEvents.begin(); itEvents != lstEvents.end(); itEvents++) { mWaitEventGroups[(*itEvents)].insert( std::pair<uint32_t, GuestWaitEvent*>(uContextID, pEvent)); /** @todo Check for key collision. */ } /* Register event in regular event list. */ /** @todo Check for key collisions. */ mWaitEvents[uContextID] = pEvent; *ppEvent = pEvent; } catch(std::bad_alloc &) { rc = VERR_NO_MEMORY; } int rc2 = RTCritSectLeave(&mWaitEventCritSect); if (RT_SUCCESS(rc)) rc = rc2; } return rc; }
void GuestBase::unregisterWaitEvent(GuestWaitEvent *pEvent) { if (!pEvent) /* Nothing to unregister. */ return; int rc = RTCritSectEnter(&mWaitEventCritSect); if (RT_SUCCESS(rc)) { LogFlowThisFunc(("pEvent=%p\n", pEvent)); const GuestEventTypes lstTypes = pEvent->Types(); for (GuestEventTypes::const_iterator itEvents = lstTypes.begin(); itEvents != lstTypes.end(); itEvents++) { /** @todo Slow O(n) lookup. Optimize this. */ GuestWaitEvents::iterator itCurEvent = mWaitEventGroups[(*itEvents)].begin(); while (itCurEvent != mWaitEventGroups[(*itEvents)].end()) { if (itCurEvent->second == pEvent) { mWaitEventGroups[(*itEvents)].erase(itCurEvent++); break; } else itCurEvent++; } } delete pEvent; pEvent = NULL; int rc2 = RTCritSectLeave(&mWaitEventCritSect); if (RT_SUCCESS(rc)) rc = rc2; } }
int GuestBase::signalWaitEvent(VBoxEventType_T aType, IEvent *aEvent) { int rc = RTCritSectEnter(&mWaitEventCritSect); #ifdef DEBUG uint32_t cEvents = 0; #endif if (RT_SUCCESS(rc)) { GuestEventGroup::iterator itGroup = mWaitEventGroups.find(aType); if (itGroup != mWaitEventGroups.end()) { GuestWaitEvents::iterator itEvents = itGroup->second.begin(); while (itEvents != itGroup->second.end()) { #ifdef DEBUG LogFlowThisFunc(("Signalling event=%p, type=%ld (CID %RU32: Session=%RU32, Object=%RU32, Count=%RU32) ...\n", itEvents->second, aType, itEvents->first, VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(itEvents->first), VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(itEvents->first), VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(itEvents->first))); #endif ComPtr<IEvent> pThisEvent = aEvent; Assert(!pThisEvent.isNull()); int rc2 = itEvents->second->SignalExternal(aEvent); if (RT_SUCCESS(rc)) rc = rc2; if (RT_SUCCESS(rc2)) { /* Remove the event from all other event groups (except the * original one!) because it was signalled. */ AssertPtr(itEvents->second); const GuestEventTypes evTypes = itEvents->second->Types(); for (GuestEventTypes::const_iterator itType = evTypes.begin(); itType != evTypes.end(); itType++) { if ((*itType) != aType) /* Only remove all other groups. */ { /* Get current event group. */ GuestEventGroup::iterator evGroup = mWaitEventGroups.find((*itType)); Assert(evGroup != mWaitEventGroups.end()); /* Lookup event in event group. */ GuestWaitEvents::iterator evEvent = evGroup->second.find(itEvents->first /* Context ID */); Assert(evEvent != evGroup->second.end()); LogFlowThisFunc(("Removing event=%p (type %ld)\n", evEvent->second, (*itType))); evGroup->second.erase(evEvent); LogFlowThisFunc(("%zu events for type=%ld left\n", evGroup->second.size(), aType)); } } /* Remove the event from the passed-in event group. */ itGroup->second.erase(itEvents++); } else itEvents++; #ifdef DEBUG cEvents++; #endif } } int rc2 = RTCritSectLeave(&mWaitEventCritSect); if (RT_SUCCESS(rc)) rc = rc2; } #ifdef DEBUG LogFlowThisFunc(("Signalled %RU32 events, rc=%Rrc\n", cEvents, rc)); #endif return rc; }