Changeset 22687 in vbox for trunk/src/libs
- Timestamp:
- Sep 2, 2009 12:25:29 AM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 51800
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/xpcom18a4/python/src/module/_xpcom.cpp
r22394 r22687 496 496 static nsIEventQueue* g_mainEventQ = nsnull; 497 497 498 static PyObject* 498 # ifdef RT_OS_DARWIN 499 # include <iprt/time.h> 500 # include <iprt/thread.h> 501 # include <iprt/err.h> 502 # include <CarbonEvents.h> 503 504 // Wrapper that checks if the queue has pending events. 505 DECLINLINE(bool) 506 hasEventQueuePendingEvents(nsIEventQueue *pQueue) 507 { 508 PRBool fHasEvents = PR_FALSE; 509 nsresult rc = pQueue->PendingEvents(&fHasEvents); 510 return NS_SUCCEEDED(rc) && fHasEvents ? true : false; 511 } 512 513 // Wrapper that checks if the queue has pending events. 514 DECLINLINE(bool) 515 isEventQueueNative(nsIEventQueue *pQueue) 516 { 517 PRBool fIsNative = PR_FALSE; 518 nsresult rc = pQueue->IsQueueNative(&fIsNative); 519 return NS_SUCCEEDED(rc) && fIsNative ? true : false; 520 } 521 522 523 // Common fallback for waiting (and maybe processing) events. Caller process 524 // any pending events when 0 is returned. 525 static nsresult 526 waitForEventsCommonFallback(nsIEventQueue *pQueue, PRInt32 cMsTimeout) 527 { 528 if (cMsTimeout < 0) { 529 // WaitForEvent probably does the trick here. 530 PLEvent *pEvent = NULL; 531 nsresult rc = -1; 532 Py_BEGIN_ALLOW_THREADS; 533 rc = pQueue->WaitForEvent(&pEvent); 534 Py_END_ALLOW_THREADS; 535 if (NS_SUCCEEDED(rc)) { 536 pQueue->HandleEvent(pEvent); 537 return 0; 538 } 539 } else { 540 // Poll until time out or event is encountered. We have 541 // no other choice here. 542 uint64_t const StartMillTS = RTTimeMilliTS(); 543 for (;;) 544 { 545 // Any pending events? 546 if (hasEventQueuePendingEvents(pQueue)) 547 return 0; 548 549 // Work any native per-thread event loops for good measure. 550 # ifdef RT_OS_DARWIN 551 RunCurrentEventLoop(0.0005 /*sec*/); 552 # endif 553 554 // Any pending events? 555 if (hasEventQueuePendingEvents(pQueue)) 556 return 0; 557 558 // Timed out? 559 uint64_t cMsElapsed = RTTimeMilliTS() - StartMillTS; 560 if (cMsElapsed > (uint32_t)cMsTimeout) 561 break; 562 563 // Sleep a bit; return 0 if interrupt (see the select code edition). 564 uint32_t cMsLeft = (uint32_t)cMsTimeout - (uint32_t)cMsElapsed; 565 int rc = RTThreadSleep(RT_MIN(cMsLeft, 250)); 566 if (rc == VERR_INTERRUPTED) 567 return 0; 568 } 569 } 570 571 return 1; 572 } 573 574 575 // Takes care of the waiting on darwin. Caller process any pending events when 576 // 0 is returned. 577 static nsresult 578 waitForEventsOnDarwin(nsIEventQueue *pQueue, PRInt32 cMsTimeout) 579 { 580 // This deals with the common case where the caller is the main 581 // application thread and the queue is a native one. 582 if ( isEventQueueNative(pQueue) 583 && GetCurrentEventLoop() == GetMainEventLoop() 584 ) { 585 OSStatus orc = -1; 586 EventTimeout rdTimeout = cMsTimeout < 0 587 ? kEventDurationForever 588 : (double)cMsTimeout / 1000; 589 Py_BEGIN_ALLOW_THREADS; 590 orc = RunCurrentEventLoop(rdTimeout); 591 Py_END_ALLOW_THREADS; 592 if (!orc || orc == eventLoopQuitErr) 593 return 0; 594 595 if (orc != eventLoopTimedOutErr) { 596 NS_WARNING("Unexpected status code from RunCurrentEventLoop"); 597 RTThreadSleep(1); // throttle 598 } 599 600 return hasEventQueuePendingEvents(pQueue) ? 0 : 1; 601 } 602 603 // All native queus are driven by the main application loop... Use the 604 // fallback for now. 605 return waitForEventsCommonFallback(pQueue, cMsTimeout); 606 } 607 608 # endif /* RT_OS_DARWIN */ 609 610 static PyObject* 499 611 PyXPCOMMethod_WaitForEvents(PyObject *self, PyObject *args) 500 612 { … … 505 617 506 618 nsIEventQueue* q = g_mainEventQ; 619 if (q == nsnull) 620 return NULL; 621 622 NS_WARN_IF_FALSE(isEventQueueNative(q), "The event queue must be native!"); 623 624 PRInt32 result = 0; 625 # ifdef RT_OS_DARWIN 626 if (aTimeout != 0 && !hasEventQueuePendingEvents(q)) 627 result = waitForEventsOnDarwin(q, aTimeout); 628 if (result == 0) 629 q->ProcessPendingEvents(); 630 631 # else /* !RT_OS_DARWIN */ 632 507 633 PRBool hasEvents = PR_FALSE; 508 634 nsresult rc; 509 PRInt32 fd, result = 0; 510 511 if (q == nsnull) 512 return NULL; 635 PRInt32 fd; 513 636 514 637 if (aTimeout == 0) … … 521 644 if (hasEvents) 522 645 goto ok; 523 646 524 647 fd = q->GetEventQueueSelectFD(); 525 648 if (fd < 0 && aTimeout < 0) … … 537 660 /* Cannot perform timed wait otherwise */ 538 661 if (fd < 0) 539 #ifdef RT_OS_DARWIN540 /**541 * @todo: maybe need some way to implement timed wait on Darwin,542 * just return immediately instead543 */544 goto ok;545 #else546 662 return NULL; 547 #endif 548 663 549 664 { 550 665 fd_set fdsetR, fdsetE; 551 666 struct timeval tv; 552 667 553 668 FD_ZERO(&fdsetR); 554 669 FD_SET(fd, &fdsetR); … … 560 675 tv.tv_usec = ((PRInt64)aTimeout % 1000) * 1000; 561 676 } 562 677 563 678 /** @todo: What to do for XPCOM platforms w/o select() ? */ 564 679 Py_BEGIN_ALLOW_THREADS; … … 569 684 ok: 570 685 q->ProcessPendingEvents(); 686 # endif /* !RT_OS_DARWIN */ 571 687 572 688 return PyInt_FromLong(result); … … 583 699 } 584 700 585 static PyObject* 701 static PyObject* 586 702 PyXPCOMMethod_InterruptWait(PyObject *self, PyObject *args) 587 703 { … … 610 726 static void deinitVBoxPython(); 611 727 612 static PyObject* 728 static PyObject* 613 729 PyXPCOMMethod_DeinitCOM(PyObject *self, PyObject *args) 614 730 { … … 621 737 static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); 622 738 623 static PyObject* 739 static PyObject* 624 740 PyXPCOMMethod_AttachThread(PyObject *self, PyObject *args) 625 741 { … … 653 769 } 654 770 655 static PyObject* 771 static PyObject* 656 772 PyXPCOMMethod_DetachThread(PyObject *self, PyObject *args) 657 773 { … … 684 800 return PyInt_FromLong(result); 685 801 } 686 #endif 802 803 #endif /* VBOX */ 687 804 688 805 extern PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args); … … 863 980 } 864 981 865 static 982 static 866 983 void deinitVBoxPython() 867 984 { 868 985 869 986 if (g_mainEventQ) 870 NS_RELEASE(g_mainEventQ); 871 987 NS_RELEASE(g_mainEventQ); 988 872 989 com::Shutdown(); 873 990 } 874 #endif 991 992 #endif /* VBOX_PYXPCOM */
Note:
See TracChangeset
for help on using the changeset viewer.