summaryrefslogtreecommitdiff
path: root/src/VBox/Main/glue/EventQueue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/glue/EventQueue.cpp')
-rw-r--r--src/VBox/Main/glue/EventQueue.cpp670
1 files changed, 145 insertions, 525 deletions
diff --git a/src/VBox/Main/glue/EventQueue.cpp b/src/VBox/Main/glue/EventQueue.cpp
index d5a09c69..c918c993 100644
--- a/src/VBox/Main/glue/EventQueue.cpp
+++ b/src/VBox/Main/glue/EventQueue.cpp
@@ -1,11 +1,10 @@
/* $Id: EventQueue.cpp $ */
/** @file
- * MS COM / XPCOM Abstraction Layer:
- * Event and EventQueue class declaration
+ * Event queue class declaration.
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -16,23 +15,18 @@
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
-#include "VBox/com/EventQueue.h"
+/** @todo Adapt / update documentation! */
-#ifdef RT_OS_DARWIN
-# include <CoreFoundation/CFRunLoop.h>
-#endif
+#include "VBox/com/EventQueue.h"
-#if defined(VBOX_WITH_XPCOM) && !defined(RT_OS_DARWIN) && !defined(RT_OS_OS2)
-# define USE_XPCOM_QUEUE
-#endif
+#include <iprt/asm.h>
+#include <new> /* For bad_alloc. */
#include <iprt/err.h>
+#include <iprt/semaphore.h>
#include <iprt/time.h>
#include <iprt/thread.h>
#include <iprt/log.h>
-#ifdef USE_XPCOM_QUEUE
-# include <errno.h>
-#endif
namespace com
{
@@ -40,430 +34,33 @@ namespace com
// EventQueue class
////////////////////////////////////////////////////////////////////////////////
-#ifndef VBOX_WITH_XPCOM
-
-# define CHECK_THREAD_RET(ret) \
- do { \
- AssertMsg(GetCurrentThreadId() == mThreadId, ("Must be on event queue thread!")); \
- if (GetCurrentThreadId() != mThreadId) \
- return ret; \
- } while (0)
-
-/** Magic LPARAM value for the WM_USER messages that we're posting.
- * @remarks This magic value is duplicated in
- * vboxapi/PlatformMSCOM::interruptWaitEvents(). */
-#define EVENTQUEUE_WIN_LPARAM_MAGIC UINT32_C(0xf241b819)
-
-
-#else // VBOX_WITH_XPCOM
-
-# define CHECK_THREAD_RET(ret) \
- do { \
- if (!mEventQ) \
- return ret; \
- BOOL isOnCurrentThread = FALSE; \
- mEventQ->IsOnCurrentThread(&isOnCurrentThread); \
- AssertMsg(isOnCurrentThread, ("Must be on event queue thread!")); \
- if (!isOnCurrentThread) \
- return ret; \
- } while (0)
-
-#endif // VBOX_WITH_XPCOM
-
-/** Pointer to the main event queue. */
-EventQueue *EventQueue::sMainQueue = NULL;
-
-
-#ifdef VBOX_WITH_XPCOM
-
-struct MyPLEvent : public PLEvent
-{
- MyPLEvent(Event *e) : event(e) {}
- Event *event;
-};
-
-/* static */
-void *PR_CALLBACK com::EventQueue::plEventHandler(PLEvent *self)
-{
- Event *ev = ((MyPLEvent *)self)->event;
- if (ev)
- ev->handler();
- else
- {
- EventQueue *eq = (EventQueue *)self->owner;
- Assert(eq);
- eq->mInterrupted = true;
- }
- return NULL;
-}
-
-/* static */
-void PR_CALLBACK com::EventQueue::plEventDestructor(PLEvent *self)
-{
- Event *ev = ((MyPLEvent *)self)->event;
- if (ev)
- delete ev;
- delete self;
-}
-
-#endif // VBOX_WITH_XPCOM
-
-/**
- * Constructs an event queue for the current thread.
- *
- * Currently, there can be only one event queue per thread, so if an event
- * queue for the current thread already exists, this object is simply attached
- * to the existing event queue.
- */
-EventQueue::EventQueue()
-{
-#ifndef VBOX_WITH_XPCOM
-
- mThreadId = GetCurrentThreadId();
- // force the system to create the message queue for the current thread
- MSG msg;
- PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
-
- if (!DuplicateHandle(GetCurrentProcess(),
- GetCurrentThread(),
- GetCurrentProcess(),
- &mhThread,
- 0 /*dwDesiredAccess*/,
- FALSE /*bInheritHandle*/,
- DUPLICATE_SAME_ACCESS))
- mhThread = INVALID_HANDLE_VALUE;
-
-#else // VBOX_WITH_XPCOM
-
- mEQCreated = false;
- mInterrupted = false;
-
- // Here we reference the global nsIEventQueueService instance and hold it
- // until we're destroyed. This is necessary to keep NS_ShutdownXPCOM() away
- // from calling StopAcceptingEvents() on all event queues upon destruction of
- // nsIEventQueueService, and makes sense when, for some reason, this happens
- // *before* we're able to send a NULL event to stop our event handler thread
- // when doing unexpected cleanup caused indirectly by NS_ShutdownXPCOM()
- // that is performing a global cleanup of everything. A good example of such
- // situation is when NS_ShutdownXPCOM() is called while the VirtualBox component
- // is still alive (because it is still referenced): eventually, it results in
- // a VirtualBox::uninit() call from where it is already not possible to post
- // NULL to the event thread (because it stopped accepting events).
-
- nsresult rc = NS_GetEventQueueService(getter_AddRefs(mEventQService));
-
- if (NS_SUCCEEDED(rc))
- {
- rc = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
- getter_AddRefs(mEventQ));
- if (rc == NS_ERROR_NOT_AVAILABLE)
- {
- rc = mEventQService->CreateThreadEventQueue();
- if (NS_SUCCEEDED(rc))
- {
- mEQCreated = true;
- rc = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
- getter_AddRefs(mEventQ));
- }
- }
- }
- AssertComRC(rc);
-
-#endif // VBOX_WITH_XPCOM
-}
-
-EventQueue::~EventQueue()
-{
-#ifndef VBOX_WITH_XPCOM
- if (mhThread != INVALID_HANDLE_VALUE)
- {
- CloseHandle(mhThread);
- mhThread = INVALID_HANDLE_VALUE;
- }
-#else // VBOX_WITH_XPCOM
- // process all pending events before destruction
- if (mEventQ)
- {
- if (mEQCreated)
- {
- mEventQ->StopAcceptingEvents();
- mEventQ->ProcessPendingEvents();
- mEventQService->DestroyThreadEventQueue();
- }
- mEventQ = nsnull;
- mEventQService = nsnull;
- }
-#endif // VBOX_WITH_XPCOM
-}
-
-/**
- * Initializes the main event queue instance.
- * @returns VBox status code.
- *
- * @remarks If you're using the rest of the COM/XPCOM glue library,
- * com::Initialize() will take care of initializing and uninitializing
- * the EventQueue class. If you don't call com::Initialize, you must
- * make sure to call this method on the same thread that did the
- * XPCOM initialization or we'll end up using the wrong main queue.
- */
-/* static */
-int EventQueue::init()
+EventQueue::EventQueue(void)
+ : mUserCnt(0),
+ mShutdown(false)
{
- Assert(sMainQueue == NULL);
- Assert(RTThreadIsMain(RTThreadSelf()));
- sMainQueue = new EventQueue();
-
-#ifdef VBOX_WITH_XPCOM
- /* Check that it actually is the main event queue, i.e. that
- we're called on the right thread. */
- nsCOMPtr<nsIEventQueue> q;
- nsresult rv = NS_GetMainEventQ(getter_AddRefs(q));
- Assert(NS_SUCCEEDED(rv));
- Assert(q == sMainQueue->mEventQ);
-
- /* Check that it's a native queue. */
- PRBool fIsNative = PR_FALSE;
- rv = sMainQueue->mEventQ->IsQueueNative(&fIsNative);
- Assert(NS_SUCCEEDED(rv) && fIsNative);
-#endif // VBOX_WITH_XPCOM
-
- return VINF_SUCCESS;
-}
-
-/**
- * Uninitialize the global resources (i.e. the main event queue instance).
- * @returns VINF_SUCCESS
- */
-/* static */
-int EventQueue::uninit()
-{
- if (sMainQueue)
- {
- /* Must process all events to make sure that no NULL event is left
- * after this point. It would need to modify the state of sMainQueue. */
-#ifdef RT_OS_DARWIN /* Do not process the native runloop, the toolkit may not be ready for it. */
- sMainQueue->mEventQ->ProcessPendingEvents();
-#else
- sMainQueue->processEventQueue(0);
-#endif
- delete sMainQueue;
- sMainQueue = NULL;
- }
- return VINF_SUCCESS;
-}
+ int rc = RTCritSectInit(&mCritSect);
+ AssertRC(rc);
-/**
- * Get main event queue instance.
- *
- * Depends on init() being called first.
- */
-/* static */
-EventQueue* EventQueue::getMainEventQueue()
-{
- return sMainQueue;
+ rc = RTSemEventCreate(&mSemEvent);
+ AssertRC(rc);
}
-#ifdef VBOX_WITH_XPCOM
-# ifdef RT_OS_DARWIN
-/**
- * Wait for events and process them (Darwin).
- *
- * @retval VINF_SUCCESS
- * @retval VERR_TIMEOUT
- * @retval VERR_INTERRUPTED
- *
- * @param cMsTimeout How long to wait, or RT_INDEFINITE_WAIT.
- */
-static int waitForEventsOnDarwin(RTMSINTERVAL cMsTimeout)
+EventQueue::~EventQueue(void)
{
- /*
- * Wait for the requested time, if we get a hit we do a poll to process
- * any other pending messages.
- *
- * Note! About 1.0e10: According to the sources anything above 3.1556952e+9
- * means indefinite wait and 1.0e10 is what CFRunLoopRun() uses.
- */
- CFTimeInterval rdTimeout = cMsTimeout == RT_INDEFINITE_WAIT ? 1e10 : (double)cMsTimeout / 1000;
- OSStatus orc = CFRunLoopRunInMode(kCFRunLoopDefaultMode, rdTimeout, true /*returnAfterSourceHandled*/);
- if (orc == kCFRunLoopRunHandledSource)
- {
- OSStatus orc2 = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, false /*returnAfterSourceHandled*/);
- if ( orc2 == kCFRunLoopRunStopped
- || orc2 == kCFRunLoopRunFinished)
- orc = orc2;
- }
- if ( orc == 0 /*???*/
- || orc == kCFRunLoopRunHandledSource)
- return VINF_SUCCESS;
- if ( orc == kCFRunLoopRunStopped
- || orc == kCFRunLoopRunFinished)
- return VERR_INTERRUPTED;
- AssertMsg(orc == kCFRunLoopRunTimedOut, ("Unexpected status code from CFRunLoopRunInMode: %#x", orc));
- return VERR_TIMEOUT;
-}
-# else // !RT_OS_DARWIN
+ int rc = RTCritSectDelete(&mCritSect);
+ AssertRC(rc);
-/**
- * Wait for events (generic XPCOM).
- *
- * @retval VINF_SUCCESS
- * @retval VERR_TIMEOUT
- * @retval VINF_INTERRUPTED
- * @retval VERR_INTERNAL_ERROR_4
- *
- * @param pQueue The queue to wait on.
- * @param cMsTimeout How long to wait, or RT_INDEFINITE_WAIT.
- */
-static int waitForEventsOnXPCOM(nsIEventQueue *pQueue, RTMSINTERVAL cMsTimeout)
-{
- int fd = pQueue->GetEventQueueSelectFD();
- fd_set fdsetR;
- FD_ZERO(&fdsetR);
- FD_SET(fd, &fdsetR);
-
- fd_set fdsetE = fdsetR;
-
- struct timeval tv = {0,0};
- struct timeval *ptv;
- if (cMsTimeout == RT_INDEFINITE_WAIT)
- ptv = NULL;
- else
- {
- tv.tv_sec = cMsTimeout / 1000;
- tv.tv_usec = (cMsTimeout % 1000) * 1000;
- ptv = &tv;
- }
+ rc = RTSemEventDestroy(mSemEvent);
+ AssertRC(rc);
- int rc = select(fd + 1, &fdsetR, NULL, &fdsetE, ptv);
- if (rc > 0)
- rc = VINF_SUCCESS;
- else if (rc == 0)
- rc = VERR_TIMEOUT;
- else if (errno == EINTR)
- rc = VINF_INTERRUPTED;
- else
+ EventQueueListIterator it = mEvents.begin();
+ while (it != mEvents.end())
{
- static uint32_t s_ErrorCount = 0;
- if (s_ErrorCount < 500)
- {
- LogRel(("waitForEventsOnXPCOM rc=%d errno=%d\n", rc, errno));
- ++s_ErrorCount;
- }
-
- AssertMsgFailed(("rc=%d errno=%d\n", rc, errno));
- rc = VERR_INTERNAL_ERROR_4;
+ (*it)->Release();
+ it = mEvents.erase(it);
}
- return rc;
}
-# endif // !RT_OS_DARWIN
-#endif // VBOX_WITH_XPCOM
-
-#ifndef VBOX_WITH_XPCOM
-
-/**
- * Dispatch a message on Windows.
- *
- * This will pick out our events and handle them specially.
- *
- * @returns @a rc or VERR_INTERRUPTED (WM_QUIT or NULL msg).
- * @param pMsg The message to dispatch.
- * @param rc The current status code.
- */
-/*static*/
-int EventQueue::dispatchMessageOnWindows(MSG const *pMsg, int rc)
-{
- /*
- * Check for and dispatch our events.
- */
- if ( pMsg->hwnd == NULL
- && pMsg->message == WM_USER)
- {
- if (pMsg->lParam == EVENTQUEUE_WIN_LPARAM_MAGIC)
- {
- Event *pEvent = (Event *)pMsg->wParam;
- if (pEvent)
- {
- pEvent->handler();
- delete pEvent;
- }
- else
- rc = VERR_INTERRUPTED;
- return rc;
- }
- AssertMsgFailed(("lParam=%p wParam=%p\n", pMsg->lParam, pMsg->wParam));
- }
-
- /*
- * Check for the quit message and dispatch the message the normal way.
- */
- if (pMsg->message == WM_QUIT)
- rc = VERR_INTERRUPTED;
- TranslateMessage(pMsg);
- DispatchMessage(pMsg);
-
- return rc;
-}
-
-
-/**
- * Process pending events (Windows).
- *
- * @retval VINF_SUCCESS
- * @retval VERR_TIMEOUT
- * @retval VERR_INTERRUPTED.
- */
-static int processPendingEvents(void)
-{
- int rc = VERR_TIMEOUT;
- MSG Msg;
- if (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE))
- {
- rc = VINF_SUCCESS;
- do
- rc = EventQueue::dispatchMessageOnWindows(&Msg, rc);
- while (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE));
- }
- return rc;
-}
-
-#else // VBOX_WITH_XPCOM
-
-/**
- * Process pending XPCOM events.
- * @param pQueue The queue to process events on.
- * @retval VINF_SUCCESS
- * @retval VERR_TIMEOUT
- * @retval VERR_INTERRUPTED (darwin only)
- * @retval VERR_INTERNAL_ERROR_2
- */
-static int processPendingEvents(nsIEventQueue *pQueue)
-{
- /* ProcessPendingEvents doesn't report back what it did, so check here. */
- PRBool fHasEvents = PR_FALSE;
- nsresult hr = pQueue->PendingEvents(&fHasEvents);
- if (NS_FAILED(hr))
- return VERR_INTERNAL_ERROR_2;
-
- /* Process pending events. */
- int rc = VINF_SUCCESS;
- if (fHasEvents)
- pQueue->ProcessPendingEvents();
- else
- rc = VERR_TIMEOUT;
-
-# ifdef RT_OS_DARWIN
- /* Process pending native events. */
- int rc2 = waitForEventsOnDarwin(0);
- if (rc == VERR_TIMEOUT || rc2 == VERR_INTERRUPTED)
- rc = rc2;
-# endif
-
- return rc;
-}
-
-#endif // VBOX_WITH_XPCOM
-
/**
* Process events pending on this event queue, and wait up to given timeout, if
* nothing is available.
@@ -489,80 +86,92 @@ static int processPendingEvents(nsIEventQueue *pQueue)
*/
int EventQueue::processEventQueue(RTMSINTERVAL cMsTimeout)
{
- int rc;
- CHECK_THREAD_RET(VERR_INVALID_CONTEXT);
-
-#ifdef VBOX_WITH_XPCOM
- /*
- * Process pending events, if none are available and we're not in a
- * poll call, wait for some to appear. (We have to be a little bit
- * careful after waiting for the events since Darwin will process
- * them as part of the wait, while the XPCOM case will not.)
- *
- * Note! Unfortunately, WaitForEvent isn't interruptible with Ctrl-C,
- * while select() is. So we cannot use it for indefinite waits.
- */
- rc = processPendingEvents(mEventQ);
- if ( rc == VERR_TIMEOUT
- && cMsTimeout > 0)
+ size_t cNumEvents;
+ int rc = RTCritSectEnter(&mCritSect);
+ if (RT_SUCCESS(rc))
{
-# ifdef RT_OS_DARWIN
- /** @todo check how Ctrl-C works on Darwin. */
- rc = waitForEventsOnDarwin(cMsTimeout);
- if (rc == VERR_TIMEOUT)
- rc = processPendingEvents(mEventQ);
-# else // !RT_OS_DARWIN
- rc = waitForEventsOnXPCOM(mEventQ, cMsTimeout);
- if ( RT_SUCCESS(rc)
- || rc == VERR_TIMEOUT)
- rc = processPendingEvents(mEventQ);
-# endif // !RT_OS_DARWIN
- }
+ if (mUserCnt == 0) /* No concurrent access allowed. */
+ {
+ mUserCnt++;
- if ( ( RT_SUCCESS(rc)
- || rc == VERR_INTERRUPTED
- || rc == VERR_TIMEOUT)
- && mInterrupted)
- {
- mInterrupted = false;
- rc = VERR_INTERRUPTED;
- }
+ cNumEvents = mEvents.size();
+ if (!cNumEvents)
+ {
+ int rc2 = RTCritSectLeave(&mCritSect);
+ AssertRC(rc2);
-#else // !VBOX_WITH_XPCOM
- if (cMsTimeout == RT_INDEFINITE_WAIT)
- {
- BOOL fRet;
- MSG Msg;
- rc = VINF_SUCCESS;
- while ( rc != VERR_INTERRUPTED
- && (fRet = GetMessage(&Msg, NULL /*hWnd*/, WM_USER, WM_USER))
- && fRet != -1)
- rc = EventQueue::dispatchMessageOnWindows(&Msg, rc);
- if (fRet == 0)
- rc = VERR_INTERRUPTED;
- else if (fRet == -1)
- rc = RTErrConvertFromWin32(GetLastError());
+ rc = RTSemEventWaitNoResume(mSemEvent, cMsTimeout);
+
+ rc2 = RTCritSectEnter(&mCritSect);
+ AssertRC(rc2);
+
+ if (RT_SUCCESS(rc))
+ {
+ if (mShutdown)
+ rc = VERR_INTERRUPTED;
+ cNumEvents = mEvents.size();
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ rc = processPendingEvents(cNumEvents);
+
+ Assert(mUserCnt);
+ mUserCnt--;
+ }
+ else
+ rc = VERR_WRONG_ORDER;
+
+ int rc2 = RTCritSectLeave(&mCritSect);
+ if (RT_SUCCESS(rc))
+ rc = rc2;
}
- else
+
+ Assert(rc != VERR_TIMEOUT || cMsTimeout != RT_INDEFINITE_WAIT);
+ return rc;
+}
+
+/**
+ * Processes all pending events in the queue at the time of
+ * calling. Note: Does no initial locking, must be done by the
+ * caller!
+ *
+ * @return IPRT status code.
+ */
+int EventQueue::processPendingEvents(size_t cNumEvents)
+{
+ if (!cNumEvents) /* Nothing to process? Bail out early. */
+ return VINF_SUCCESS;
+
+ int rc = VINF_SUCCESS;
+
+ EventQueueListIterator it = mEvents.begin();
+ for (size_t i = 0;
+ i < cNumEvents
+ && it != mEvents.end(); i++)
{
- rc = processPendingEvents();
- if ( rc == VERR_TIMEOUT
- && cMsTimeout != 0)
+ Event *pEvent = *it;
+ AssertPtr(pEvent);
+
+ mEvents.erase(it);
+
+ int rc2 = RTCritSectLeave(&mCritSect);
+ AssertRC(rc2);
+
+ pEvent->handler();
+ pEvent->Release();
+
+ rc2 = RTCritSectEnter(&mCritSect);
+ AssertRC(rc2);
+
+ it = mEvents.begin();
+ if (mShutdown)
{
- DWORD rcW = MsgWaitForMultipleObjects(1,
- &mhThread,
- TRUE /*fWaitAll*/,
- cMsTimeout,
- QS_ALLINPUT);
- AssertMsgReturn(rcW == WAIT_TIMEOUT || rcW == WAIT_OBJECT_0,
- ("%d\n", rcW),
- VERR_INTERNAL_ERROR_4);
- rc = processPendingEvents();
+ rc = VERR_INTERRUPTED;
+ break;
}
}
-#endif // !VBOX_WITH_XPCOM
- Assert(rc != VERR_TIMEOUT || cMsTimeout != RT_INDEFINITE_WAIT);
return rc;
}
@@ -573,13 +182,11 @@ int EventQueue::processEventQueue(RTMSINTERVAL cMsTimeout)
*
* @returns VBox status code.
*/
-int EventQueue::interruptEventQueueProcessing()
+int EventQueue::interruptEventQueueProcessing(void)
{
- /* Send a NULL event. This event will be picked up and handled specially
- * both for XPCOM and Windows. It is the responsibility of the caller to
- * take care of not running the loop again in a way which will hang. */
- postEvent(NULL);
- return VINF_SUCCESS;
+ ASMAtomicWriteBool(&mShutdown, true);
+
+ return RTSemEventSignal(mSemEvent);
}
/**
@@ -588,39 +195,52 @@ int EventQueue::interruptEventQueueProcessing()
* @param event the event to post, must be allocated using |new|
* @return TRUE if successful and false otherwise
*/
-BOOL EventQueue::postEvent(Event *event)
+BOOL EventQueue::postEvent(Event *pEvent)
{
-#ifndef VBOX_WITH_XPCOM
- /* Note! The event == NULL case is duplicated in vboxapi/PlatformMSCOM::interruptWaitEvents(). */
- return PostThreadMessage(mThreadId, WM_USER, (WPARAM)event, EVENTQUEUE_WIN_LPARAM_MAGIC);
-
-#else // VBOX_WITH_XPCOM
-
- if (!mEventQ)
- return FALSE;
+ int rc = RTCritSectEnter(&mCritSect);
+ if (RT_SUCCESS(rc))
+ {
+ try
+ {
+ if (pEvent)
+ {
+ pEvent->AddRef();
+ mEvents.push_back(pEvent);
+ }
+ else /* No locking, since we're already in our crit sect. */
+ mShutdown = true;
- MyPLEvent *ev = new MyPLEvent(event);
- mEventQ->InitEvent(ev, this, com::EventQueue::plEventHandler,
- com::EventQueue::plEventDestructor);
- HRESULT rc = mEventQ->PostEvent(ev);
- return NS_SUCCEEDED(rc);
+ size_t cEvents = mEvents.size();
+ if (cEvents > _1K) /** @todo Make value configurable? */
+ {
+ static int s_cBitchedAboutLotEvents = 0;
+ if (s_cBitchedAboutLotEvents < 10)
+ LogRel(("Warning: Event queue received lots of events (%zu), expect delayed event handling (%d/10)\n",
+ cEvents, ++s_cBitchedAboutLotEvents));
+ }
-#endif // VBOX_WITH_XPCOM
-}
+ /* Leave critical section before signalling event. */
+ rc = RTCritSectLeave(&mCritSect);
+ if (RT_SUCCESS(rc))
+ {
+ int rc2 = RTSemEventSignal(mSemEvent);
+ AssertRC(rc2);
+ }
+ }
+ catch (std::bad_alloc &ba)
+ {
+ NOREF(ba);
+ rc = VERR_NO_MEMORY;
+ }
+ if (RT_FAILURE(rc))
+ {
+ int rc2 = RTCritSectLeave(&mCritSect);
+ AssertRC(rc2);
+ }
+ }
-/**
- * Get select()'able selector for this event queue.
- * This will return -1 on platforms and queue variants not supporting such
- * functionality.
- */
-int EventQueue::getSelectFD()
-{
-#ifdef VBOX_WITH_XPCOM
- return mEventQ->GetEventQueueSelectFD();
-#else
- return -1;
-#endif
+ return RT_SUCCESS(rc) ? TRUE : FALSE;
}
}