void EventManager<T>::fire(EventPtr ev) { mUnprocessed.push(ev); SILOG(task,debug,"**** Firing event " << (void*)(&(*ev)) << " with " << ev->getId()); if (mEventCV && mEventLock && !mCleanup) { boost::mutex *lock = (boost::mutex *)mEventLock; boost::condition_variable *cv = (boost::condition_variable *)mEventCV; if (++mPendingEvents == 1) { boost::unique_lock<boost::mutex> waitforevent (*lock); // we are the first ones to fire an event. cv->notify_one(); } } };
void EventManager<T>::temporary_processEventQueue(AbsTime forceCompletionBy) { AbsTime startTime = AbsTime::now(); SILOG(task,insane," >>> Processing events."); // swaps to allow people to keep adding new events typename EventList::NodeIterator processingList(mUnprocessed); // The events are swapped first to guarantee that listeners are at least as up-to-date as events. // Events can be delayed, but we cannot allow any lost subscriptions/unsubscriptions. { typename ListenerRequestList::NodeIterator procListeners(mListenerRequests); const ListenerRequest *req; while ((req = procListeners.next()) != NULL) { if (req->subscription) { SILOG(task,debug," >>>\tDoing subscription listener "<< req->listenerId << " for event " << req->eventId << " (" << req->onlyPrimary << ")."); doSubscribeId(*req); } else { SILOGNOCR(task,debug," >>>\t"); if (req->notifyListener) { SILOGNOCR(task,debug,"Notifying"); } SILOG(task,debug,"UNSUBSCRIBED listener " << req->listenerId << "."); doUnsubscribe(req->listenerId, req->notifyListener); } } } if (SILOGP(task,insane)){ SILOG(task,insane,"==== All Event Subscribers for " << (intptr_t)this << " ===="); typename PrimaryListenerMap::const_iterator priIter = mListeners.begin(); while (priIter != mListeners.end()) { SILOG(task,insane," ID " << (*priIter).first << ":"); PartiallyOrderedListenerList *primaryLists = &((*priIter).second->first); SecondaryListenerMap *secondaryMap = &((*priIter).second->second); for (int i = 0; i < NUM_EVENTORDER; i++) { ListenerList *currentList = &(primaryLists->get(i)); for (typename ListenerList::const_iterator iter = currentList->begin(); iter != currentList->end(); ++iter) { SILOG(task,insane," \t" "[" << (i==MIDDLE?'=':i<MIDDLE?'*':'/') << "] " << (*iter).second); } } typename SecondaryListenerMap::const_iterator secIter; secIter = secondaryMap->begin(); while (secIter != secondaryMap->end()) { SILOG(task,insane,"\tSec ID " << (*secIter).first << ":"); for (int i = 0; i < NUM_EVENTORDER; i++) { ListenerList *currentList = &((*secIter).second->get(i)); for (typename ListenerList::const_iterator iter = currentList->begin(); iter != currentList->end(); ++iter) { SILOG(task,insane," \t\t" "[" << (i==MIDDLE?'=':i<MIDDLE?'*':'/') << "] " << (*iter).second); } } ++secIter; } ++priIter; } SILOG(task,insane,"==== ---------------------------------- ===="); } EventPtr *evTemp; int numProcessed = 0; while ((evTemp = processingList.next())!=NULL) { EventPtr ev (*evTemp); ++numProcessed; typename PrimaryListenerMap::iterator priIter = mListeners.find(ev->getId().mPriId); if (priIter == mListeners.end()) { // FIXME: Should this ever happen? SILOG(task,warning," >>>\tWARNING: No listeners for type " << "event type " << ev->getId().mPriId); continue; } PartiallyOrderedListenerList *primaryLists = &((*priIter).second->first); SecondaryListenerMap *secondaryMap = &((*priIter).second->second); typename SecondaryListenerMap::iterator secIter; secIter = secondaryMap->find(ev->getId().mSecId); bool cancel = false; EventHistory eventHistory=EVENT_UNHANDLED; // Call once per event order. for (int i = 0; i < NUM_EVENTORDER && cancel == false; i++) { SILOG(task,debug," >>>\tFiring " << ev << ": " << ev->getId() << " [order " << i << "]"); ListenerList *currentList = &(primaryLists->get(i)); if (!currentList->empty()) eventHistory=EVENT_HANDLED; if (callAllListeners(ev, currentList, forceCompletionBy)) { cancel = cancel || true; } if (secIter != secondaryMap->end() && !(*secIter).second->get(i).empty()) { currentList = &((*secIter).second->get(i)); if (!currentList->empty()) eventHistory=EVENT_HANDLED; if (callAllListeners(ev, currentList, forceCompletionBy)) { cancel = cancel || true; } // all listeners may have returned false. // cleanUp(secondaryMap, secIter); // secIter = secondaryMap->find(ev->getId().mSecId); } if (cancel) { SILOG(task,debug," >>>\tCancelling " << ev->getId()); } } if (secIter != secondaryMap->end()) { cleanUp(secondaryMap, secIter); } if (cancel) eventHistory=EVENT_CANCELED; (*ev)(eventHistory); SILOG(task,debug," >>>\tFinished " << ev->getId()); } if (mEventCV) { mPendingEvents -= numProcessed; } AbsTime finishTime = AbsTime::now(); SILOG(task,insane, "**** Done processing events this round. " << "Took " << (finishTime-startTime).toSeconds() << " seconds."); }