Changeset 22847 in vbox for trunk/src/libs/xpcom18a4/python
- Timestamp:
- Sep 8, 2009 8:37:54 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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.