VirtualBox

Changeset 22911 in vbox for trunk/src/VBox/Main/glue


Ignore:
Timestamp:
Sep 10, 2009 12:02:36 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
52173
Message:

event queues cleaned up

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/glue/EventQueue.cpp

    r22849 r22911  
    179179timedWaitForEventsOnDarwin(nsIEventQueue *pQueue, PRInt32 cMsTimeout)
    180180{
    181   // This deals with the common case where the caller is the main
    182   // application thread and the queue is a native one.
    183181  OSStatus       orc       = -1;
    184182  CFTimeInterval rdTimeout = (double)cMsTimeout / 1000;
     
    200198#ifdef RT_OS_WINDOWS
    201199static int
    202 processPendingEventsOnWindows()
     200processPendingEvents()
    203201{
    204202    MSG Msg;
     
    211209        if (rc == VERR_INTERRUPTED)
    212210            break;
    213         rc = VINF_SUCCESS; 
     211        rc = VINF_SUCCESS;
    214212    }   
    215213    return rc;
     
    239237  }
    240238};
    241 #endif
    242 #include <stdio.h>
     239#else
     240static int
     241processPendingEvents(nsIEventQueue* pQueue)
     242{
     243  /** @todo: rethink interruption events, current NULL event approach is bad */
     244  pQueue->ProcessPendingEvents();
     245  return VINF_SUCCESS;
     246}
     247#endif
    243248int EventQueue::processEventQueue(uint32_t cMsTimeout)
    244249{
    245250    int rc = VINF_SUCCESS;
     251    /** @todo: check that current thread == one we were created on */
    246252#if defined (VBOX_WITH_XPCOM)
    247253    do {
     
    249255      nsresult rc;
    250256     
    251       rc = mEventQ->PendingEvents(&fHasEvents);
     257      rc = mEventQ->PendingEvents(&fHasEvents);     
    252258      if (NS_FAILED (rc))
    253259          return VERR_INTERNAL_ERROR_3;
     
    305311    } while (0);
    306312
    307     mEventQ->ProcessPendingEvents();
     313    rc = processPendingEvents(mEventQ);
    308314#else /* Windows */
    309315    do {
     
    342348    } while (0);
    343349
    344     processPendingEventsOnWindows();
     350    rc = processPendingEvents();
    345351#endif
    346352    return rc;
    347 
    348353}
    349354
    350355int EventQueue::interruptEventQueueProcessing()
    351356{
     357    /** @todo: rethink me! */
    352358    postEvent(NULL);
    353359    return VINF_SUCCESS;
     
    469475}
    470476
    471 
     477int  EventQueue::getSelectFD()
     478{
    472479#ifdef VBOX_WITH_XPCOM
    473 
    474 /** Wrapper around nsIEventQueue::PendingEvents. */
    475 DECLINLINE(bool) hasEventQueuePendingEvents(nsIEventQueue *pQueue)
    476 {
    477     PRBool fHasEvents = PR_FALSE;
    478     nsresult rc = pQueue->PendingEvents(&fHasEvents);
    479     return NS_SUCCEEDED(rc) && fHasEvents ? true : false;
    480 }
    481 
    482 /** Wrapper around nsIEventQueue::IsQueueNative. */
    483 DECLINLINE(bool) isEventQueueNative(nsIEventQueue *pQueue)
    484 {
    485     PRBool fIsNative = PR_FALSE;
    486     nsresult rc = pQueue->IsQueueNative(&fIsNative);
    487     return NS_SUCCEEDED(rc) && fIsNative ? true : false;
    488 }
    489 
    490 /** Wrapper around nsIEventQueue::ProcessPendingEvents. */
    491 DECLINLINE(void) processPendingEvents(nsIEventQueue *pQueue)
    492 {
    493     pQueue->ProcessPendingEvents();
    494 }
    495 
    496 #else
    497 
    498 /** COM version of nsIEventQueue::PendingEvents. */
    499 DECLINLINE(bool) hasEventQueuePendingEvents(MyThreadHandle &Handle)
    500 {
    501     DWORD rc = MsgWaitForMultipleObjects(1, &Handle.mh, TRUE /*fWaitAll*/, 0 /*ms*/, QS_ALLINPUT);
    502     return rc == WAIT_OBJECT_0;
    503 }
    504 
    505 /** COM version of nsIEventQueue::IsQueueNative, the question doesn't make
    506  *  sense and we have to return false for the code below to work. */
    507 DECLINLINE(bool) isEventQueueNative(MyThreadHandle const &Handle)
    508 {
    509     return false;
    510 }
    511 
    512 /** COM version of nsIEventQueue::ProcessPendingEvents. */
    513 static void processPendingEvents(MyThreadHandle const &Handle)
    514 {
    515     /*
    516      * Process pending thead messages.
    517      */
    518     MSG Msg;
    519     while (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE))
    520     {
    521         if (Msg.message == WM_QUIT)
    522             return /*VERR_INTERRUPTED*/;
    523         DispatchMessage(&Msg);
    524     }
    525 }
    526 
    527 #endif /* VBOX_WITH_XPCOM */
    528 
    529 /**
    530  *  Processes events for the current thread.
    531  *
    532  *  @param cMsTimeout       The timeout in milliseconds or RT_INDEFINITE_WAIT.
    533  *  @param pfnExitCheck     Optional callback for checking for some exit condition
    534  *                          while looping.  Note that this may be called
    535  *  @param pvUser           User argument for pfnExitCheck.
    536  *  @param cMsPollInterval  The interval cMsTimeout should be called at. 0 means
    537  *                          never default.
    538  *  @param fReturnOnEvent   If true, return immediately after some events has
    539  *                          been processed. If false, process events until we
    540  *                          time out, pfnExitCheck returns true, interrupted or
    541  *                          the queue receives some kind of quit message.
    542  *
    543  *  @returns VBox status code.
    544  *  @retval VINF_SUCCESS if events were processed.
    545  *  @retval VERR_TIMEOUT if no events before cMsTimeout elapsed.
    546  *  @retval VERR_INTERRUPTED if the wait was interrupted by a signal or other
    547  *          async event.
    548  *  @retval VERR_NOT_FOUND if the thread has no event queue.
    549  *  @retval VERR_CALLBACK_RETURN if the callback indicates return.
    550  *
    551  *  @todo This is just a quick approximation of what we need. Feel free to
    552  *        improve the interface and make it fit better in with the EventQueue
    553  *        class.
    554  */
    555 /*static*/ int
    556 EventQueue::processThreadEventQueue(uint32_t cMsTimeout, bool (*pfnExitCheck)(void *pvUser) /*= 0*/,
    557                                     void *pvUser /*= 0*/, uint32_t cMsPollInterval /*= 1000*/,
    558                                     bool fReturnOnEvent /*= true*/)
    559 {
    560     uint64_t const StartMsTS = RTTimeMilliTS();
    561 
    562     /* set default. */
    563     if (cMsPollInterval == 0)
    564         cMsPollInterval = 1000;
    565 
    566     /*
    567      * Get the event queue / thread.
    568      */
    569 #ifdef VBOX_WITH_XPCOM
    570     nsCOMPtr<nsIEventQueue> q;
    571     nsresult rv = NS_GetCurrentEventQ(getter_AddRefs(q));
    572     if (NS_FAILED(rv))
    573         return VERR_NOT_FOUND;
    574 #else
    575     MyThreadHandle q;
    576 #endif
    577 
    578     /*
    579      * Check for pending before setting up the wait.
    580      */
    581     if (    !hasEventQueuePendingEvents(q)
    582         ||  !fReturnOnEvent)
    583     {
    584         bool fIsNative = isEventQueueNative(q);
    585         if (    fIsNative
    586             ||  cMsTimeout != RT_INDEFINITE_WAIT
    587             ||  pfnExitCheck
    588             ||  !fReturnOnEvent /** @todo !fReturnOnEvent and cMsTimeout RT_INDEFINITE_WAIT can be handled in else */)
    589         {
    590 #ifdef USE_XPCOM_QUEUE
    591             int const fdQueue = fIsNative ? q->GetEventQueueSelectFD() : -1;
    592             if (fIsNative && fdQueue == -1)
    593                 return VERR_INTERNAL_ERROR_4;
    594 #endif
    595             for (;;)
    596             {
    597                 /*
    598                  * Check for events.
    599                  */
    600                 if (hasEventQueuePendingEvents(q))
    601                 {
    602                     if (fReturnOnEvent)
    603                         break;
    604                     processPendingEvents(q);
    605                 }
    606 
    607                 /*
    608                  * Check the user exit.
    609                  */
    610                 if (   pfnExitCheck
    611                     && pfnExitCheck(pvUser))
    612                     return VERR_CALLBACK_RETURN;
    613 
    614                 /*
    615                  * Figure out how much we have left to wait and if we've timed out already.
    616                  */
    617                 uint32_t cMsLeft;
    618                 if (cMsTimeout == RT_INDEFINITE_WAIT)
    619                     cMsLeft = RT_INDEFINITE_WAIT;
    620                 else
    621                 {
    622                     uint64_t cMsElapsed = RTTimeMilliTS() - StartMsTS;
    623                     if (cMsElapsed >= cMsTimeout)
    624                         break; /* timeout */
    625                     cMsLeft = cMsTimeout - (uint32_t)cMsElapsed;
    626                 }
    627 
    628                 /*
    629                  * Wait in a queue & platform specific manner.
    630                  */
    631 #ifdef VBOX_WITH_XPCOM
    632                 if (!fIsNative)
    633                     RTThreadSleep(250 /*ms*/);
    634                 else
    635                 {
    636 # ifdef USE_XPCOM_QUEUE
    637                     fd_set fdset;
    638                     FD_ZERO(&fdset);
    639                     FD_SET(fdQueue, &fdset);
    640                     struct timeval tv;
    641                     if (    cMsLeft == RT_INDEFINITE_WAIT
    642                         ||  cMsLeft >= cMsPollInterval)
    643                     {
    644                         tv.tv_sec = cMsPollInterval / 1000;
    645                         tv.tv_usec = (cMsPollInterval % 1000) * 1000;
    646                     }
    647                     else
    648                     {
    649                         tv.tv_sec = cMsLeft / 1000;
    650                         tv.tv_usec = (cMsLeft % 1000) * 1000;
    651                     }
    652                     int prc = select(fdQueue + 1, &fdset, NULL, NULL, &tv);
    653                     if (prc == -1)
    654                         return RTErrConvertFromErrno(errno);
    655 
    656 # elif defined(RT_OS_DARWIN)
    657                     CFTimeInterval rdTimeout = (double)RT_MIN(cMsLeft, cMsPollInterval) / 1000;
    658                     OSStatus orc = CFRunLoopRunInMode(kCFRunLoopDefaultMode, rdTimeout, true /*returnAfterSourceHandled*/);
    659                     if (orc == kCFRunLoopRunHandledSource)
    660                         orc = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, false /*returnAfterSourceHandled*/);
    661                     if (   orc != 0
    662                         && orc != kCFRunLoopRunHandledSource
    663                         && orc != kCFRunLoopRunTimedOut)
    664                         return orc == kCFRunLoopRunStopped || orc == kCFRunLoopRunFinished
    665                              ? VERR_INTERRUPTED
    666                              : RTErrConvertFromDarwin(orc);
    667 # else
    668 #  warning "PORTME:"
    669                     RTThreadSleep(250);
    670 # endif
    671                 }
    672 
    673 #else  /* !VBOX_WITH_XPCOM */
    674                 DWORD rc = MsgWaitForMultipleObjects(1, &q.mh, TRUE /*fWaitAll*/, RT_MIN(cMsLeft, cMsPollInterval), QS_ALLINPUT);
    675                 if (rc == WAIT_OBJECT_0)
    676                 {
    677                     if (fReturnOnEvent)
    678                         break;
    679                     processPendingEvents(q);
    680                 }
    681                 else if (rc == WAIT_FAILED)
    682                     return RTErrConvertFromWin32(GetLastError());
    683                 else if (rc != WAIT_TIMEOUT)
    684                     return VERR_INTERNAL_ERROR_4;
    685 #endif /* !VBOX_WITH_XPCOM */
    686             } /* for (;;) */
    687         }
    688         else
    689         {
    690             /*
    691              * Indefinite wait without any complications.
    692              */
    693 #ifdef VBOX_WITH_XPCOM
    694             PLEvent *pEvent = NULL;
    695             rv = q->WaitForEvent(&pEvent);
    696             if (NS_FAILED(rv))
    697                 return VERR_INTERRUPTED;
    698             q->HandleEvent(pEvent);
    699 #else
    700             DWORD rc = MsgWaitForMultipleObjects(1, &q.mh, TRUE /*fWaitAll*/, INFINITE, QS_ALLINPUT);
    701             if (rc != WAIT_OBJECT_0)
    702             {
    703                 if (rc == WAIT_FAILED)
    704                     return RTErrConvertFromWin32(GetLastError());
    705                 return VERR_INTERNAL_ERROR_3;
    706             }
    707 #endif
    708         }
    709     }
    710 
    711     /*
    712      * We have/had events in the queue. Process pending events and
    713      * return successfully.
    714      */
    715     processPendingEvents(q);
    716 
    717     return VINF_SUCCESS;
     480    return mEventQ->GetEventQueueSelectFD();
     481#else
     482    return -1;
     483#endif
    718484}
    719485}
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette