VirtualBox

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


Ignore:
Timestamp:
Sep 8, 2009 8:37:54 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
52083
Message:

Python, COM glue: event processing API

Location:
trunk/src/VBox/Main/glue
Files:
2 edited

Legend:

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

    r22722 r22847  
    6969
    7070#endif // !defined (RT_OS_WINDOWS)
     71
     72EventQueue* EventQueue::mMainQueue = NULL;
    7173
    7274/**
     
    146148}
    147149
     150/* static */ int EventQueue::init()
     151{
     152    mMainQueue = new EventQueue();
     153#if defined (VBOX_WITH_XPCOM)
     154    nsCOMPtr<nsIEventQueue> q;
     155    nsresult rv = NS_GetMainEventQ(getter_AddRefs(q));
     156    Assert(NS_SUCCEEDED(rv));
     157    Assert(q == mMainQueue->mEventQ);
     158    PRBool fIsNative = PR_FALSE;
     159    rv = mMainQueue->mEventQ->IsQueueNative(&fIsNative);
     160    Assert(NS_SUCCEEDED(rv) && fIsNative);
     161#endif
     162    return VINF_SUCCESS;
     163}
     164
     165/* static */ int EventQueue::deinit()
     166{
     167    delete mMainQueue;
     168    mMainQueue = NULL;
     169    return VINF_SUCCESS;
     170}
     171
     172/* static */ EventQueue* EventQueue::getMainEventQueue()
     173{
     174    return mMainQueue;
     175}
     176
     177#ifdef RT_OS_DARWIN
     178static int
     179timedWaitForEventsOnDarwin(nsIEventQueue *pQueue, PRInt32 cMsTimeout)
     180{
     181  // This deals with the common case where the caller is the main
     182  // application thread and the queue is a native one.
     183  OSStatus       orc       = -1;
     184  CFTimeInterval rdTimeout = (double)cMsTimeout / 1000;
     185  orc = CFRunLoopRunInMode(kCFRunLoopDefaultMode, rdTimeout, true /*returnAfterSourceHandled*/);
     186  if (orc == kCFRunLoopRunHandledSource)
     187    orc = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, false /*returnAfterSourceHandled*/);
     188  if (!orc || orc == kCFRunLoopRunHandledSource)
     189    return VINF_SUCCESS;
     190
     191  if (orc != kCFRunLoopRunTimedOut)
     192  {
     193      NS_WARNING("Unexpected status code from CFRunLoopRunInMode");
     194  }
     195
     196  return VERR_TIMEOUT;
     197}
     198#endif
     199
     200#ifdef RT_OS_WINDOWS
     201static int
     202processPendingEventsOnWindows()
     203{
     204    MSG Msg;
     205    int rc = VERR_TIMEOUT;
     206    while (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE))
     207    {
     208        if (Msg.message == WM_QUIT)
     209            rc = VERR_INTERRUPTED;
     210        DispatchMessage(&Msg);
     211        if (rc == VERR_INTERRUPTED)
     212            break;
     213        rc = VINF_SUCCESS;
     214    }   
     215    return rc;
     216}
     217/** For automatic cleanup,   */
     218class MyThreadHandle
     219{
     220public:
     221  HANDLE mh;
     222 
     223  MyThreadHandle()
     224  {
     225    if (!DuplicateHandle(GetCurrentProcess(),
     226                         GetCurrentThread(),
     227                         GetCurrentProcess(),
     228                         &mh,
     229                         0 /*dwDesiredAccess*/,
     230                         FALSE /*bInheritHandle*/,
     231                         DUPLICATE_SAME_ACCESS))
     232      mh = INVALID_HANDLE_VALUE;
     233  }
     234
     235  ~MyThreadHandle()
     236  {
     237    CloseHandle(mh);
     238    mh = INVALID_HANDLE_VALUE;
     239  }
     240};
     241#endif
     242#include <stdio.h>
     243int EventQueue::processEventQueue(uint32_t cMsTimeout)
     244{
     245    int rc = VINF_SUCCESS;
     246#if defined (VBOX_WITH_XPCOM)
     247    do {
     248      PRBool fHasEvents = PR_FALSE;
     249      nsresult rc;
     250     
     251      rc = mEventQ->PendingEvents(&fHasEvents);
     252      if (NS_FAILED (rc))
     253          return VERR_INTERNAL_ERROR_3;
     254
     255      if (fHasEvents || cMsTimeout == 0)
     256          break;
     257
     258      /**
     259       * Unfortunately, WaitForEvent isn't interruptible with Ctrl-C,
     260       * while select() is.
     261       */
     262
     263      if (cMsTimeout == RT_INDEFINITE_WAIT)
     264      {
     265#if 0
     266          PLEvent *pEvent = NULL;
     267          int rc1 = mEventQ->WaitForEvent(&pEvent);
     268          if (NS_FAILED(rc1) || pEvent == NULL)
     269          {
     270                rc = VERR_INTERRUPTED;
     271                break;
     272          }
     273          mEventQ->HandleEvent(pEvent);
     274          break;
     275#else
     276          /* Pretty close to forever */
     277          cMsTimeout = 0xffff0000;
     278#endif
     279      }
     280     
     281      /* Bit tricky part - perform timed wait */
     282#  ifdef RT_OS_DARWIN
     283      rc = timedWaitForEventsOnDarwin(mEventQ, cMsTimeout);
     284#  else
     285      int fd = mEventQ->GetEventQueueSelectFD();
     286      fd_set fdsetR, fdsetE;
     287      struct timeval tv;
     288     
     289      FD_ZERO(&fdsetR);
     290      FD_SET(fd, &fdsetR);
     291     
     292      fdsetE = fdsetR;
     293      tv.tv_sec = (PRInt64)cMsTimeout / 1000;
     294      tv.tv_usec = ((PRInt64)cMsTimeout % 1000) * 1000;
     295
     296      int aCode = select(fd + 1, &fdsetR, NULL, &fdsetE, &tv);
     297      if (aCode == 0)
     298        rc = VERR_TIMEOUT;
     299      else if (aCode == EINTR)
     300        rc = VERR_INTERRUPTED;
     301      else if (aCode < 0)
     302        rc = VERR_INTERNAL_ERROR_4;
     303     
     304#  endif     
     305    } while (0);
     306
     307    mEventQ->ProcessPendingEvents();
     308#else /* Windows */
     309    do {
     310        int aCode = processPendingEventsOnWindows();
     311        if (aCode != VERR_TIMEOUT || cMsTimeout == 0)
     312        {
     313            rc = aCode;
     314            break;
     315        }
     316       
     317        if (cMsTimeout == RT_INDEFINITE_WAIT)
     318        {
     319            Event* aEvent = NULL;
     320         
     321            fHasEvent = waitForEvent(&aEvent);
     322            if (fHasEvent)
     323              handleEvent(aEvent);
     324            else
     325              rc = VERR_INTERRUPTED;
     326            break;
     327        }
     328
     329        /* Perform timed wait */
     330        MyThreadHandle aHandle;
     331
     332        DWORD aCode = MsgWaitForMultipleObjects(1, &aHandle.mh,
     333                                             TRUE /*fWaitAll*/,
     334                                             0 /*ms*/,
     335                                             QS_ALLINPUT);
     336        if (aCode == WAIT_TIMEOUT)
     337            rc = VERR_TIMEOUT;
     338        else if (aCode == WAIT_OBJECT_0)
     339            rc = VINF_SUCCESS;
     340        else
     341            rc = VERR_INTERNAL_ERROR_4;
     342    } while (0);
     343
     344    processPendingEventsOnWindows();
     345#endif
     346    return rc;
     347
     348}
     349
     350int EventQueue::interruptEventQueueProcessing()
     351{
     352    postEvent(NULL);
     353    return VINF_SUCCESS;
     354}
     355
    148356/**
    149357 *  Posts an event to this event loop asynchronously.
     
    287495
    288496#else
    289 
    290 /** For automatic cleanup.  */
    291 class MyThreadHandle
    292 {
    293 public:
    294     HANDLE mh;
    295 
    296     MyThreadHandle(HANDLE hThread)
    297     {
    298         if (!DuplicateHandle(GetCurrentProcess(), hThread, GetCurrentProcess(),
    299                              &mh, 0 /*dwDesiredAccess*/, FALSE /*bInheritHandle*/,
    300                              DUPLICATE_SAME_ACCESS))
    301             mh = INVALID_HANDLE_VALUE;
    302     }
    303 
    304     ~MyThreadHandle()
    305     {
    306         CloseHandle(mh);
    307         mh = INVALID_HANDLE_VALUE;
    308     }
    309 };
    310497
    311498/** COM version of nsIEventQueue::PendingEvents. */
     
    386573        return VERR_NOT_FOUND;
    387574#else
    388     MyThreadHandle q(GetCurrentThread());
     575    MyThreadHandle q;
    389576#endif
    390577
     
    530717    return VINF_SUCCESS;
    531718}
    532 
    533719}
    534720/* namespace com */
  • trunk/src/VBox/Main/glue/initterm.cpp

    r21878 r22847  
    5353#include "VBox/com/com.h"
    5454#include "VBox/com/assert.h"
     55#include "VBox/com/EventQueue.h"
    5556
    5657#include "../include/Logging.h"
     
    497498    AssertComRC (rc);
    498499
     500    EventQueue::init();
     501
    499502    return rc;
    500503}
     
    503506{
    504507    HRESULT rc = S_OK;
     508
     509    EventQueue::deinit();
    505510
    506511#if !defined (VBOX_WITH_XPCOM)
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