Changeset 31589 in vbox for trunk/src/VBox/Main
- Timestamp:
- Aug 11, 2010 11:04:33 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/glue/EventQueue.cpp
r31579 r31589 1 1 /* $Id$ */ 2 3 2 /** @file 4 *5 3 * MS COM / XPCOM Abstraction Layer: 6 4 * Event and EventQueue class declaration … … 44 42 #ifndef VBOX_WITH_XPCOM 45 43 46 # define CHECK_THREAD_RET(ret) \44 # define CHECK_THREAD_RET(ret) \ 47 45 do { \ 48 46 AssertMsg(GetCurrentThreadId() == mThreadId, ("Must be on event queue thread!")); \ … … 51 49 } while (0) 52 50 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 53 59 #else // VBOX_WITH_XPCOM 54 60 55 # define CHECK_THREAD_RET(ret) \61 # define CHECK_THREAD_RET(ret) \ 56 62 do { \ 57 63 if (!mEventQ) \ … … 66 72 #endif // VBOX_WITH_XPCOM 67 73 68 EventQueue *EventQueue::mMainQueue = NULL; 74 /** Pointer to the main event queue. */ 75 EventQueue *EventQueue::sMainQueue = NULL; 76 69 77 70 78 #ifdef VBOX_WITH_XPCOM 79 71 80 struct MyPLEvent : public PLEvent 72 81 { … … 128 137 #else // VBOX_WITH_XPCOM 129 138 130 mEQCreated = FALSE;131 mInterrupted = FALSE;139 mEQCreated = false; 140 mInterrupted = false; 132 141 133 142 // Here we reference the global nsIEventQueueService instance and hold it … … 154 163 if (NS_SUCCEEDED(rc)) 155 164 { 156 mEQCreated = TRUE;165 mEQCreated = true; 157 166 rc = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, 158 167 getter_AddRefs(mEventQ)); … … 202 211 int EventQueue::init() 203 212 { 204 Assert( mMainQueue == NULL);213 Assert(sMainQueue == NULL); 205 214 Assert(RTThreadIsMain(RTThreadSelf())); 206 mMainQueue = new EventQueue();215 sMainQueue = new EventQueue(); 207 216 208 217 #ifdef VBOX_WITH_XPCOM … … 212 221 nsresult rv = NS_GetMainEventQ(getter_AddRefs(q)); 213 222 Assert(NS_SUCCEEDED(rv)); 214 Assert(q == mMainQueue->mEventQ);223 Assert(q == sMainQueue->mEventQ); 215 224 216 225 /* Check that it's a native queue. */ 217 226 PRBool fIsNative = PR_FALSE; 218 rv = mMainQueue->mEventQ->IsQueueNative(&fIsNative);227 rv = sMainQueue->mEventQ->IsQueueNative(&fIsNative); 219 228 Assert(NS_SUCCEEDED(rv) && fIsNative); 220 229 #endif // VBOX_WITH_XPCOM … … 230 239 int EventQueue::uninit() 231 240 { 232 Assert( mMainQueue);241 Assert(sMainQueue); 233 242 /* 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; 238 247 return VINF_SUCCESS; 239 248 } … … 247 256 EventQueue* EventQueue::getMainEventQueue() 248 257 { 249 return mMainQueue;258 return sMainQueue; 250 259 } 251 260 … … 253 262 # ifdef RT_OS_DARWIN 254 263 /** 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 */ 272 static int waitForEventsOnDarwin(RTMSINTERVAL cMsTimeout) 263 273 { 264 274 /* … … 287 297 288 298 /** 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 */ 309 static int waitForEventsOnXPCOM(nsIEventQueue *pQueue, RTMSINTERVAL cMsTimeout) 298 310 { 299 311 int fd = pQueue->GetEventQueueSelectFD(); … … 334 346 335 347 #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*/ 359 int 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 */ 401 static int processPendingEvents(void) 402 { 403 int rc = VERR_TIMEOUT; 343 404 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 { 352 407 rc = VINF_SUCCESS; 408 do 409 rc = EventQueue::dispatchMessageOnWindows(&Msg, rc); 410 while (PeekMessage(&Msg, NULL /*hWnd*/, 0 /*wMsgFilterMin*/, 0 /*wMsgFilterMax*/, PM_REMOVE)); 353 411 } 354 412 return rc; 355 413 } 414 356 415 #else // VBOX_WITH_XPCOM 416 357 417 /** 358 418 * Process pending XPCOM events. … … 360 420 * @returns VINF_SUCCESS or VERR_TIMEOUT. 361 421 */ 362 static 363 int processPendingEvents(nsIEventQueue *pQueue) 422 static int processPendingEvents(nsIEventQueue *pQueue) 364 423 { 365 424 /* Check for timeout condition so the caller can be a bit more lazy. */ … … 374 433 return VINF_SUCCESS; 375 434 } 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 */ 463 int EventQueue::processEventQueue(RTMSINTERVAL cMsTimeout) 395 464 { 396 465 int rc; … … 423 492 # endif // !RT_OS_DARWIN 424 493 } 425 if (RT_SUCCESS(rc) && mInterrupted) 494 495 if ( ( RT_SUCCESS(rc) 496 || rc == VERR_INTERRUPTED) 497 && mInterrupted) 426 498 { 427 499 mInterrupted = false; … … 432 504 if (cMsTimeout == RT_INDEFINITE_WAIT) 433 505 { 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) 443 514 rc = VERR_INTERRUPTED; 515 else if (fRet == -1) 516 rc = RTErrConvertFromWin32(GetLastError()); 444 517 } 445 518 else … … 447 520 rc = processPendingEvents(); 448 521 if ( rc == VERR_TIMEOUT 449 || cMsTimeout == 0)522 && cMsTimeout != 0) 450 523 { 451 524 DWORD rcW = MsgWaitForMultipleObjects(1, … … 461 534 } 462 535 #endif // !VBOX_WITH_XPCOM 536 463 537 return rc; 464 538 } 465 539 466 540 /** 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. 470 546 */ 471 547 int EventQueue::interruptEventQueueProcessing() 472 548 { 473 /* Send a NULL event. This gets us out of the event loop on XPCOM, and474 * doesn't hurt on Windows.It is the responsibility of the caller to549 /* 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 475 551 * take care of not running the loop again in a way which will hang. */ 476 552 postEvent(NULL); … … 488 564 #ifndef VBOX_WITH_XPCOM 489 565 490 return PostThreadMessage(mThreadId, WM_USER, (WPARAM)event, NULL);566 return PostThreadMessage(mThreadId, WM_USER, (WPARAM)event, EVENTQUEUE_WIN_LPARAM_MAGIC); 491 567 492 568 #else // VBOX_WITH_XPCOM
Note:
See TracChangeset
for help on using the changeset viewer.