VirtualBox

Changeset 31589 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Aug 11, 2010 11:04:33 PM (14 years ago)
Author:
vboxsync
Message:

EventQueue: windows fixes.

File:
1 edited

Legend:

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

    r31579 r31589  
    11/* $Id$ */
    2 
    32/** @file
    4  *
    53 * MS COM / XPCOM Abstraction Layer:
    64 * Event and EventQueue class declaration
     
    4442#ifndef VBOX_WITH_XPCOM
    4543
    46 #define CHECK_THREAD_RET(ret) \
     44# define CHECK_THREAD_RET(ret) \
    4745    do { \
    4846        AssertMsg(GetCurrentThreadId() == mThreadId, ("Must be on event queue thread!")); \
     
    5149    } while (0)
    5250
     51/** Magic LPARAM value for the WM_USER messages that we're posting. */
     52# if ARCH_BITS == 64
     53#  define EVENTQUEUE_WIN_LPARAM_MAGIC   UINT64_C(0xf241b8196623bb4c)
     54# else
     55#  define EVENTQUEUE_WIN_LPARAM_MAGIC   UINT32_C(0xf241b819)
     56# endif
     57
     58
    5359#else // VBOX_WITH_XPCOM
    5460
    55 #define CHECK_THREAD_RET(ret) \
     61# define CHECK_THREAD_RET(ret) \
    5662    do { \
    5763        if (!mEventQ) \
     
    6672#endif // VBOX_WITH_XPCOM
    6773
    68 EventQueue *EventQueue::mMainQueue = NULL;
     74/** Pointer to the main event queue. */
     75EventQueue *EventQueue::sMainQueue = NULL;
     76
    6977
    7078#ifdef VBOX_WITH_XPCOM
     79
    7180struct MyPLEvent : public PLEvent
    7281{
     
    128137#else // VBOX_WITH_XPCOM
    129138
    130     mEQCreated = FALSE;
    131     mInterrupted = FALSE;
     139    mEQCreated = false;
     140    mInterrupted = false;
    132141
    133142    // Here we reference the global nsIEventQueueService instance and hold it
     
    154163            if (NS_SUCCEEDED(rc))
    155164            {
    156                 mEQCreated = TRUE;
     165                mEQCreated = true;
    157166                rc = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
    158167                                                         getter_AddRefs(mEventQ));
     
    202211int EventQueue::init()
    203212{
    204     Assert(mMainQueue == NULL);
     213    Assert(sMainQueue == NULL);
    205214    Assert(RTThreadIsMain(RTThreadSelf()));
    206     mMainQueue = new EventQueue();
     215    sMainQueue = new EventQueue();
    207216
    208217#ifdef VBOX_WITH_XPCOM
     
    212221    nsresult rv = NS_GetMainEventQ(getter_AddRefs(q));
    213222    Assert(NS_SUCCEEDED(rv));
    214     Assert(q == mMainQueue->mEventQ);
     223    Assert(q == sMainQueue->mEventQ);
    215224
    216225    /* Check that it's a native queue. */
    217226    PRBool fIsNative = PR_FALSE;
    218     rv = mMainQueue->mEventQ->IsQueueNative(&fIsNative);
     227    rv = sMainQueue->mEventQ->IsQueueNative(&fIsNative);
    219228    Assert(NS_SUCCEEDED(rv) && fIsNative);
    220229#endif // VBOX_WITH_XPCOM
     
    230239int EventQueue::uninit()
    231240{
    232     Assert(mMainQueue);
     241    Assert(sMainQueue);
    233242    /* Must process all events to make sure that no NULL event is left
    234      * after this point. It would need to modify the state of mMainQueue. */
    235     mMainQueue->processEventQueue(0);
    236     delete mMainQueue;
    237     mMainQueue = NULL;
     243     * after this point. It would need to modify the state of sMainQueue. */
     244    sMainQueue->processEventQueue(0);
     245    delete sMainQueue;
     246    sMainQueue = NULL;
    238247    return VINF_SUCCESS;
    239248}
     
    247256EventQueue* EventQueue::getMainEventQueue()
    248257{
    249     return mMainQueue;
     258    return sMainQueue;
    250259}
    251260
     
    253262# ifdef RT_OS_DARWIN
    254263/**
    255  *  Wait for events and process them (Darwin).
    256  *
    257  *  @returns VINF_SUCCESS or VERR_TIMEOUT.
    258  *
    259  *  @param  cMsTimeout      How long to wait, or RT_INDEFINITE_WAIT.
    260  */
    261 static int
    262 waitForEventsOnDarwin(unsigned cMsTimeout)
     264 * Wait for events and process them (Darwin).
     265 *
     266 * @retval  VINF_SUCCESS
     267 * @retval  VERR_TIMEOUT
     268 * @retval  VERR_INTERRUPTED
     269 *
     270 * @param   cMsTimeout      How long to wait, or RT_INDEFINITE_WAIT.
     271 */
     272static int waitForEventsOnDarwin(RTMSINTERVAL cMsTimeout)
    263273{
    264274    /*
     
    287297
    288298/**
    289  *  Wait for events (generic XPCOM).
    290  *
    291  *  @returns VINF_SUCCESS or VERR_TIMEOUT.
    292  *
    293  *  @param  pQueue          The queue to wait on.
    294  *  @param  cMsTimeout      How long to wait, or RT_INDEFINITE_WAIT.
    295  */
    296 static
    297 int waitForEventsOnXPCOM(nsIEventQueue *pQueue, unsigned cMsTimeout)
     299 * Wait for events (generic XPCOM).
     300 *
     301 * @retval  VINF_SUCCESS
     302 * @retval  VERR_TIMEOUT
     303 * @retval  VERR_INTERRUPTED
     304 * @retval  VERR_INTERNAL_ERROR_4
     305 *
     306 * @param   pQueue          The queue to wait on.
     307 * @param   cMsTimeout      How long to wait, or RT_INDEFINITE_WAIT.
     308 */
     309static int waitForEventsOnXPCOM(nsIEventQueue *pQueue, RTMSINTERVAL cMsTimeout)
    298310{
    299311    int     fd = pQueue->GetEventQueueSelectFD();
     
    334346
    335347#ifndef VBOX_WITH_XPCOM
    336 /**
    337  *  Process pending events (Windows).
    338  *  @returns VINF_SUCCESS, VERR_TIMEOUT or VERR_INTERRUPTED.
    339  */
    340 static int
    341 processPendingEvents(void)
    342 {
     348
     349/**
     350 * Dispatch a message on Windows.
     351 *
     352 * This will pick out our events and handle them specially.
     353 *
     354 * @returns @a rc or VERR_INTERRUPTED (WM_QUIT or NULL msg).
     355 * @param   pMsg    The message to dispatch.
     356 * @param   rc      The current status code.
     357 */
     358/*static*/
     359int EventQueue::dispatchMessageOnWindows(MSG const *pMsg, int rc)
     360{
     361    /*
     362     * Check for and dispatch our events.
     363     */
     364    if (   pMsg->hwnd    == NULL
     365        && pMsg->message == WM_USER)
     366    {
     367        if (pMsg->lParam == EVENTQUEUE_WIN_LPARAM_MAGIC)
     368        {
     369            Event *pEvent = (Event *)pMsg->wParam;
     370            if (pEvent)
     371            {
     372                pEvent->handler();
     373                delete pEvent;
     374            }
     375            else
     376                rc = VERR_INTERRUPTED;
     377            return rc;
     378        }
     379        AssertMsgFailed(("lParam=%p wParam=%p\n", pMsg->lParam, pMsg->wParam));
     380    }
     381
     382    /*
     383     * Check for the quit message and dispatch the message the normal way.
     384     */
     385    if (pMsg->message == WM_QUIT)
     386        rc = VERR_INTERRUPTED;
     387    TranslateMessage(pMsg);
     388    DispatchMessage(pMsg);
     389
     390    return rc;
     391}
     392
     393
     394/**
     395 * Process pending events (Windows).
     396 *
     397 * @retval  VINF_SUCCESS
     398 * @retval  VERR_TIMEOUT
     399 * @retval  VERR_INTERRUPTED.
     400 */
     401static int processPendingEvents(void)
     402{
     403    int rc = VERR_TIMEOUT;
    343404    MSG Msg;
    344     int rc = VERR_TIMEOUT;
    345     while (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE))
    346     {
    347         if (Msg.message == WM_QUIT)
    348             rc = VERR_INTERRUPTED;
    349         DispatchMessage(&Msg);
    350         if (rc == VERR_INTERRUPTED)
    351             break;
     405    if (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE))
     406    {
    352407        rc = VINF_SUCCESS;
     408        do
     409            rc = EventQueue::dispatchMessageOnWindows(&Msg, rc);
     410        while (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE));
    353411    }
    354412    return rc;
    355413}
     414
    356415#else // VBOX_WITH_XPCOM
     416
    357417/**
    358418 * Process pending XPCOM events.
     
    360420 * @returns VINF_SUCCESS or VERR_TIMEOUT.
    361421 */
    362 static
    363 int processPendingEvents(nsIEventQueue *pQueue)
     422static int processPendingEvents(nsIEventQueue *pQueue)
    364423{
    365424    /* Check for timeout condition so the caller can be a bit more lazy. */
     
    374433    return VINF_SUCCESS;
    375434}
    376 #endif // VBOX_WITH_XPCOM
    377 
    378 
    379 /**
    380  *  Process events pending on this event queue, and wait up to given timeout, if
    381  *  nothing is available.
    382  *
    383  *  Must be called on same thread this event queue was created on.
    384  *
    385  *  @param cMsTimeout The timeout specified as milliseconds.  Use
    386  *                    RT_INDEFINITE_WAIT to wait till an event is posted on the
    387  *                    queue.
    388  *
    389  *  @returns VBox status code
    390  *  @retval VINF_SUCCESS
    391  *  @retval VERR_TIMEOUT
    392  *  @retval VERR_INVALID_CONTEXT
    393  */
    394 int EventQueue::processEventQueue(uint32_t cMsTimeout)
     435
     436#endif // VBOX_WITH_XPCOM
     437
     438/**
     439 * Process events pending on this event queue, and wait up to given timeout, if
     440 * nothing is available.
     441 *
     442 * Must be called on same thread this event queue was created on.
     443 *
     444 * @param   cMsTimeout  The timeout specified as milliseconds.  Use
     445 *                      RT_INDEFINITE_WAIT to wait till an event is posted on the
     446 *                      queue.
     447 *
     448 * @returns VBox status code
     449 * @retval  VINF_SUCCESS if one or more messages was processed.
     450 * @retval  VERR_TIMEOUT if cMsTimeout expired.
     451 * @retval  VERR_INVALID_CONTEXT if called on the wrong thread.
     452 * @retval  VERR_INTERRUPTED if interruptEventQueueProcessing was called.
     453 *          On Windows will also be returned when WM_QUIT is encountered.
     454 *          On UNIXy systems this may also be returned when a signal is
     455 *          dispatched on the calling thread.
     456 *          On Darwin this may also be returned when the native queue is
     457 *          stopped or destroyed/finished.
     458 * @todo Change this method to use some status other than VERR_INTERRUPTED
     459 *       for indicating harmless interruptions by the system, or some other
     460 *       status for indicating interruptEventQueueProcessing/WM_QUIT.  Maybe
     461 *       VINF_INTERRUPTED for system interruption would be best appropriate.
     462 */
     463int EventQueue::processEventQueue(RTMSINTERVAL cMsTimeout)
    395464{
    396465    int rc;
     
    423492# endif // !RT_OS_DARWIN
    424493    }
    425     if (RT_SUCCESS(rc) && mInterrupted)
     494
     495    if (  (   RT_SUCCESS(rc)
     496           || rc == VERR_INTERRUPTED)
     497        && mInterrupted)
    426498    {
    427499        mInterrupted = false;
     
    432504    if (cMsTimeout == RT_INDEFINITE_WAIT)
    433505    {
    434         BOOL bRet;
    435         MSG Msg;
    436         int rc = VINF_SUCCESS;
    437         while ((bRet = GetMessage(&Msg, NULL /*hWnd*/, WM_USER, WM_USER)))
    438         {
    439             if (bRet != -1)
    440                 DispatchMessage(&Msg);
    441         }
    442         if (bRet == 0)
     506        BOOL fRet;
     507        MSG  Msg;
     508        int  rc = VINF_SUCCESS;
     509        while (   (fRet = GetMessage(&Msg, NULL /*hWnd*/, WM_USER, WM_USER))
     510               && fRet != -1
     511               && rc != VERR_INTERRUPTED)
     512            rc = EventQueue::dispatchMessageOnWindows(&Msg, rc);
     513        if (fRet == 0)
    443514            rc = VERR_INTERRUPTED;
     515        else if (fRet == -1)
     516            rc = RTErrConvertFromWin32(GetLastError());
    444517    }
    445518    else
     
    447520        rc = processPendingEvents();
    448521        if (   rc == VERR_TIMEOUT
    449             || cMsTimeout == 0)
     522            && cMsTimeout != 0)
    450523        {
    451524            DWORD rcW = MsgWaitForMultipleObjects(1,
     
    461534    }
    462535#endif // !VBOX_WITH_XPCOM
     536
    463537    return rc;
    464538}
    465539
    466540/**
    467  *  Interrupt thread waiting on event queue processing.
    468  *
    469  *  Can be called on any thread.
     541 * Interrupt thread waiting on event queue processing.
     542 *
     543 * Can be called on any thread.
     544 *
     545 * @returns VBox status code.
    470546 */
    471547int EventQueue::interruptEventQueueProcessing()
    472548{
    473     /* Send a NULL event. This gets us out of the event loop on XPCOM, and
    474      * doesn't hurt on Windows. It is the responsibility of the caller to
     549    /* Send a NULL event. This event will be picked up and handled specially
     550     * both for XPCOM and Windows. It is the responsibility of the caller to
    475551     * take care of not running the loop again in a way which will hang. */
    476552    postEvent(NULL);
     
    488564#ifndef VBOX_WITH_XPCOM
    489565
    490     return PostThreadMessage(mThreadId, WM_USER, (WPARAM)event, NULL);
     566    return PostThreadMessage(mThreadId, WM_USER, (WPARAM)event, EVENTQUEUE_WIN_LPARAM_MAGIC);
    491567
    492568#else // VBOX_WITH_XPCOM
Note: See TracChangeset for help on using the changeset viewer.

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