Changeset 46649 in vbox for trunk/src/VBox/Main
- Timestamp:
- Jun 19, 2013 11:47:32 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 86538
- Location:
- trunk
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/VBox-4.1 merged: 82579,85941 /branches/VBox-4.2 merged: 86229-86230,86234,86529 /branches/andy/guestctrl20 (added) merged: 78916,78930
- Property svn:mergeinfo changed
-
trunk/src/VBox
- Property svn:mergeinfo changed
/branches/VBox-4.1/src/VBox merged: 85941 /branches/VBox-4.2/src/VBox merged: 86529
- Property svn:mergeinfo changed
-
trunk/src/VBox/Main/Makefile.kmk
r46474 r46649 736 736 glue/AutoLock.cpp \ 737 737 glue/EventQueue.cpp \ 738 glue/NativeEventQueue.cpp \ 738 739 glue/ErrorInfo.cpp \ 739 740 glue/errorprint.cpp -
trunk/src/VBox/Main/glue/EventQueue.cpp
r43944 r46649 1 1 /* $Id$ */ 2 2 /** @file 3 * MS COM / XPCOM Abstraction Layer: 4 * Event and EventQueue class declaration 3 * Event queue class declaration. 5 4 */ 6 5 7 6 /* 8 * Copyright (C) 20 06-2012Oracle Corporation7 * Copyright (C) 2013 Oracle Corporation 9 8 * 10 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 17 16 */ 18 17 18 /** @todo Adapt / update documentation! */ 19 19 20 #include "VBox/com/EventQueue.h" 20 21 21 #ifdef RT_OS_DARWIN 22 # include <CoreFoundation/CFRunLoop.h> 23 #endif 24 25 #if defined(VBOX_WITH_XPCOM) && !defined(RT_OS_DARWIN) && !defined(RT_OS_OS2) 26 # define USE_XPCOM_QUEUE 27 #endif 28 22 #include <iprt/asm.h> 29 23 #include <new> /* For bad_alloc. */ 30 24 31 25 #include <iprt/err.h> 26 #include <iprt/semaphore.h> 32 27 #include <iprt/time.h> 33 28 #include <iprt/thread.h> 34 29 #include <iprt/log.h> 35 #ifdef USE_XPCOM_QUEUE36 # include <errno.h>37 #endif38 30 39 31 namespace com … … 43 35 //////////////////////////////////////////////////////////////////////////////// 44 36 45 #ifndef VBOX_WITH_XPCOM 46 47 # define CHECK_THREAD_RET(ret) \ 48 do { \ 49 AssertMsg(GetCurrentThreadId() == mThreadId, ("Must be on event queue thread!")); \ 50 if (GetCurrentThreadId() != mThreadId) \ 51 return ret; \ 52 } while (0) 53 54 /** Magic LPARAM value for the WM_USER messages that we're posting. 55 * @remarks This magic value is duplicated in 56 * vboxapi/PlatformMSCOM::interruptWaitEvents(). */ 57 #define EVENTQUEUE_WIN_LPARAM_MAGIC UINT32_C(0xf241b819) 58 59 60 #else // VBOX_WITH_XPCOM 61 62 # define CHECK_THREAD_RET(ret) \ 63 do { \ 64 if (!mEventQ) \ 65 return ret; \ 66 BOOL isOnCurrentThread = FALSE; \ 67 mEventQ->IsOnCurrentThread(&isOnCurrentThread); \ 68 AssertMsg(isOnCurrentThread, ("Must be on event queue thread!")); \ 69 if (!isOnCurrentThread) \ 70 return ret; \ 71 } while (0) 72 73 #endif // VBOX_WITH_XPCOM 74 75 /** Pointer to the main event queue. */ 76 EventQueue *EventQueue::sMainQueue = NULL; 77 78 79 #ifdef VBOX_WITH_XPCOM 80 81 struct MyPLEvent : public PLEvent 82 { 83 MyPLEvent(Event *e) : event(e) {} 84 Event *event; 85 }; 86 87 /* static */ 88 void *PR_CALLBACK com::EventQueue::plEventHandler(PLEvent *self) 89 { 90 Event *ev = ((MyPLEvent *)self)->event; 91 if (ev) 92 ev->handler(); 93 else 94 { 95 EventQueue *eq = (EventQueue *)self->owner; 96 Assert(eq); 97 eq->mInterrupted = true; 98 } 99 return NULL; 100 } 101 102 /* static */ 103 void PR_CALLBACK com::EventQueue::plEventDestructor(PLEvent *self) 104 { 105 Event *ev = ((MyPLEvent *)self)->event; 106 if (ev) 107 delete ev; 108 delete self; 109 } 110 111 #endif // VBOX_WITH_XPCOM 112 113 /** 114 * Constructs an event queue for the current thread. 115 * 116 * Currently, there can be only one event queue per thread, so if an event 117 * queue for the current thread already exists, this object is simply attached 118 * to the existing event queue. 119 */ 120 EventQueue::EventQueue() 121 { 122 /** @todo r=andy This constructor does way too much. In case of failure 123 * it's up to the caller to verify all sorts of stuff. Why 124 * isn't this done in init() and moving the main queue 125 * creation/deletion stuff to a dedicated function? */ 126 #ifndef VBOX_WITH_XPCOM 127 128 mThreadId = GetCurrentThreadId(); 129 // force the system to create the message queue for the current thread 130 MSG msg; 131 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); 132 133 if (!DuplicateHandle(GetCurrentProcess(), 134 GetCurrentThread(), 135 GetCurrentProcess(), 136 &mhThread, 137 0 /*dwDesiredAccess*/, 138 FALSE /*bInheritHandle*/, 139 DUPLICATE_SAME_ACCESS)) 140 mhThread = INVALID_HANDLE_VALUE; 141 142 #else // VBOX_WITH_XPCOM 143 144 mEQCreated = false; 145 mInterrupted = false; 146 147 // Here we reference the global nsIEventQueueService instance and hold it 148 // until we're destroyed. This is necessary to keep NS_ShutdownXPCOM() away 149 // from calling StopAcceptingEvents() on all event queues upon destruction of 150 // nsIEventQueueService, and makes sense when, for some reason, this happens 151 // *before* we're able to send a NULL event to stop our event handler thread 152 // when doing unexpected cleanup caused indirectly by NS_ShutdownXPCOM() 153 // that is performing a global cleanup of everything. A good example of such 154 // situation is when NS_ShutdownXPCOM() is called while the VirtualBox component 155 // is still alive (because it is still referenced): eventually, it results in 156 // a VirtualBox::uninit() call from where it is already not possible to post 157 // NULL to the event thread (because it stopped accepting events). 158 159 nsresult rc = NS_GetEventQueueService(getter_AddRefs(mEventQService)); 160 161 if (NS_SUCCEEDED(rc)) 162 { 163 rc = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, 164 getter_AddRefs(mEventQ)); 165 if (rc == NS_ERROR_NOT_AVAILABLE) 166 { 167 rc = mEventQService->CreateThreadEventQueue(); 168 if (NS_SUCCEEDED(rc)) 169 { 170 mEQCreated = true; 171 rc = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, 172 getter_AddRefs(mEventQ)); 173 } 174 } 175 } 176 AssertComRC(rc); 177 178 #endif // VBOX_WITH_XPCOM 179 } 180 181 EventQueue::~EventQueue() 182 { 183 #ifndef VBOX_WITH_XPCOM 184 if (mhThread != INVALID_HANDLE_VALUE) 185 { 186 CloseHandle(mhThread); 187 mhThread = INVALID_HANDLE_VALUE; 188 } 189 #else // VBOX_WITH_XPCOM 190 // process all pending events before destruction 191 if (mEventQ) 192 { 193 if (mEQCreated) 194 { 195 mEventQ->StopAcceptingEvents(); 196 mEventQ->ProcessPendingEvents(); 197 mEventQService->DestroyThreadEventQueue(); 198 } 199 mEventQ = nsnull; 200 mEventQService = nsnull; 201 } 202 #endif // VBOX_WITH_XPCOM 203 } 204 205 /** 206 * Initializes the main event queue instance. 207 * @returns VBox status code. 208 * 209 * @remarks If you're using the rest of the COM/XPCOM glue library, 210 * com::Initialize() will take care of initializing and uninitializing 211 * the EventQueue class. If you don't call com::Initialize, you must 212 * make sure to call this method on the same thread that did the 213 * XPCOM initialization or we'll end up using the wrong main queue. 214 */ 215 /* static */ 216 int EventQueue::init() 217 { 218 Assert(sMainQueue == NULL); 219 Assert(RTThreadIsMain(RTThreadSelf())); 220 221 try 222 { 223 sMainQueue = new EventQueue(); 224 225 #ifdef VBOX_WITH_XPCOM 226 /* Check that it actually is the main event queue, i.e. that 227 we're called on the right thread. */ 228 nsCOMPtr<nsIEventQueue> q; 229 nsresult rv = NS_GetMainEventQ(getter_AddRefs(q)); 230 Assert(NS_SUCCEEDED(rv)); 231 Assert(q == sMainQueue->mEventQ); 232 233 /* Check that it's a native queue. */ 234 PRBool fIsNative = PR_FALSE; 235 rv = sMainQueue->mEventQ->IsQueueNative(&fIsNative); 236 Assert(NS_SUCCEEDED(rv) && fIsNative); 237 #endif // VBOX_WITH_XPCOM 238 } 239 catch (std::bad_alloc &) 240 { 241 return VERR_NO_MEMORY; 242 } 243 244 return VINF_SUCCESS; 245 } 246 247 /** 248 * Uninitialize the global resources (i.e. the main event queue instance). 249 * @returns VINF_SUCCESS 250 */ 251 /* static */ 252 int EventQueue::uninit() 253 { 254 if (sMainQueue) 255 { 256 /* Must process all events to make sure that no NULL event is left 257 * after this point. It would need to modify the state of sMainQueue. */ 258 #ifdef RT_OS_DARWIN /* Do not process the native runloop, the toolkit may not be ready for it. */ 259 sMainQueue->mEventQ->ProcessPendingEvents(); 260 #else 261 sMainQueue->processEventQueue(0); 262 #endif 263 delete sMainQueue; 264 sMainQueue = NULL; 265 } 266 return VINF_SUCCESS; 267 } 268 269 /** 270 * Get main event queue instance. 271 * 272 * Depends on init() being called first. 273 */ 274 /* static */ 275 EventQueue* EventQueue::getMainEventQueue() 276 { 277 return sMainQueue; 278 } 279 280 #ifdef VBOX_WITH_XPCOM 281 # ifdef RT_OS_DARWIN 282 /** 283 * Wait for events and process them (Darwin). 284 * 285 * @retval VINF_SUCCESS 286 * @retval VERR_TIMEOUT 287 * @retval VERR_INTERRUPTED 288 * 289 * @param cMsTimeout How long to wait, or RT_INDEFINITE_WAIT. 290 */ 291 static int waitForEventsOnDarwin(RTMSINTERVAL cMsTimeout) 292 { 293 /* 294 * Wait for the requested time, if we get a hit we do a poll to process 295 * any other pending messages. 296 * 297 * Note! About 1.0e10: According to the sources anything above 3.1556952e+9 298 * means indefinite wait and 1.0e10 is what CFRunLoopRun() uses. 299 */ 300 CFTimeInterval rdTimeout = cMsTimeout == RT_INDEFINITE_WAIT ? 1e10 : (double)cMsTimeout / 1000; 301 OSStatus orc = CFRunLoopRunInMode(kCFRunLoopDefaultMode, rdTimeout, true /*returnAfterSourceHandled*/); 302 if (orc == kCFRunLoopRunHandledSource) 303 { 304 OSStatus orc2 = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, false /*returnAfterSourceHandled*/); 305 if ( orc2 == kCFRunLoopRunStopped 306 || orc2 == kCFRunLoopRunFinished) 307 orc = orc2; 308 } 309 if ( orc == 0 /*???*/ 310 || orc == kCFRunLoopRunHandledSource) 311 return VINF_SUCCESS; 312 if ( orc == kCFRunLoopRunStopped 313 || orc == kCFRunLoopRunFinished) 314 return VERR_INTERRUPTED; 315 AssertMsg(orc == kCFRunLoopRunTimedOut, ("Unexpected status code from CFRunLoopRunInMode: %#x", orc)); 316 return VERR_TIMEOUT; 317 } 318 # else // !RT_OS_DARWIN 319 320 /** 321 * Wait for events (generic XPCOM). 322 * 323 * @retval VINF_SUCCESS 324 * @retval VERR_TIMEOUT 325 * @retval VINF_INTERRUPTED 326 * @retval VERR_INTERNAL_ERROR_4 327 * 328 * @param pQueue The queue to wait on. 329 * @param cMsTimeout How long to wait, or RT_INDEFINITE_WAIT. 330 */ 331 static int waitForEventsOnXPCOM(nsIEventQueue *pQueue, RTMSINTERVAL cMsTimeout) 332 { 333 int fd = pQueue->GetEventQueueSelectFD(); 334 fd_set fdsetR; 335 FD_ZERO(&fdsetR); 336 FD_SET(fd, &fdsetR); 337 338 fd_set fdsetE = fdsetR; 339 340 struct timeval tv = {0,0}; 341 struct timeval *ptv; 342 if (cMsTimeout == RT_INDEFINITE_WAIT) 343 ptv = NULL; 344 else 345 { 346 tv.tv_sec = cMsTimeout / 1000; 347 tv.tv_usec = (cMsTimeout % 1000) * 1000; 348 ptv = &tv; 349 } 350 351 int rc = select(fd + 1, &fdsetR, NULL, &fdsetE, ptv); 352 if (rc > 0) 353 rc = VINF_SUCCESS; 354 else if (rc == 0) 355 rc = VERR_TIMEOUT; 356 else if (errno == EINTR) 357 rc = VINF_INTERRUPTED; 358 else 359 { 360 static uint32_t s_ErrorCount = 0; 361 if (s_ErrorCount < 500) 362 { 363 LogRel(("waitForEventsOnXPCOM rc=%d errno=%d\n", rc, errno)); 364 ++s_ErrorCount; 365 } 366 367 AssertMsgFailed(("rc=%d errno=%d\n", rc, errno)); 368 rc = VERR_INTERNAL_ERROR_4; 369 } 370 return rc; 371 } 372 373 # endif // !RT_OS_DARWIN 374 #endif // VBOX_WITH_XPCOM 375 376 #ifndef VBOX_WITH_XPCOM 377 378 /** 379 * Dispatch a message on Windows. 380 * 381 * This will pick out our events and handle them specially. 382 * 383 * @returns @a rc or VERR_INTERRUPTED (WM_QUIT or NULL msg). 384 * @param pMsg The message to dispatch. 385 * @param rc The current status code. 386 */ 387 /*static*/ 388 int EventQueue::dispatchMessageOnWindows(MSG const *pMsg, int rc) 389 { 390 /* 391 * Check for and dispatch our events. 392 */ 393 if ( pMsg->hwnd == NULL 394 && pMsg->message == WM_USER) 395 { 396 if (pMsg->lParam == EVENTQUEUE_WIN_LPARAM_MAGIC) 397 { 398 Event *pEvent = (Event *)pMsg->wParam; 399 if (pEvent) 400 { 401 pEvent->handler(); 402 delete pEvent; 403 } 404 else 405 rc = VERR_INTERRUPTED; 406 return rc; 407 } 408 AssertMsgFailed(("lParam=%p wParam=%p\n", pMsg->lParam, pMsg->wParam)); 409 } 410 411 /* 412 * Check for the quit message and dispatch the message the normal way. 413 */ 414 if (pMsg->message == WM_QUIT) 415 rc = VERR_INTERRUPTED; 416 TranslateMessage(pMsg); 417 DispatchMessage(pMsg); 418 419 return rc; 420 } 421 422 423 /** 424 * Process pending events (Windows). 425 * 426 * @retval VINF_SUCCESS 427 * @retval VERR_TIMEOUT 428 * @retval VERR_INTERRUPTED. 429 */ 430 static int processPendingEvents(void) 431 { 432 int rc = VERR_TIMEOUT; 433 MSG Msg; 434 if (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE)) 435 { 436 rc = VINF_SUCCESS; 437 do 438 rc = EventQueue::dispatchMessageOnWindows(&Msg, rc); 439 while (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE)); 440 } 441 return rc; 442 } 443 444 #else // VBOX_WITH_XPCOM 445 446 /** 447 * Process pending XPCOM events. 448 * @param pQueue The queue to process events on. 449 * @retval VINF_SUCCESS 450 * @retval VERR_TIMEOUT 451 * @retval VERR_INTERRUPTED (darwin only) 452 * @retval VERR_INTERNAL_ERROR_2 453 */ 454 static int processPendingEvents(nsIEventQueue *pQueue) 455 { 456 /* ProcessPendingEvents doesn't report back what it did, so check here. */ 457 PRBool fHasEvents = PR_FALSE; 458 nsresult hr = pQueue->PendingEvents(&fHasEvents); 459 if (NS_FAILED(hr)) 460 return VERR_INTERNAL_ERROR_2; 461 462 /* Process pending events. */ 463 int rc = VINF_SUCCESS; 464 if (fHasEvents) 465 pQueue->ProcessPendingEvents(); 466 else 467 rc = VERR_TIMEOUT; 468 469 # ifdef RT_OS_DARWIN 470 /* Process pending native events. */ 471 int rc2 = waitForEventsOnDarwin(0); 472 if (rc == VERR_TIMEOUT || rc2 == VERR_INTERRUPTED) 473 rc = rc2; 474 # endif 475 476 return rc; 477 } 478 479 #endif // VBOX_WITH_XPCOM 37 EventQueue::EventQueue(void) 38 : mShutdown(false) 39 { 40 int rc = RTCritSectInit(&mCritSect); 41 AssertRC(rc); 42 43 rc = RTSemEventCreate(&mSemEvent); 44 AssertRC(rc); 45 } 46 47 EventQueue::~EventQueue(void) 48 { 49 int rc = RTCritSectDelete(&mCritSect); 50 AssertRC(rc); 51 52 rc = RTSemEventDestroy(mSemEvent); 53 AssertRC(rc); 54 55 EventQueueListIterator it = mEvents.begin(); 56 while (it != mEvents.end()) 57 { 58 (*it)->Release(); 59 it = mEvents.erase(it); 60 } 61 } 480 62 481 63 /** … … 504 86 int EventQueue::processEventQueue(RTMSINTERVAL cMsTimeout) 505 87 { 506 int rc; 507 CHECK_THREAD_RET(VERR_INVALID_CONTEXT); 508 509 #ifdef VBOX_WITH_XPCOM 510 /* 511 * Process pending events, if none are available and we're not in a 512 * poll call, wait for some to appear. (We have to be a little bit 513 * careful after waiting for the events since Darwin will process 514 * them as part of the wait, while the XPCOM case will not.) 515 * 516 * Note! Unfortunately, WaitForEvent isn't interruptible with Ctrl-C, 517 * while select() is. So we cannot use it for indefinite waits. 518 */ 519 rc = processPendingEvents(mEventQ); 520 if ( rc == VERR_TIMEOUT 521 && cMsTimeout > 0) 522 { 523 # ifdef RT_OS_DARWIN 524 /** @todo check how Ctrl-C works on Darwin. */ 525 rc = waitForEventsOnDarwin(cMsTimeout); 526 if (rc == VERR_TIMEOUT) 527 rc = processPendingEvents(mEventQ); 528 # else // !RT_OS_DARWIN 529 rc = waitForEventsOnXPCOM(mEventQ, cMsTimeout); 530 if ( RT_SUCCESS(rc) 531 || rc == VERR_TIMEOUT) 532 rc = processPendingEvents(mEventQ); 533 # endif // !RT_OS_DARWIN 534 } 535 536 if ( ( RT_SUCCESS(rc) 537 || rc == VERR_INTERRUPTED 538 || rc == VERR_TIMEOUT) 539 && mInterrupted) 540 { 541 mInterrupted = false; 542 rc = VERR_INTERRUPTED; 543 } 544 545 #else // !VBOX_WITH_XPCOM 546 if (cMsTimeout == RT_INDEFINITE_WAIT) 547 { 548 BOOL fRet; 549 MSG Msg; 550 rc = VINF_SUCCESS; 551 while ( rc != VERR_INTERRUPTED 552 && (fRet = GetMessage(&Msg, NULL /*hWnd*/, WM_USER, WM_USER)) 553 && fRet != -1) 554 rc = EventQueue::dispatchMessageOnWindows(&Msg, rc); 555 if (fRet == 0) 556 rc = VERR_INTERRUPTED; 557 else if (fRet == -1) 558 rc = RTErrConvertFromWin32(GetLastError()); 88 bool fWait; 89 int rc = RTCritSectEnter(&mCritSect); 90 if (RT_SUCCESS(rc)) 91 { 92 fWait = mEvents.size() == 0; 93 if (!fWait) 94 { 95 int rc2 = RTCritSectLeave(&mCritSect); 96 AssertRC(rc2); 97 } 98 } 99 100 if (fWait) 101 { 102 int rc2 = RTCritSectLeave(&mCritSect); 103 AssertRC(rc2); 104 105 rc = RTSemEventWaitNoResume(mSemEvent, cMsTimeout); 106 } 107 108 if (RT_SUCCESS(rc)) 109 { 110 if (ASMAtomicReadBool(&mShutdown)) 111 return VERR_INTERRUPTED; 112 113 if (fWait) 114 rc = RTCritSectEnter(&mCritSect); 115 if (RT_SUCCESS(rc)) 116 { 117 EventQueueListIterator it = mEvents.begin(); 118 if (it != mEvents.end()) 119 { 120 Event *pEvent = *it; 121 AssertPtr(pEvent); 122 123 mEvents.erase(it); 124 125 int rc2 = RTCritSectLeave(&mCritSect); 126 if (RT_SUCCESS(rc)) 127 rc = rc2; 128 129 pEvent->handler(); 130 pEvent->Release(); 559 131 } 560 132 else 561 133 { 562 rc = processPendingEvents(); 563 if ( rc == VERR_TIMEOUT 564 && cMsTimeout != 0) 565 { 566 DWORD rcW = MsgWaitForMultipleObjects(1, 567 &mhThread, 568 TRUE /*fWaitAll*/, 569 cMsTimeout, 570 QS_ALLINPUT); 571 AssertMsgReturn(rcW == WAIT_TIMEOUT || rcW == WAIT_OBJECT_0, 572 ("%d\n", rcW), 573 VERR_INTERNAL_ERROR_4); 574 rc = processPendingEvents(); 575 } 576 } 577 #endif // !VBOX_WITH_XPCOM 134 int rc2 = RTCritSectLeave(&mCritSect); 135 if (RT_SUCCESS(rc)) 136 rc = rc2; 137 } 138 } 139 } 578 140 579 141 Assert(rc != VERR_TIMEOUT || cMsTimeout != RT_INDEFINITE_WAIT); … … 588 150 * @returns VBox status code. 589 151 */ 590 int EventQueue::interruptEventQueueProcessing() 591 { 592 /* Send a NULL event. This event will be picked up and handled specially 593 * both for XPCOM and Windows. It is the responsibility of the caller to 594 * take care of not running the loop again in a way which will hang. */ 595 postEvent(NULL); 596 return VINF_SUCCESS; 152 int EventQueue::interruptEventQueueProcessing(void) 153 { 154 ASMAtomicWriteBool(&mShutdown, true); 155 156 return RTSemEventSignal(mSemEvent); 597 157 } 598 158 … … 605 165 BOOL EventQueue::postEvent(Event *pEvent) 606 166 { 607 #ifndef VBOX_WITH_XPCOM 608 /* Note! The event == NULL case is duplicated in vboxapi/PlatformMSCOM::interruptWaitEvents(). */ 609 return PostThreadMessage(mThreadId, WM_USER, (WPARAM)pEvent, EVENTQUEUE_WIN_LPARAM_MAGIC); 610 611 #else // VBOX_WITH_XPCOM 612 613 if (!mEventQ) 614 return FALSE; 615 616 try 617 { 618 MyPLEvent *pMyEvent = new MyPLEvent(pEvent); 619 mEventQ->InitEvent(pMyEvent, this, com::EventQueue::plEventHandler, 620 com::EventQueue::plEventDestructor); 621 HRESULT rc = mEventQ->PostEvent(pMyEvent); 622 return NS_SUCCEEDED(rc); 623 } 624 catch (std::bad_alloc &ba) 625 { 626 AssertMsgFailed(("Out of memory while allocating memory for event=%p: %s\n", 627 pEvent, ba.what())); 628 } 629 630 return FALSE; 631 #endif // VBOX_WITH_XPCOM 632 } 633 634 635 /** 636 * Get select()'able selector for this event queue. 637 * This will return -1 on platforms and queue variants not supporting such 638 * functionality. 639 */ 640 int EventQueue::getSelectFD() 641 { 642 #ifdef VBOX_WITH_XPCOM 643 return mEventQ->GetEventQueueSelectFD(); 644 #else 645 return -1; 646 #endif 167 int rc = RTCritSectEnter(&mCritSect); 168 if (RT_SUCCESS(rc)) 169 { 170 try 171 { 172 if (pEvent) 173 { 174 pEvent->AddRef(); 175 mEvents.push_back(pEvent); 176 } 177 else /* No locking, since we're already in our crit sect. */ 178 mShutdown = true; 179 180 size_t cEvents = mEvents.size(); 181 if (cEvents > _1K) /** @todo Make value configurable? */ 182 { 183 static int s_cBitchedAboutLotEvents = 0; 184 if (s_cBitchedAboutLotEvents < 10) 185 LogRel(("Warning: Event queue received lots of events (%zu), expect delayed event handling (%d/10)\n", 186 cEvents, ++s_cBitchedAboutLotEvents)); 187 } 188 189 /* Leave critical section before signalling event. */ 190 rc = RTCritSectLeave(&mCritSect); 191 if (RT_SUCCESS(rc)) 192 { 193 int rc2 = RTSemEventSignal(mSemEvent); 194 AssertRC(rc2); 195 } 196 } 197 catch (std::bad_alloc &ba) 198 { 199 NOREF(ba); 200 rc = VERR_NO_MEMORY; 201 } 202 203 if (RT_FAILURE(rc)) 204 { 205 int rc2 = RTCritSectLeave(&mCritSect); 206 AssertRC(rc2); 207 } 208 } 209 210 return RT_SUCCESS(rc) ? TRUE : FALSE; 647 211 } 648 212 -
trunk/src/VBox/Main/glue/initterm.cpp
r44528 r46649 6 6 7 7 /* 8 * Copyright (C) 2006-201 2Oracle Corporation8 * Copyright (C) 2006-2013 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 49 49 #include "VBox/com/com.h" 50 50 #include "VBox/com/assert.h" 51 #include "VBox/com/ EventQueue.h"51 #include "VBox/com/NativeEventQueue.h" 52 52 #include "VBox/com/AutoLock.h" 53 53 … … 499 499 */ 500 500 if (SUCCEEDED(rc)) 501 EventQueue::init();501 NativeEventQueue::init(); 502 502 503 503 return rc; … … 517 517 if (-- gCOMMainInitCount == 0) 518 518 { 519 EventQueue::uninit();519 NativeEventQueue::uninit(); 520 520 ASMAtomicWriteHandle(&gCOMMainThread, NIL_RTTHREAD); 521 521 } … … 556 556 if (--gXPCOMInitCount == 0) 557 557 { 558 EventQueue::uninit();558 MainEventQueue::uninit(); 559 559 rc = NS_ShutdownXPCOM(nsnull); 560 560 -
trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp
r45356 r46649 5356 5356 AssertReturn(pvUser, VERR_INVALID_POINTER); 5357 5357 5358 com::Initialize(); 5359 5360 // create an event queue for the current thread 5361 EventQueue *eventQ = new EventQueue(); 5362 AssertReturn(eventQ, VERR_NO_MEMORY); 5363 5364 // return the queue to the one who created this thread 5365 *(static_cast <EventQueue **>(pvUser)) = eventQ; 5366 // signal that we're ready 5367 RTThreadUserSignal(thread); 5368 5369 /* 5370 * In case of spurious wakeups causing VERR_TIMEOUTs and/or other return codes 5371 * we must not stop processing events and delete the "eventQ" object. This must 5372 * be done ONLY when we stop this loop via interruptEventQueueProcessing(). 5373 * See @bugref{5724}. 5374 */ 5375 while (eventQ->processEventQueue(RT_INDEFINITE_WAIT) != VERR_INTERRUPTED) 5376 /* nothing */ ; 5377 5378 delete eventQ; 5358 HRESULT hr = com::Initialize(); 5359 if (FAILED(hr)) 5360 return VERR_COM_UNEXPECTED; 5361 5362 int rc = VINF_SUCCESS; 5363 5364 try 5365 { 5366 /* Create an event queue for the current thread. */ 5367 EventQueue *pEventQueue = new EventQueue(); 5368 AssertPtr(pEventQueue); 5369 5370 /* Return the queue to the one who created this thread. */ 5371 *(static_cast <EventQueue **>(pvUser)) = pEventQueue; 5372 5373 /* signal that we're ready. */ 5374 RTThreadUserSignal(thread); 5375 5376 /* 5377 * In case of spurious wakeups causing VERR_TIMEOUTs and/or other return codes 5378 * we must not stop processing events and delete the pEventQueue object. This must 5379 * be done ONLY when we stop this loop via interruptEventQueueProcessing(). 5380 * See @bugref{5724}. 5381 */ 5382 while (pEventQueue->processEventQueue(RT_INDEFINITE_WAIT) != VERR_INTERRUPTED) 5383 /* nothing */ ; 5384 5385 delete pEventQueue; 5386 } 5387 catch (std::bad_alloc &ba) 5388 { 5389 rc = VERR_NO_MEMORY; 5390 NOREF(ba); 5391 } 5379 5392 5380 5393 com::Shutdown(); 5381 5394 5382 5383 LogFlowFuncLeave(); 5384 5385 return 0; 5395 LogFlowFuncLeaveRC(rc); 5396 return rc; 5386 5397 } 5387 5398
Note:
See TracChangeset
for help on using the changeset viewer.