Changeset 22847 in vbox
- Timestamp:
- Sep 8, 2009 8:37:54 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
-
include/VBox/com/EventQueue.h (modified) (1 diff)
-
src/VBox/Main/glue/EventQueue.cpp (modified) (5 diffs)
-
src/VBox/Main/glue/initterm.cpp (modified) (3 diffs)
-
src/libs/xpcom18a4/python/src/module/_xpcom.cpp (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/com/EventQueue.h
r22722 r22847 91 91 BOOL handleEvent (Event *event); 92 92 static int processThreadEventQueue(uint32_t cMsTimeout, bool (*pfnExitCheck)(void *pvUser) = 0, 93 void *pvUser = 0, uint32_t cMsPollInterval = 1000, 94 bool fReturnOnEvent = true); 93 void *pvUser = 0, uint32_t cMsPollInterval = 1000, 94 bool fReturnOnEvent = true); 95 /** 96 * Process events pending on this event queue, and wait 97 * up to given timeout, if nothing is available. 98 * Must be called on same thread this event queue was created on. 99 */ 100 int processEventQueue(uint32_t cMsTimeout); 101 /** 102 * Interrupt thread waiting on event queue processing. 103 * Can be called on any thread. 104 */ 105 int interruptEventQueueProcessing(); 106 /** 107 * Initialize/deinitialize event queues. 108 */ 109 static int init(); 110 static int deinit(); 111 /** 112 * Get main event queue instance. 113 */ 114 static EventQueue* getMainEventQueue(); 95 115 96 116 private: 117 static EventQueue* mMainQueue; 97 118 98 119 #if !defined (VBOX_WITH_XPCOM) -
trunk/src/VBox/Main/glue/EventQueue.cpp
r22722 r22847 69 69 70 70 #endif // !defined (RT_OS_WINDOWS) 71 72 EventQueue* EventQueue::mMainQueue = NULL; 71 73 72 74 /** … … 146 148 } 147 149 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 178 static int 179 timedWaitForEventsOnDarwin(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 201 static int 202 processPendingEventsOnWindows() 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, */ 218 class MyThreadHandle 219 { 220 public: 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> 243 int 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 350 int EventQueue::interruptEventQueueProcessing() 351 { 352 postEvent(NULL); 353 return VINF_SUCCESS; 354 } 355 148 356 /** 149 357 * Posts an event to this event loop asynchronously. … … 287 495 288 496 #else 289 290 /** For automatic cleanup. */291 class MyThreadHandle292 {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 };310 497 311 498 /** COM version of nsIEventQueue::PendingEvents. */ … … 386 573 return VERR_NOT_FOUND; 387 574 #else 388 MyThreadHandle q (GetCurrentThread());575 MyThreadHandle q; 389 576 #endif 390 577 … … 530 717 return VINF_SUCCESS; 531 718 } 532 533 719 } 534 720 /* namespace com */ -
trunk/src/VBox/Main/glue/initterm.cpp
r21878 r22847 53 53 #include "VBox/com/com.h" 54 54 #include "VBox/com/assert.h" 55 #include "VBox/com/EventQueue.h" 55 56 56 57 #include "../include/Logging.h" … … 497 498 AssertComRC (rc); 498 499 500 EventQueue::init(); 501 499 502 return rc; 500 503 } … … 503 506 { 504 507 HRESULT rc = S_OK; 508 509 EventQueue::deinit(); 505 510 506 511 #if !defined (VBOX_WITH_XPCOM) -
trunk/src/libs/xpcom18a4/python/src/module/_xpcom.cpp
r22829 r22847 493 493 494 494 #ifdef VBOX 495 //#define USE_EVENTQUEUE 1 496 497 # ifdef USE_EVENTQUEUE 495 498 496 # include <VBox/com/EventQueue.h> 499 497 # include <iprt/err.h> 500 # else501 # include <iprt/cdefs.h>502 # endif503 504 static nsIEventQueue* g_mainEventQ = nsnull;505 506 # ifndef USE_EVENTQUEUE /** @todo Make USE_EVENTQUEUE default. */507 // Wrapper that checks if the queue has pending events.508 DECLINLINE(bool)509 hasEventQueuePendingEvents(nsIEventQueue *pQueue)510 {511 PRBool fHasEvents = PR_FALSE;512 nsresult rc = pQueue->PendingEvents(&fHasEvents);513 return NS_SUCCEEDED(rc) && fHasEvents ? true : false;514 }515 516 // Wrapper that checks if the queue is native or not.517 DECLINLINE(bool)518 isEventQueueNative(nsIEventQueue *pQueue)519 {520 PRBool fIsNative = PR_FALSE;521 nsresult rc = pQueue->IsQueueNative(&fIsNative);522 return NS_SUCCEEDED(rc) && fIsNative ? true : false;523 }524 525 # ifdef RT_OS_DARWIN526 # include <iprt/time.h>527 # include <iprt/thread.h>528 # include <iprt/err.h>529 # include <CoreFoundation/CFRunLoop.h>530 # if MAC_OS_X_VERSION_MAX_ALLOWED == 1040 /* ASSUMES this means we're using the 10.4 SDK. */531 # include <CarbonEvents.h>532 # endif533 534 // Common fallback for waiting (and maybe processing) events. Caller process535 // any pending events when 0 is returned.536 static nsresult537 waitForEventsCommonFallback(nsIEventQueue *pQueue, PRInt32 cMsTimeout)538 {539 if (cMsTimeout < 0) {540 // WaitForEvent probably does the trick here.541 PLEvent *pEvent = NULL;542 nsresult rc = -1;543 Py_BEGIN_ALLOW_THREADS;544 rc = pQueue->WaitForEvent(&pEvent);545 Py_END_ALLOW_THREADS;546 if (NS_SUCCEEDED(rc)) {547 pQueue->HandleEvent(pEvent);548 return 0;549 }550 } else {551 // Poll until time out or event is encountered. We have552 // no other choice here.553 uint64_t const StartMillTS = RTTimeMilliTS();554 for (;;)555 {556 // Any pending events?557 if (hasEventQueuePendingEvents(pQueue))558 return 0;559 560 // Work any native per-thread event loops for good measure.561 # ifdef RT_OS_DARWIN562 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, false /*returnAfterSourceHandled*/);563 # endif564 565 // Any pending events?566 if (hasEventQueuePendingEvents(pQueue))567 return 0;568 569 // Timed out?570 uint64_t cMsElapsed = RTTimeMilliTS() - StartMillTS;571 if (cMsElapsed > (uint32_t)cMsTimeout)572 break;573 574 // Sleep a bit; return 0 if interrupt (see the select code edition).575 uint32_t cMsLeft = (uint32_t)cMsTimeout - (uint32_t)cMsElapsed;576 int rc = RTThreadSleep(RT_MIN(cMsLeft, 250));577 if (rc == VERR_INTERRUPTED)578 return 0;579 }580 }581 582 return 1;583 }584 585 586 // Takes care of the waiting on darwin. Caller process any pending events when587 // 0 is returned.588 static nsresult589 waitForEventsOnDarwin(nsIEventQueue *pQueue, PRInt32 cMsTimeout)590 {591 // This deals with the common case where the caller is the main592 // application thread and the queue is a native one.593 if ( isEventQueueNative(pQueue)594 # if MAC_OS_X_VERSION_MAX_ALLOWED == 1040 /* ASSUMES this means we're using the 10.4 SDK. */595 && GetCurrentEventLoop() == GetMainEventLoop()596 # else597 && CFRunLoopGetMain() == CFRunLoopGetCurrent()598 # endif599 ) {600 OSStatus orc = -1;601 CFTimeInterval rdTimeout = cMsTimeout < 0602 ? 1.0e10603 : (double)cMsTimeout / 1000;604 Py_BEGIN_ALLOW_THREADS;605 orc = CFRunLoopRunInMode(kCFRunLoopDefaultMode, rdTimeout, true /*returnAfterSourceHandled*/);606 if (orc == kCFRunLoopRunHandledSource)607 orc = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, false /*returnAfterSourceHandled*/);608 Py_END_ALLOW_THREADS;609 if (!orc || orc == kCFRunLoopRunHandledSource)610 return 0;611 612 if (orc != kCFRunLoopRunTimedOut) {613 NS_WARNING("Unexpected status code from CFRunLoopRunInMode");614 RTThreadSleep(1); // throttle615 }616 617 return hasEventQueuePendingEvents(pQueue) ? 0 : 1;618 }619 620 // All native queus are driven by the main application loop... Use the621 // fallback for now.622 return waitForEventsCommonFallback(pQueue, cMsTimeout);623 }624 625 # endif /* RT_OS_DARWIN */626 # endif /* !USE_EVENTQUEUE */627 498 628 499 static PyObject* … … 634 505 return NULL; /** @todo throw exception */ 635 506 636 nsIEventQueue* q = g_mainEventQ;637 if (q == nsnull)638 return NULL; /** @todo throw exception */639 640 # ifdef USE_EVENTQUEUE641 507 int rc; 642 643 Py_BEGIN_ALLOW_THREADS; 644 rc = com::EventQueue::processThreadEventQueue(aTimeout < 0 ? RT_INDEFINITE_WAIT : (uint32_t)aTimeout); 645 Py_END_ALLOW_THREADS; 646 508 com::EventQueue* aEventQ = com::EventQueue::getMainEventQueue(); 509 NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue"); 510 if (!aEventQ) 511 return NULL; 512 513 Py_BEGIN_ALLOW_THREADS 514 rc = aEventQ->processEventQueue(aTimeout < 0 ? RT_INDEFINITE_WAIT : (uint32_t)aTimeout); 515 Py_END_ALLOW_THREADS 647 516 if (RT_SUCCESS(rc)) 648 517 return PyInt_FromLong(0); 518 649 519 if ( rc == VERR_TIMEOUT 650 520 || rc == VERR_INTERRUPTED) 651 521 return PyInt_FromLong(1); 652 return NULL; /** @todo throw exception */ 653 654 # else /* !USE_EVENTQUEUE */ 655 NS_WARN_IF_FALSE(isEventQueueNative(q), "The event queue must be native!"); 656 657 PRInt32 result = 0; 658 # ifdef RT_OS_DARWIN 659 if (aTimeout != 0 && !hasEventQueuePendingEvents(q)) 660 result = waitForEventsOnDarwin(q, aTimeout); 661 if (result == 0) 662 q->ProcessPendingEvents(); 663 664 # else /* !RT_OS_DARWIN */ 665 666 PRBool hasEvents = PR_FALSE; 667 nsresult rc; 668 PRInt32 fd; 669 670 if (aTimeout == 0) 671 goto ok; 672 673 rc = q->PendingEvents(&hasEvents); 674 if (NS_FAILED (rc)) 675 return NULL; 676 677 if (hasEvents) 678 goto ok; 679 680 fd = q->GetEventQueueSelectFD(); 681 if (fd < 0 && aTimeout < 0) 682 { 683 /* fallback */ 684 PLEvent *pEvent = NULL; 685 Py_BEGIN_ALLOW_THREADS 686 rc = q->WaitForEvent(&pEvent); 687 Py_END_ALLOW_THREADS 688 if (NS_SUCCEEDED(rc)) 689 q->HandleEvent(pEvent); 690 goto ok; 691 } 692 693 /* Cannot perform timed wait otherwise */ 694 if (fd < 0) 695 return NULL; 696 697 { 698 fd_set fdsetR, fdsetE; 699 struct timeval tv; 700 701 FD_ZERO(&fdsetR); 702 FD_SET(fd, &fdsetR); 703 704 fdsetE = fdsetR; 705 if (aTimeout > 0) 706 { 707 tv.tv_sec = (PRInt64)aTimeout / 1000; 708 tv.tv_usec = ((PRInt64)aTimeout % 1000) * 1000; 709 } 710 711 /** @todo: What to do for XPCOM platforms w/o select() ? */ 712 Py_BEGIN_ALLOW_THREADS; 713 int n = select(fd + 1, &fdsetR, NULL, &fdsetE, aTimeout < 0 ? NULL : &tv); 714 result = (n == 0) ? 1 : 0; 715 Py_END_ALLOW_THREADS; 716 } 717 ok: 718 q->ProcessPendingEvents(); 719 # endif /* !RT_OS_DARWIN */ 720 return PyInt_FromLong(result); 721 # endif /* !USE_EVENTQUEUE */ 722 } 723 724 PR_STATIC_CALLBACK(void *) PyHandleEvent(PLEvent *ev) 725 { 726 return nsnull; 727 } 728 729 PR_STATIC_CALLBACK(void) PyDestroyEvent(PLEvent *ev) 730 { 731 delete ev; 522 523 return NULL; /** @todo throw correct exception */ 732 524 } 733 525 … … 735 527 PyXPCOMMethod_InterruptWait(PyObject *self, PyObject *args) 736 528 { 737 nsIEventQueue* q = g_mainEventQ; 738 PRInt32 result = 0; 739 nsresult rc; 740 741 PLEvent *ev = new PLEvent(); 742 if (!ev) 743 { 744 result = 1; 745 goto done; 746 } 747 q->InitEvent (ev, NULL, PyHandleEvent, PyDestroyEvent); 748 rc = q->PostEvent (ev); 749 if (NS_FAILED(rc)) 750 { 751 result = 2; 752 goto done; 753 } 754 755 done: 756 return PyInt_FromLong(result); 529 com::EventQueue* aEventQ = com::EventQueue::getMainEventQueue(); 530 NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue"); 531 if (!aEventQ) 532 return NULL; 533 534 aEventQ->interruptEventQueueProcessing(); 535 536 return PyInt_FromLong(0); 757 537 } 758 538 … … 1004 784 rc = com::Initialize(); 1005 785 1006 if (NS_SUCCEEDED(rc))1007 {1008 NS_GetMainEventQ (&g_mainEventQ);1009 }1010 1011 786 init_xpcom(); 1012 787 } … … 1016 791 void deinitVBoxPython() 1017 792 { 1018 1019 if (g_mainEventQ)1020 NS_RELEASE(g_mainEventQ);1021 1022 793 com::Shutdown(); 1023 794 }
Note:
See TracChangeset
for help on using the changeset viewer.

