- Timestamp:
- Oct 12, 2018 3:09:44 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/ExtPack/ExtPack.h
r74219 r74804 281 281 * @param pProgressOther Pointer to an IProgress object reference, the one 282 282 * to be waited for. 283 * @param cTimeoutMS Timeout in milliseconds, 0 for indefinite wait. 283 284 */ 284 285 DECLR3CALLBACKMEMBER(uint32_t, pfnWaitOtherProgress,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress, 285 VBOXEXTPACK_IF_CS(IProgress) *pProgressOther)); 286 VBOXEXTPACK_IF_CS(IProgress) *pProgressOther, 287 uint32_t cTimeoutMS)); 286 288 287 289 /** -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r74778 r74804 14269 14269 <interface 14270 14270 name="IProgress" extends="$unknown" 14271 uuid=" 64c7fb5c-ce8f-4681-9c8c-d523cb4dea3d"14271 uuid="d3ee3588-a762-4ba1-9e9e-23146587ed3a" 14272 14272 wsmap="managed" 14273 reservedMethods="1" reservedAttributes="2" 14273 wrap-hint-server-addinterfaces="IInternalProgressControl" 14274 reservedMethods="4" reservedAttributes="8" 14274 14275 > 14275 14276 <desc> … … 14408 14409 <attribute name="eventSource" type="IEventSource" readonly="yes"/> 14409 14410 14410 <method name="setCurrentOperationProgress">14411 <desc>Internal method, not to be called externally.</desc>14412 <param name="percent" type="unsigned long" dir="in" />14413 </method>14414 <method name="setNextOperation">14415 <desc>Internal method, not to be called externally.</desc>14416 <param name="nextOperationDescription" type="wstring" dir="in" />14417 <param name="nextOperationsWeight" type="unsigned long" dir="in" />14418 </method>14419 14420 14411 <method name="waitForCompletion"> 14421 14412 <desc> … … 14480 14471 14481 14472 </desc> 14473 </method> 14474 14475 </interface> 14476 14477 <interface 14478 name="IInternalProgressControl" extends="$unknown" 14479 uuid="9bf38c56-ac64-4f72-871a-321a25f52a57" 14480 internal="yes" 14481 wsmap="suppress" 14482 reservedMethods="4" reservedAttributes="8" 14483 > 14484 14485 <method name="setCurrentOperationProgress"> 14486 <desc>Internal method, not to be called externally.</desc> 14487 <param name="percent" type="unsigned long" dir="in" /> 14488 </method> 14489 14490 <method name="waitForOtherProgressCompletion"> 14491 <desc> 14492 Internal method, not to be called externally. 14493 14494 Waits until the other task is completed (including all sub-operations) 14495 and forward all changes from the other progress to this progress. This 14496 means sub-operation number, description, percent and so on. 14497 14498 The caller is responsible for having at least the same count of 14499 sub-operations in this progress object as there are in the other 14500 progress object. 14501 14502 If the other progress object supports cancel and this object gets any 14503 cancel request (when here enabled as well), it will be forwarded to 14504 the other progress object. 14505 14506 Error information is automatically preserved (by transferring it to 14507 the current thread's error information). If the caller wants to set it 14508 as the completion state of this progress it needs to be done separately. 14509 14510 <result name="VBOX_E_TIMEOUT"> 14511 Waiting time has expired. 14512 </result> 14513 </desc> 14514 <param name="progressOther" type="IProgress" dir="in" /> 14515 <param name="timeoutMS" type="unsigned long" dir="in"> 14516 <desc>Timeout (in ms). Pass 0 for an infinite timeout.</desc> 14517 </param> 14518 </method> 14519 14520 <method name="setNextOperation"> 14521 <desc>Internal method, not to be called externally.</desc> 14522 <param name="nextOperationDescription" type="wstring" dir="in" /> 14523 <param name="nextOperationsWeight" type="unsigned long" dir="in" /> 14524 </method> 14525 14526 <method name="notifyPointOfNoReturn"> 14527 <desc>Internal method, not to be called externally.</desc> 14528 </method> 14529 14530 <method name="notifyComplete"> 14531 <desc>Internal method, not to be called externally.</desc> 14532 <param name="resultCode" type="long" dir="in" /> 14533 <param name="errorInfo" type="IVirtualBoxErrorInfo" dir="in" /> 14482 14534 </method> 14483 14535 -
trunk/src/VBox/Main/include/ExtPackManagerImpl.h
r74219 r74804 163 163 uint32_t uNextOperationWeight); 164 164 static DECLCALLBACK(uint32_t) i_hlpWaitOtherProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress, 165 VBOXEXTPACK_IF_CS(IProgress) *pProgressOther); 165 VBOXEXTPACK_IF_CS(IProgress) *pProgressOther, 166 uint32_t cTimeoutMS); 166 167 static DECLCALLBACK(uint32_t) i_hlpCompleteProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress, 167 168 uint32_t uResultCode); -
trunk/src/VBox/Main/include/ProgressImpl.h
r73824 r74804 136 136 const char *aText, 137 137 va_list va); 138 HRESULT i_notifyCompleteEI(HRESULT aResultCode, 139 const ComPtr<IVirtualBoxErrorInfo> &aErrorInfo); 140 /** 141 * Waits until the other task is completed (including all sub-operations) 142 * and forward all changes from the other progress to this progress. This 143 * means sub-operation number, description, percent and so on. 144 * 145 * The caller is responsible for having at least the same count of 146 * sub-operations in this progress object as there are in the other 147 * progress object. 148 * 149 * If the other progress object supports cancel and this object gets any 150 * cancel request (when here enabled as well), it will be forwarded to 151 * the other progress object. 152 * 153 * Error information is automatically preserved (by transferring it to 154 * the current thread's error information). If the caller wants to set it 155 * as the completion state of this progress it needs to be done separately. 156 * 157 * @param aProgressOther Progress object from which the state is 158 * forwarded until it is signalling completion. 159 * @return COM error status, also reflecting the failed completion. 160 */ 161 HRESULT i_waitForOtherProgressCompletion(const ComPtr<IProgress> &aProgressOther); 162 163 bool i_notifyPointOfNoReturn(void); 138 164 139 bool i_setCancelCallback(void (*pfnCallback)(void *), void *pvUser); 165 140 … … 229 204 230 205 // wrapped IProgress methods 231 HRESULT setCurrentOperationProgress(ULONG aPercent);232 HRESULT setNextOperation(const com::Utf8Str &aNextOperationDescription,233 ULONG aNextOperationsWeight);234 206 HRESULT waitForCompletion(LONG aTimeout); 235 207 HRESULT waitForOperationCompletion(ULONG aOperation, … … 237 209 HRESULT cancel(); 238 210 211 // wrapped IInternalProgressControl methods 212 HRESULT setCurrentOperationProgress(ULONG aPercent); 213 HRESULT waitForOtherProgressCompletion(const ComPtr<IProgress> &aProgressOther, 214 ULONG aTimeoutMS); 215 HRESULT setNextOperation(const com::Utf8Str &aNextOperationDescription, 216 ULONG aNextOperationsWeight); 217 HRESULT notifyPointOfNoReturn(); 218 HRESULT notifyComplete(LONG aResultCode, 219 const ComPtr<IVirtualBoxErrorInfo> &aErrorInfo); 220 239 221 // internal helper methods 240 222 double i_calcTotalPercent(); -
trunk/src/VBox/Main/src-all/ExtPackManagerImpl.cpp
r74219 r74804 1810 1810 AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, (uint32_t)E_INVALIDARG); 1811 1811 1812 return pProgress->SetCurrentOperationProgress(uPercent); 1812 ComPtr<IInternalProgressControl> pProgressControl(pProgress); 1813 AssertReturn(!!pProgressControl, E_INVALIDARG); 1814 return pProgressControl->SetCurrentOperationProgress(uPercent); 1813 1815 } 1814 1816 … … 1828 1830 AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, (uint32_t)E_INVALIDARG); 1829 1831 1830 return pProgress->SetNextOperation(Bstr(pcszNextOperationDescription).raw(), uNextOperationWeight); 1832 ComPtr<IInternalProgressControl> pProgressControl(pProgress); 1833 AssertReturn(!!pProgressControl, E_INVALIDARG); 1834 return pProgressControl->SetNextOperation(Bstr(pcszNextOperationDescription).raw(), uNextOperationWeight); 1831 1835 } 1832 1836 1833 1837 /*static*/ DECLCALLBACK(uint32_t) 1834 1838 ExtPack::i_hlpWaitOtherProgress(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress, 1835 VBOXEXTPACK_IF_CS(IProgress) *pProgressOther )1839 VBOXEXTPACK_IF_CS(IProgress) *pProgressOther, uint32_t cTimeoutMS) 1836 1840 { 1837 1841 /* … … 1844 1848 AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, (uint32_t)E_INVALIDARG); 1845 1849 1846 Progress *pProgressInt = static_cast<Progress *>(pProgress); 1847 return pProgressInt->i_waitForOtherProgressCompletion(pProgressOther); 1850 ComPtr<IInternalProgressControl> pProgressControl(pProgress); 1851 AssertReturn(!!pProgressControl, E_INVALIDARG); 1852 return pProgressControl->WaitForOtherProgressCompletion(pProgressOther, cTimeoutMS); 1848 1853 } 1849 1854 … … 1860 1865 AssertReturn(pHlp->u32Version == VBOXEXTPACKHLP_VERSION, (uint32_t)E_INVALIDARG); 1861 1866 1862 Progress *pProgressInt = static_cast<Progress *>(pProgress); 1863 return pProgressInt->i_notifyComplete(uResultCode); 1867 ComPtr<IInternalProgressControl> pProgressControl(pProgress); 1868 AssertReturn(!!pProgressControl, E_INVALIDARG); 1869 1870 ComPtr<IVirtualBoxErrorInfo> errorInfo; 1871 if (FAILED((HRESULT)uResultCode)) 1872 { 1873 ErrorInfoKeeper eik; 1874 eik.getVirtualBoxErrorInfo(errorInfo); 1875 } 1876 return pProgressControl->NotifyComplete(uResultCode, errorInfo); 1864 1877 } 1865 1878 -
trunk/src/VBox/Main/src-all/ProgressImpl.cpp
r74759 r74804 370 370 } 371 371 372 return i_notifyCompleteEI(aResultCode, errorInfo);372 return notifyComplete(aResultCode, errorInfo); 373 373 } 374 374 … … 414 414 errorInfo->init(aResultCode, aIID, pcszComponent, text); 415 415 416 return i_notifyCompleteEI(aResultCode, errorInfo); 417 } 418 419 /** 420 * Marks the operation as complete and attaches full error info. 421 * 422 * This is where the actual work is done, the related methods all end up here. 423 * 424 * @param aResultCode Operation result (error) code, must not be S_OK. 425 * @param aErrorInfo List of arguments for the format string. 426 */ 427 HRESULT Progress::i_notifyCompleteEI(HRESULT aResultCode, const ComPtr<IVirtualBoxErrorInfo> &aErrorInfo) 428 { 429 LogThisFunc(("aResultCode=%d\n", aResultCode)); 430 /* on failure we expect error info, on success there must be none */ 431 AssertMsg(FAILED(aResultCode) ^ aErrorInfo.isNull(), 432 ("No error info but trying to set a failed result (%08X)!\n", 433 aResultCode)); 434 416 return notifyComplete(aResultCode, errorInfo); 417 } 418 419 /** 420 * Sets the cancelation callback, checking for cancelation first. 421 * 422 * @returns Success indicator. 423 * @retval true on success. 424 * @retval false if the progress object has already been canceled or is in an 425 * invalid state 426 * 427 * @param pfnCallback The function to be called upon cancelation. 428 * @param pvUser The callback argument. 429 */ 430 bool Progress::i_setCancelCallback(void (*pfnCallback)(void *), void *pvUser) 431 { 435 432 AutoCaller autoCaller(this); 436 AssertComRCReturn RC(autoCaller.rc());433 AssertComRCReturn(autoCaller.rc(), false); 437 434 438 435 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 439 436 440 AssertReturn(mCompleted == FALSE, E_FAIL); 441 442 if (mCanceled && SUCCEEDED(aResultCode)) 443 aResultCode = E_FAIL; 444 445 mCompleted = TRUE; 446 mResultCode = aResultCode; 447 if (SUCCEEDED(aResultCode)) 448 { 449 m_ulCurrentOperation = m_cOperations - 1; /* last operation */ 450 m_ulOperationPercent = 100; 451 } 452 mErrorInfo = aErrorInfo; 453 437 i_checkForAutomaticTimeout(); 438 if (mCanceled) 439 return false; 440 441 m_pvCancelUserArg = pvUser; 442 m_pfnCancelCallback = pfnCallback; 443 return true; 444 } 445 446 /** 447 * @callback_method_impl{FNRTPROGRESS, 448 * Works the progress of the current operation.} 449 */ 450 /*static*/ DECLCALLBACK(int) Progress::i_iprtProgressCallback(unsigned uPercentage, void *pvUser) 451 { 452 Progress *pThis = (Progress *)pvUser; 453 454 /* 455 * Same as setCurrentOperationProgress, except we don't fail on mCompleted. 456 */ 457 AutoWriteLock alock(pThis COMMA_LOCKVAL_SRC_POS); 458 int vrc = VINF_SUCCESS; 459 if (!pThis->mCompleted) 460 { 461 pThis->i_checkForAutomaticTimeout(); 462 if (!pThis->mCanceled) 463 { 464 if (uPercentage > pThis->m_ulOperationPercent) 465 pThis->setCurrentOperationProgress(uPercentage); 466 } 467 else 468 { 469 Assert(pThis->mCancelable); 470 vrc = VERR_CANCELLED; 471 } 472 } 473 /* else ignored */ 474 return vrc; 475 } 476 477 /** 478 * @callback_method_impl{FNVDPROGRESS, 479 * Progress::i_iprtProgressCallback with parameters switched around.} 480 */ 481 /*static*/ DECLCALLBACK(int) Progress::i_vdProgressCallback(void *pvUser, unsigned uPercentage) 482 { 483 return i_iprtProgressCallback(uPercentage, pvUser); 484 } 485 486 487 // IProgress properties 488 ///////////////////////////////////////////////////////////////////////////// 489 490 HRESULT Progress::getId(com::Guid &aId) 491 { 492 /* mId is constant during life time, no need to lock */ 493 aId = mId; 494 495 return S_OK; 496 } 497 498 HRESULT Progress::getDescription(com::Utf8Str &aDescription) 499 { 500 /* mDescription is constant during life time, no need to lock */ 501 aDescription = mDescription; 502 503 return S_OK; 504 } 505 HRESULT Progress::getInitiator(ComPtr<IUnknown> &aInitiator) 506 { 507 /* mInitiator/mParent are constant during life time, no need to lock */ 454 508 #if !defined(VBOX_COM_INPROC) 455 /* remove from the global collection of pending progress operations */ 456 if (mParent) 457 mParent->i_removeProgress(mId.ref()); 509 if (mInitiator) 510 mInitiator.queryInterfaceTo(aInitiator.asOutParam()); 511 else 512 { 513 ComObjPtr<VirtualBox> pVirtualBox(mParent); 514 pVirtualBox.queryInterfaceTo(aInitiator.asOutParam()); 515 } 516 #else 517 mInitiator.queryInterfaceTo(aInitiator.asOutParam()); 458 518 #endif 459 519 460 /* wake up all waiting threads */ 461 if (mWaitersCount > 0) 462 RTSemEventMultiSignal(mCompletedSem); 463 464 fireProgressTaskCompletedEvent(pEventSource, mId.toUtf16().raw()); 465 466 return S_OK; 467 } 468 469 HRESULT Progress::i_waitForOtherProgressCompletion(const ComPtr<IProgress> &aProgressOther) 520 return S_OK; 521 } 522 523 HRESULT Progress::getCancelable(BOOL *aCancelable) 524 { 525 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 526 527 *aCancelable = mCancelable; 528 529 return S_OK; 530 } 531 532 HRESULT Progress::getPercent(ULONG *aPercent) 533 { 534 /* i_checkForAutomaticTimeout requires a write lock. */ 535 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 536 537 if (mCompleted && SUCCEEDED(mResultCode)) 538 *aPercent = 100; 539 else 540 { 541 ULONG ulPercent = (ULONG)i_calcTotalPercent(); 542 // do not report 100% until we're really really done with everything 543 // as the Qt GUI dismisses progress dialogs in that case 544 if ( ulPercent == 100 545 && ( m_ulOperationPercent < 100 546 || (m_ulCurrentOperation < m_cOperations -1) 547 ) 548 ) 549 *aPercent = 99; 550 else 551 *aPercent = ulPercent; 552 } 553 554 i_checkForAutomaticTimeout(); 555 556 return S_OK; 557 } 558 559 HRESULT Progress::getTimeRemaining(LONG *aTimeRemaining) 560 { 561 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 562 563 if (mCompleted) 564 *aTimeRemaining = 0; 565 else 566 { 567 double dPercentDone = i_calcTotalPercent(); 568 if (dPercentDone < 1) 569 *aTimeRemaining = -1; // unreliable, or avoid division by 0 below 570 else 571 { 572 uint64_t ullTimeNow = RTTimeMilliTS(); 573 uint64_t ullTimeElapsed = ullTimeNow - m_ullTimestamp; 574 uint64_t ullTimeTotal = (uint64_t)((double)ullTimeElapsed * 100 / dPercentDone); 575 uint64_t ullTimeRemaining = ullTimeTotal - ullTimeElapsed; 576 577 // LogFunc(("dPercentDone = %RI32, ullTimeNow = %RI64, ullTimeElapsed = %RI64, ullTimeTotal = %RI64, ullTimeRemaining = %RI64\n", 578 // (uint32_t)dPercentDone, ullTimeNow, ullTimeElapsed, ullTimeTotal, ullTimeRemaining)); 579 580 *aTimeRemaining = (LONG)(ullTimeRemaining / 1000); 581 } 582 } 583 584 return S_OK; 585 } 586 587 HRESULT Progress::getCompleted(BOOL *aCompleted) 588 { 589 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 590 591 *aCompleted = mCompleted; 592 593 return S_OK; 594 } 595 596 HRESULT Progress::getCanceled(BOOL *aCanceled) 597 { 598 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 599 600 *aCanceled = mCanceled; 601 602 return S_OK; 603 } 604 605 HRESULT Progress::getResultCode(LONG *aResultCode) 606 { 607 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 608 609 if (!mCompleted) 610 return setError(E_FAIL, tr("Result code is not available, operation is still in progress")); 611 612 *aResultCode = mResultCode; 613 614 return S_OK; 615 } 616 617 HRESULT Progress::getErrorInfo(ComPtr<IVirtualBoxErrorInfo> &aErrorInfo) 618 { 619 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 620 621 if (!mCompleted) 622 return setError(E_FAIL, tr("Error info is not available, operation is still in progress")); 623 624 mErrorInfo.queryInterfaceTo(aErrorInfo.asOutParam()); 625 626 return S_OK; 627 } 628 629 HRESULT Progress::getOperationCount(ULONG *aOperationCount) 630 { 631 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 632 633 *aOperationCount = m_cOperations; 634 635 return S_OK; 636 } 637 638 HRESULT Progress::getOperation(ULONG *aOperation) 639 { 640 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 641 642 *aOperation = m_ulCurrentOperation; 643 644 return S_OK; 645 } 646 647 HRESULT Progress::getOperationDescription(com::Utf8Str &aOperationDescription) 648 { 649 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 650 651 aOperationDescription = m_operationDescription; 652 653 return S_OK; 654 } 655 656 HRESULT Progress::getOperationPercent(ULONG *aOperationPercent) 657 { 658 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 659 660 if (mCompleted && SUCCEEDED(mResultCode)) 661 *aOperationPercent = 100; 662 else 663 *aOperationPercent = m_ulOperationPercent; 664 665 return S_OK; 666 } 667 668 HRESULT Progress::getOperationWeight(ULONG *aOperationWeight) 669 { 670 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 671 672 *aOperationWeight = m_ulCurrentOperationWeight; 673 674 return S_OK; 675 } 676 677 HRESULT Progress::getTimeout(ULONG *aTimeout) 678 { 679 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 680 681 *aTimeout = m_cMsTimeout; 682 683 return S_OK; 684 } 685 686 HRESULT Progress::setTimeout(ULONG aTimeout) 687 { 688 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 689 690 if (!mCancelable) 691 return setError(VBOX_E_INVALID_OBJECT_STATE, tr("Operation cannot be canceled")); 692 m_cMsTimeout = aTimeout; 693 694 return S_OK; 695 } 696 697 HRESULT Progress::getEventSource(ComPtr<IEventSource> &aEventSource) 698 { 699 /* event source is const, no need to lock */ 700 pEventSource.queryInterfaceTo(aEventSource.asOutParam()); 701 return S_OK; 702 } 703 704 705 // IProgress methods 706 ///////////////////////////////////////////////////////////////////////////// 707 708 /** 709 * @note XPCOM: when this method is not called on the main XPCOM thread, it 710 * simply blocks the thread until mCompletedSem is signalled. If the 711 * thread has its own event queue (hmm, what for?) that it must run, then 712 * calling this method will definitely freeze event processing. 713 */ 714 HRESULT Progress::waitForCompletion(LONG aTimeout) 715 { 716 LogFlowThisFuncEnter(); 717 LogFlowThisFunc(("aTimeout=%d\n", aTimeout)); 718 719 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 720 721 /* if we're already completed, take a shortcut */ 722 if (!mCompleted) 723 { 724 int vrc = VINF_SUCCESS; 725 bool fForever = aTimeout < 0; 726 int64_t timeLeft = aTimeout; 727 int64_t lastTime = RTTimeMilliTS(); 728 729 while (!mCompleted && (fForever || timeLeft > 0)) 730 { 731 mWaitersCount++; 732 alock.release(); 733 vrc = RTSemEventMultiWait(mCompletedSem, 734 fForever ? RT_INDEFINITE_WAIT : (RTMSINTERVAL)timeLeft); 735 alock.acquire(); 736 mWaitersCount--; 737 738 /* the last waiter resets the semaphore */ 739 if (mWaitersCount == 0) 740 RTSemEventMultiReset(mCompletedSem); 741 742 if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT) 743 break; 744 745 if (!fForever) 746 { 747 int64_t now = RTTimeMilliTS(); 748 timeLeft -= now - lastTime; 749 lastTime = now; 750 } 751 } 752 753 if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT) 754 return setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Failed to wait for the task completion (%Rrc)"), vrc); 755 } 756 757 LogFlowThisFuncLeave(); 758 759 return S_OK; 760 } 761 762 /** 763 * @note XPCOM: when this method is not called on the main XPCOM thread, it 764 * simply blocks the thread until mCompletedSem is signalled. If the 765 * thread has its own event queue (hmm, what for?) that it must run, then 766 * calling this method will definitely freeze event processing. 767 */ 768 HRESULT Progress::waitForOperationCompletion(ULONG aOperation, LONG aTimeout) 769 770 { 771 LogFlowThisFuncEnter(); 772 LogFlowThisFunc(("aOperation=%d, aTimeout=%d\n", aOperation, aTimeout)); 773 774 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 775 776 CheckComArgExpr(aOperation, aOperation < m_cOperations); 777 778 /* if we're already completed or if the given operation is already done, 779 * then take a shortcut */ 780 if ( !mCompleted 781 && aOperation >= m_ulCurrentOperation) 782 { 783 int vrc = VINF_SUCCESS; 784 bool fForever = aTimeout < 0; 785 int64_t timeLeft = aTimeout; 786 int64_t lastTime = RTTimeMilliTS(); 787 788 while ( !mCompleted && aOperation >= m_ulCurrentOperation 789 && (fForever || timeLeft > 0)) 790 { 791 mWaitersCount ++; 792 alock.release(); 793 vrc = RTSemEventMultiWait(mCompletedSem, 794 fForever ? RT_INDEFINITE_WAIT : (unsigned) timeLeft); 795 alock.acquire(); 796 mWaitersCount--; 797 798 /* the last waiter resets the semaphore */ 799 if (mWaitersCount == 0) 800 RTSemEventMultiReset(mCompletedSem); 801 802 if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT) 803 break; 804 805 if (!fForever) 806 { 807 int64_t now = RTTimeMilliTS(); 808 timeLeft -= now - lastTime; 809 lastTime = now; 810 } 811 } 812 813 if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT) 814 return setErrorBoth(E_FAIL, vrc, tr("Failed to wait for the operation completion (%Rrc)"), vrc); 815 } 816 817 LogFlowThisFuncLeave(); 818 819 return S_OK; 820 } 821 822 HRESULT Progress::cancel() 823 { 824 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 825 826 if (!mCancelable) 827 return setError(VBOX_E_INVALID_OBJECT_STATE, tr("Operation cannot be canceled")); 828 829 if (!mCanceled) 830 { 831 LogThisFunc(("Canceling\n")); 832 mCanceled = TRUE; 833 if (m_pfnCancelCallback) 834 m_pfnCancelCallback(m_pvCancelUserArg); 835 836 } 837 else 838 LogThisFunc(("Already canceled\n")); 839 840 return S_OK; 841 } 842 843 844 // IInternalProgressControl methods 845 ///////////////////////////////////////////////////////////////////////////// 846 847 /** 848 * Updates the percentage value of the current operation. 849 * 850 * @param aPercent New percentage value of the operation in progress 851 * (in range [0, 100]). 852 */ 853 HRESULT Progress::setCurrentOperationProgress(ULONG aPercent) 854 { 855 AssertMsgReturn(aPercent <= 100, ("%u\n", aPercent), E_INVALIDARG); 856 857 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 858 859 i_checkForAutomaticTimeout(); 860 if (mCancelable && mCanceled) 861 AssertReturn(!mCompleted, E_FAIL); 862 AssertReturn(!mCompleted && !mCanceled, E_FAIL); 863 864 if (m_ulOperationPercent != aPercent) 865 { 866 m_ulOperationPercent = aPercent; 867 ULONG actualPercent = 0; 868 getPercent(&actualPercent); 869 fireProgressPercentageChangedEvent(pEventSource, mId.toUtf16().raw(), actualPercent); 870 } 871 872 return S_OK; 873 } 874 875 HRESULT Progress::waitForOtherProgressCompletion(const ComPtr<IProgress> &aProgressOther, 876 ULONG aTimeoutMS) 470 877 { 471 878 LogFlowThisFuncEnter(); … … 483 890 rc = aProgressOther->COMGETTER(Cancelable)(&fCancelable); 484 891 if (FAILED(rc)) return rc; 892 893 uint64_t u64StopTime = UINT64_MAX; 894 if (aTimeoutMS > 0) 895 u64StopTime = RTTimeMilliTS() + aTimeoutMS; 485 896 /* Loop as long as the sync process isn't completed. */ 486 897 while (SUCCEEDED(aProgressOther->COMGETTER(Completed(&fCompleted)))) … … 541 952 break; 542 953 543 /* Make sure the loop is not too tight */ 544 rc = aProgressOther->WaitForCompletion(100); 545 if (FAILED(rc)) return rc; 954 if (aTimeoutMS != 0) 955 { 956 /* Make sure the loop is not too tight */ 957 uint64_t u64Now = RTTimeMilliTS(); 958 uint64_t u64RemainingMS = u64StopTime - u64Now; 959 if (u64RemainingMS < 10) 960 u64RemainingMS = 10; 961 else if (u64RemainingMS > 200) 962 u64RemainingMS = 200; 963 rc = aProgressOther->WaitForCompletion((LONG)u64RemainingMS); 964 if (FAILED(rc)) return rc; 965 966 if (RTTimeMilliTS() >= u64StopTime) 967 return VBOX_E_TIMEOUT; 968 } 969 else 970 { 971 /* Make sure the loop is not too tight */ 972 rc = aProgressOther->WaitForCompletion(200); 973 if (FAILED(rc)) return rc; 974 } 546 975 } 547 976 … … 562 991 563 992 /** 993 * Signals that the current operation is successfully completed and advances to 994 * the next operation. The operation percentage is reset to 0. 995 * 996 * @param aNextOperationDescription Description of the next operation. 997 * @param aNextOperationsWeight Weight of the next operation. 998 * 999 * @note The current operation must not be the last one. 1000 */ 1001 HRESULT Progress::setNextOperation(const com::Utf8Str &aNextOperationDescription, ULONG aNextOperationsWeight) 1002 { 1003 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1004 1005 if (mCanceled) 1006 return E_FAIL; 1007 AssertReturn(!mCompleted, E_FAIL); 1008 AssertReturn(m_ulCurrentOperation + 1 < m_cOperations, E_FAIL); 1009 1010 ++m_ulCurrentOperation; 1011 m_ulOperationsCompletedWeight += m_ulCurrentOperationWeight; 1012 1013 m_operationDescription = aNextOperationDescription; 1014 m_ulCurrentOperationWeight = aNextOperationsWeight; 1015 m_ulOperationPercent = 0; 1016 1017 LogThisFunc(("%s: aNextOperationsWeight = %d; m_ulCurrentOperation is now %d, m_ulOperationsCompletedWeight is now %d\n", 1018 m_operationDescription.c_str(), aNextOperationsWeight, m_ulCurrentOperation, m_ulOperationsCompletedWeight)); 1019 1020 /* wake up all waiting threads */ 1021 if (mWaitersCount > 0) 1022 RTSemEventMultiSignal(mCompletedSem); 1023 1024 ULONG actualPercent = 0; 1025 getPercent(&actualPercent); 1026 fireProgressPercentageChangedEvent(pEventSource, mId.toUtf16().raw(), actualPercent); 1027 1028 return S_OK; 1029 } 1030 1031 /** 564 1032 * Notify the progress object that we're almost at the point of no return. 565 1033 * … … 570 1038 * user believe it was rolled back. 571 1039 * 572 * @returns Success indicator.573 * @retval trueon success.574 * @retval falseif the progress object has already been canceled or is in an1040 * @returns COM error status. 1041 * @retval S_OK on success. 1042 * @retval E_FAIL if the progress object has already been canceled or is in an 575 1043 * invalid state 576 1044 */ 577 bool Progress::i_notifyPointOfNoReturn(void) 578 { 579 AutoCaller autoCaller(this); 580 AssertComRCReturn(autoCaller.rc(), false); 581 1045 HRESULT Progress::notifyPointOfNoReturn(void) 1046 { 582 1047 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 583 1048 584 1049 if (mCanceled) 585 1050 { 586 LogThisFunc(("returns fa lse\n"));587 return false;1051 LogThisFunc(("returns failure\n")); 1052 return E_FAIL; 588 1053 } 589 1054 590 1055 mCancelable = FALSE; 591 LogThisFunc(("returns true\n"));592 return true;593 } 594 595 /** 596 * Sets the cancelation callback, checking for cancelation first.597 * 598 * @returns Success indicator.599 * @retval true on success.600 * @ retval false if the progress object has already been canceled or is in an601 * invalid state602 * 603 * @param pfnCallback The function to be called upon cancelation. 604 * @param pvUser The callback argument. 605 */606 bool Progress::i_setCancelCallback(void (*pfnCallback)(void *), void *pvUser) 607 { 608 AutoCaller autoCaller(this);609 AssertComRCReturn(autoCaller.rc(), false);1056 LogThisFunc(("returns success\n")); 1057 return S_OK; 1058 } 1059 1060 /** 1061 * Marks the operation as complete and attaches full error info. 1062 * 1063 * This is where the actual work is done, the related methods all end up here. 1064 * 1065 * @param aResultCode Operation result (error) code, must not be S_OK. 1066 * @param aErrorInfo List of arguments for the format string. 1067 */ 1068 HRESULT Progress::notifyComplete(LONG aResultCode, const ComPtr<IVirtualBoxErrorInfo> &aErrorInfo) 1069 { 1070 LogThisFunc(("aResultCode=%d\n", aResultCode)); 1071 /* on failure we expect error info, on success there must be none */ 1072 AssertMsg(FAILED(aResultCode) ^ aErrorInfo.isNull(), 1073 ("No error info but trying to set a failed result (%08X)!\n", 1074 aResultCode)); 610 1075 611 1076 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 612 1077 613 i_checkForAutomaticTimeout(); 614 if (mCanceled) 615 return false; 616 617 m_pvCancelUserArg = pvUser; 618 m_pfnCancelCallback = pfnCallback; 619 return true; 620 } 621 622 /** 623 * @callback_method_impl{FNRTPROGRESS, 624 * Works the progress of the current operation.} 625 */ 626 /*static*/ DECLCALLBACK(int) Progress::i_iprtProgressCallback(unsigned uPercentage, void *pvUser) 627 { 628 Progress *pThis = (Progress *)pvUser; 629 630 /* 631 * Same as setCurrentOperationProgress, except we don't fail on mCompleted. 632 */ 633 AutoWriteLock alock(pThis COMMA_LOCKVAL_SRC_POS); 634 int vrc = VINF_SUCCESS; 635 if (!pThis->mCompleted) 636 { 637 pThis->i_checkForAutomaticTimeout(); 638 if (!pThis->mCanceled) 639 { 640 if (uPercentage > pThis->m_ulOperationPercent) 641 pThis->setCurrentOperationProgress(uPercentage); 642 } 643 else 644 { 645 Assert(pThis->mCancelable); 646 vrc = VERR_CANCELLED; 647 } 648 } 649 /* else ignored */ 650 return vrc; 651 } 652 653 /** 654 * @callback_method_impl{FNVDPROGRESS, 655 * Progress::i_iprtProgressCallback with parameters switched around.} 656 */ 657 /*static*/ DECLCALLBACK(int) Progress::i_vdProgressCallback(void *pvUser, unsigned uPercentage) 658 { 659 return i_iprtProgressCallback(uPercentage, pvUser); 660 } 661 662 // IProgress properties 663 ///////////////////////////////////////////////////////////////////////////// 664 665 HRESULT Progress::getId(com::Guid &aId) 666 { 667 /* mId is constant during life time, no need to lock */ 668 aId = mId; 669 670 return S_OK; 671 } 672 673 HRESULT Progress::getDescription(com::Utf8Str &aDescription) 674 { 675 /* mDescription is constant during life time, no need to lock */ 676 aDescription = mDescription; 677 678 return S_OK; 679 } 680 HRESULT Progress::getInitiator(ComPtr<IUnknown> &aInitiator) 681 { 682 /* mInitiator/mParent are constant during life time, no need to lock */ 1078 AssertReturn(mCompleted == FALSE, E_FAIL); 1079 1080 if (mCanceled && SUCCEEDED(aResultCode)) 1081 aResultCode = E_FAIL; 1082 1083 mCompleted = TRUE; 1084 mResultCode = aResultCode; 1085 if (SUCCEEDED(aResultCode)) 1086 { 1087 m_ulCurrentOperation = m_cOperations - 1; /* last operation */ 1088 m_ulOperationPercent = 100; 1089 } 1090 mErrorInfo = aErrorInfo; 1091 683 1092 #if !defined(VBOX_COM_INPROC) 684 if (mInitiator) 685 mInitiator.queryInterfaceTo(aInitiator.asOutParam()); 686 else 687 { 688 ComObjPtr<VirtualBox> pVirtualBox(mParent); 689 pVirtualBox.queryInterfaceTo(aInitiator.asOutParam()); 690 } 691 #else 692 mInitiator.queryInterfaceTo(aInitiator.asOutParam()); 1093 /* remove from the global collection of pending progress operations */ 1094 if (mParent) 1095 mParent->i_removeProgress(mId.ref()); 693 1096 #endif 694 695 return S_OK;696 }697 698 HRESULT Progress::getCancelable(BOOL *aCancelable)699 {700 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);701 702 *aCancelable = mCancelable;703 704 return S_OK;705 }706 707 HRESULT Progress::getPercent(ULONG *aPercent)708 {709 /* i_checkForAutomaticTimeout requires a write lock. */710 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);711 712 if (mCompleted && SUCCEEDED(mResultCode))713 *aPercent = 100;714 else715 {716 ULONG ulPercent = (ULONG)i_calcTotalPercent();717 // do not report 100% until we're really really done with everything718 // as the Qt GUI dismisses progress dialogs in that case719 if ( ulPercent == 100720 && ( m_ulOperationPercent < 100721 || (m_ulCurrentOperation < m_cOperations -1)722 )723 )724 *aPercent = 99;725 else726 *aPercent = ulPercent;727 }728 729 i_checkForAutomaticTimeout();730 731 return S_OK;732 }733 734 HRESULT Progress::getTimeRemaining(LONG *aTimeRemaining)735 {736 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);737 738 if (mCompleted)739 *aTimeRemaining = 0;740 else741 {742 double dPercentDone = i_calcTotalPercent();743 if (dPercentDone < 1)744 *aTimeRemaining = -1; // unreliable, or avoid division by 0 below745 else746 {747 uint64_t ullTimeNow = RTTimeMilliTS();748 uint64_t ullTimeElapsed = ullTimeNow - m_ullTimestamp;749 uint64_t ullTimeTotal = (uint64_t)((double)ullTimeElapsed * 100 / dPercentDone);750 uint64_t ullTimeRemaining = ullTimeTotal - ullTimeElapsed;751 752 // LogFunc(("dPercentDone = %RI32, ullTimeNow = %RI64, ullTimeElapsed = %RI64, ullTimeTotal = %RI64, ullTimeRemaining = %RI64\n",753 // (uint32_t)dPercentDone, ullTimeNow, ullTimeElapsed, ullTimeTotal, ullTimeRemaining));754 755 *aTimeRemaining = (LONG)(ullTimeRemaining / 1000);756 }757 }758 759 return S_OK;760 }761 762 HRESULT Progress::getCompleted(BOOL *aCompleted)763 {764 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);765 766 *aCompleted = mCompleted;767 768 return S_OK;769 }770 771 HRESULT Progress::getCanceled(BOOL *aCanceled)772 {773 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);774 775 *aCanceled = mCanceled;776 777 return S_OK;778 }779 780 HRESULT Progress::getResultCode(LONG *aResultCode)781 {782 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);783 784 if (!mCompleted)785 return setError(E_FAIL, tr("Result code is not available, operation is still in progress"));786 787 *aResultCode = mResultCode;788 789 return S_OK;790 }791 792 HRESULT Progress::getErrorInfo(ComPtr<IVirtualBoxErrorInfo> &aErrorInfo)793 {794 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);795 796 if (!mCompleted)797 return setError(E_FAIL, tr("Error info is not available, operation is still in progress"));798 799 mErrorInfo.queryInterfaceTo(aErrorInfo.asOutParam());800 801 return S_OK;802 }803 804 HRESULT Progress::getOperationCount(ULONG *aOperationCount)805 {806 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);807 808 *aOperationCount = m_cOperations;809 810 return S_OK;811 }812 813 HRESULT Progress::getOperation(ULONG *aOperation)814 {815 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);816 817 *aOperation = m_ulCurrentOperation;818 819 return S_OK;820 }821 822 HRESULT Progress::getOperationDescription(com::Utf8Str &aOperationDescription)823 {824 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);825 826 aOperationDescription = m_operationDescription;827 828 return S_OK;829 }830 831 HRESULT Progress::getOperationPercent(ULONG *aOperationPercent)832 {833 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);834 835 if (mCompleted && SUCCEEDED(mResultCode))836 *aOperationPercent = 100;837 else838 *aOperationPercent = m_ulOperationPercent;839 840 return S_OK;841 }842 843 HRESULT Progress::getOperationWeight(ULONG *aOperationWeight)844 {845 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);846 847 *aOperationWeight = m_ulCurrentOperationWeight;848 849 return S_OK;850 }851 852 HRESULT Progress::getTimeout(ULONG *aTimeout)853 {854 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);855 856 *aTimeout = m_cMsTimeout;857 858 return S_OK;859 }860 861 HRESULT Progress::setTimeout(ULONG aTimeout)862 {863 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);864 865 if (!mCancelable)866 return setError(VBOX_E_INVALID_OBJECT_STATE, tr("Operation cannot be canceled"));867 m_cMsTimeout = aTimeout;868 869 return S_OK;870 }871 872 873 // IProgress methods874 /////////////////////////////////////////////////////////////////////////////875 876 /**877 * Updates the percentage value of the current operation.878 *879 * @param aPercent New percentage value of the operation in progress880 * (in range [0, 100]).881 */882 HRESULT Progress::setCurrentOperationProgress(ULONG aPercent)883 {884 AssertMsgReturn(aPercent <= 100, ("%u\n", aPercent), E_INVALIDARG);885 886 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);887 888 i_checkForAutomaticTimeout();889 if (mCancelable && mCanceled)890 AssertReturn(!mCompleted, E_FAIL);891 AssertReturn(!mCompleted && !mCanceled, E_FAIL);892 893 if (m_ulOperationPercent != aPercent)894 {895 m_ulOperationPercent = aPercent;896 ULONG actualPercent = 0;897 getPercent(&actualPercent);898 fireProgressPercentageChangedEvent(pEventSource, mId.toUtf16().raw(), actualPercent);899 }900 901 return S_OK;902 }903 904 /**905 * Signals that the current operation is successfully completed and advances to906 * the next operation. The operation percentage is reset to 0.907 *908 * @param aNextOperationDescription Description of the next operation.909 * @param aNextOperationsWeight Weight of the next operation.910 *911 * @note The current operation must not be the last one.912 */913 HRESULT Progress::setNextOperation(const com::Utf8Str &aNextOperationDescription, ULONG aNextOperationsWeight)914 {915 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);916 917 if (mCanceled)918 return E_FAIL;919 AssertReturn(!mCompleted, E_FAIL);920 AssertReturn(m_ulCurrentOperation + 1 < m_cOperations, E_FAIL);921 922 ++m_ulCurrentOperation;923 m_ulOperationsCompletedWeight += m_ulCurrentOperationWeight;924 925 m_operationDescription = aNextOperationDescription;926 m_ulCurrentOperationWeight = aNextOperationsWeight;927 m_ulOperationPercent = 0;928 929 LogThisFunc(("%s: aNextOperationsWeight = %d; m_ulCurrentOperation is now %d, m_ulOperationsCompletedWeight is now %d\n",930 m_operationDescription.c_str(), aNextOperationsWeight, m_ulCurrentOperation, m_ulOperationsCompletedWeight));931 1097 932 1098 /* wake up all waiting threads */ … … 934 1100 RTSemEventMultiSignal(mCompletedSem); 935 1101 936 ULONG actualPercent = 0; 937 getPercent(&actualPercent); 938 fireProgressPercentageChangedEvent(pEventSource, mId.toUtf16().raw(), actualPercent); 939 940 return S_OK; 941 } 942 943 /** 944 * @note XPCOM: when this method is not called on the main XPCOM thread, it 945 * simply blocks the thread until mCompletedSem is signalled. If the 946 * thread has its own event queue (hmm, what for?) that it must run, then 947 * calling this method will definitely freeze event processing. 948 */ 949 HRESULT Progress::waitForCompletion(LONG aTimeout) 950 { 951 LogFlowThisFuncEnter(); 952 LogFlowThisFunc(("aTimeout=%d\n", aTimeout)); 953 954 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 955 956 /* if we're already completed, take a shortcut */ 957 if (!mCompleted) 958 { 959 int vrc = VINF_SUCCESS; 960 bool fForever = aTimeout < 0; 961 int64_t timeLeft = aTimeout; 962 int64_t lastTime = RTTimeMilliTS(); 963 964 while (!mCompleted && (fForever || timeLeft > 0)) 965 { 966 mWaitersCount++; 967 alock.release(); 968 vrc = RTSemEventMultiWait(mCompletedSem, 969 fForever ? RT_INDEFINITE_WAIT : (RTMSINTERVAL)timeLeft); 970 alock.acquire(); 971 mWaitersCount--; 972 973 /* the last waiter resets the semaphore */ 974 if (mWaitersCount == 0) 975 RTSemEventMultiReset(mCompletedSem); 976 977 if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT) 978 break; 979 980 if (!fForever) 981 { 982 int64_t now = RTTimeMilliTS(); 983 timeLeft -= now - lastTime; 984 lastTime = now; 985 } 986 } 987 988 if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT) 989 return setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Failed to wait for the task completion (%Rrc)"), vrc); 990 } 991 992 LogFlowThisFuncLeave(); 993 994 return S_OK; 995 } 996 997 /** 998 * @note XPCOM: when this method is not called on the main XPCOM thread, it 999 * simply blocks the thread until mCompletedSem is signalled. If the 1000 * thread has its own event queue (hmm, what for?) that it must run, then 1001 * calling this method will definitely freeze event processing. 1002 */ 1003 HRESULT Progress::waitForOperationCompletion(ULONG aOperation, LONG aTimeout) 1004 1005 { 1006 LogFlowThisFuncEnter(); 1007 LogFlowThisFunc(("aOperation=%d, aTimeout=%d\n", aOperation, aTimeout)); 1008 1009 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1010 1011 CheckComArgExpr(aOperation, aOperation < m_cOperations); 1012 1013 /* if we're already completed or if the given operation is already done, 1014 * then take a shortcut */ 1015 if ( !mCompleted 1016 && aOperation >= m_ulCurrentOperation) 1017 { 1018 int vrc = VINF_SUCCESS; 1019 bool fForever = aTimeout < 0; 1020 int64_t timeLeft = aTimeout; 1021 int64_t lastTime = RTTimeMilliTS(); 1022 1023 while ( !mCompleted && aOperation >= m_ulCurrentOperation 1024 && (fForever || timeLeft > 0)) 1025 { 1026 mWaitersCount ++; 1027 alock.release(); 1028 vrc = RTSemEventMultiWait(mCompletedSem, 1029 fForever ? RT_INDEFINITE_WAIT : (unsigned) timeLeft); 1030 alock.acquire(); 1031 mWaitersCount--; 1032 1033 /* the last waiter resets the semaphore */ 1034 if (mWaitersCount == 0) 1035 RTSemEventMultiReset(mCompletedSem); 1036 1037 if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT) 1038 break; 1039 1040 if (!fForever) 1041 { 1042 int64_t now = RTTimeMilliTS(); 1043 timeLeft -= now - lastTime; 1044 lastTime = now; 1045 } 1046 } 1047 1048 if (RT_FAILURE(vrc) && vrc != VERR_TIMEOUT) 1049 return setErrorBoth(E_FAIL, vrc, tr("Failed to wait for the operation completion (%Rrc)"), vrc); 1050 } 1051 1052 LogFlowThisFuncLeave(); 1053 1054 return S_OK; 1055 } 1056 1057 HRESULT Progress::cancel() 1058 { 1059 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 1060 1061 if (!mCancelable) 1062 return setError(VBOX_E_INVALID_OBJECT_STATE, tr("Operation cannot be canceled")); 1063 1064 if (!mCanceled) 1065 { 1066 LogThisFunc(("Canceling\n")); 1067 mCanceled = TRUE; 1068 if (m_pfnCancelCallback) 1069 m_pfnCancelCallback(m_pvCancelUserArg); 1070 1071 } 1072 else 1073 LogThisFunc(("Already canceled\n")); 1074 1075 return S_OK; 1076 } 1077 1078 HRESULT Progress::getEventSource(ComPtr<IEventSource> &aEventSource) 1079 { 1080 /* event source is const, no need to lock */ 1081 pEventSource.queryInterfaceTo(aEventSource.asOutParam()); 1082 return S_OK; 1083 } 1102 fireProgressTaskCompletedEvent(pEventSource, mId.toUtf16().raw()); 1103 1104 return S_OK; 1105 } 1106 1084 1107 1085 1108 // private internal helpers -
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r74765 r74804 6239 6239 IProgress *pProgress = static_cast<IProgress *>(pvUser); 6240 6240 if (pProgress) 6241 rc = pProgress->SetCurrentOperationProgress(uPercentage); 6241 { 6242 ComPtr<IInternalProgressControl> pProgressControl(pProgress); 6243 AssertReturn(!!pProgressControl, VERR_INVALID_PARAMETER); 6244 rc = pProgressControl->SetCurrentOperationProgress(uPercentage); 6245 } 6242 6246 return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_GENERAL_FAILURE; 6243 6247 } … … 7855 7859 AssertComRCReturnRC(autoCaller.rc()); 7856 7860 7861 ComPtr<IInternalProgressControl> pProgressControl(aProgress); 7862 7857 7863 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 7858 7864 … … 7947 7953 7948 7954 /* advance percent count */ 7949 if ( aProgress)7950 aProgress->SetCurrentOperationProgress(99 * (++step) / StepCount);7955 if (pProgressControl) 7956 pProgressControl->SetCurrentOperationProgress(99 * (++step) / StepCount); 7951 7957 7952 7958 … … 7976 7982 7977 7983 /* advance percent count */ 7978 if ( aProgress)7979 aProgress->SetCurrentOperationProgress(99 * (++step) / StepCount);7984 if (pProgressControl) 7985 pProgressControl->SetCurrentOperationProgress(99 * (++step) / StepCount); 7980 7986 7981 7987 vrc = VINF_SUCCESS; … … 8001 8007 8002 8008 /* advance percent count */ 8003 if ( aProgress)8004 aProgress->SetCurrentOperationProgress(99 * (++step) / StepCount);8009 if (pProgressControl) 8010 pProgressControl->SetCurrentOperationProgress(99 * (++step) / StepCount); 8005 8011 8006 8012 #ifdef VBOX_WITH_HGCM … … 8019 8025 8020 8026 /* advance percent count */ 8021 if ( aProgress)8022 aProgress->SetCurrentOperationProgress(99 * (++step) / StepCount);8027 if (pProgressControl) 8028 pProgressControl->SetCurrentOperationProgress(99 * (++step) / StepCount); 8023 8029 8024 8030 #endif /* VBOX_WITH_HGCM */ … … 8061 8067 8062 8068 /* advance percent count */ 8063 if ( aProgress)8064 aProgress->SetCurrentOperationProgress(99 * (++step) / StepCount);8069 if (pProgressControl) 8070 pProgressControl->SetCurrentOperationProgress(99 * (++step) / StepCount); 8065 8071 8066 8072 if (RT_SUCCESS(vrc)) … … 8093 8099 8094 8100 /* advance percent count */ 8095 if ( aProgress)8096 aProgress->SetCurrentOperationProgress(99 * (++step) / StepCount);8101 if (pProgressControl) 8102 pProgressControl->SetCurrentOperationProgress(99 * (++step) / StepCount); 8097 8103 } 8098 8104 else … … 9504 9510 /* update the progress object */ 9505 9511 if (pProgress) 9506 pProgress->SetCurrentOperationProgress(uPercent); 9512 { 9513 ComPtr<IInternalProgressControl> pProgressControl(pProgress); 9514 AssertReturn(!!pProgressControl, VERR_INVALID_PARAMETER); 9515 pProgressControl->SetCurrentOperationProgress(uPercent); 9516 } 9507 9517 9508 9518 NOREF(pUVM); -
trunk/src/VBox/Main/src-client/ConsoleImplTeleporter.cpp
r73003 r74804 718 718 * We're at the point of no return. 719 719 */ 720 if ( !pState->mptrProgress->i_notifyPointOfNoReturn())720 if (FAILED(pState->mptrProgress->NotifyPointOfNoReturn())) 721 721 { 722 722 i_teleporterSrcSubmitCommand(pState, "cancel", false /*fWaitForAck*/); … … 1414 1414 * make it possible to recover from some VMR3Resume failures. 1415 1415 */ 1416 if ( pState->mptrProgress->i_notifyPointOfNoReturn()1416 if ( SUCCEEDED(pState->mptrProgress->NotifyPointOfNoReturn()) 1417 1417 && pState->mfLockedMedia) 1418 1418 { -
trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp
r73784 r74804 2656 2656 /* Now wait for the background import operation to complete; this throws 2657 2657 * HRESULTs on error. */ 2658 stack.pProgress-> i_waitForOtherProgressCompletion(pProgressImport);2658 stack.pProgress->WaitForOtherProgressCompletion(pProgressImport, 0 /* indefinite wait */); 2659 2659 } 2660 2660 } -
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r74474 r74804 5498 5498 rc = pMedium->DeleteStorage(pProgress2.asOutParam()); 5499 5499 if (FAILED(rc)) throw rc; 5500 rc = task.m_pProgress-> i_waitForOtherProgressCompletion(pProgress2);5500 rc = task.m_pProgress->WaitForOtherProgressCompletion(pProgress2, 0 /* indefinite wait */); 5501 5501 if (FAILED(rc)) throw rc; 5502 5502 } … … 10943 10943 LogFlowThisFunc(("aOnline=%d\n", aOnline)); 10944 10944 10945 ComPtr<IInternalProgressControl> pProgressControl(aProgress); 10946 AssertReturn(!!pProgressControl, E_INVALIDARG); 10947 10945 10948 AutoCaller autoCaller(this); 10946 10949 AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); … … 11048 11051 { 11049 11052 if (pMedium == NULL) 11050 aProgress->SetNextOperation(Bstr(tr("Skipping attachment without medium")).raw(),11051 aWeight); // weight11053 pProgressControl->SetNextOperation(Bstr(tr("Skipping attachment without medium")).raw(), 11054 aWeight); // weight 11052 11055 else 11053 aProgress->SetNextOperation(BstrFmt(tr("Skipping medium '%s'"),11054 pMedium->i_getBase()->i_getName().c_str()).raw(),11055 aWeight); // weight11056 pProgressControl->SetNextOperation(BstrFmt(tr("Skipping medium '%s'"), 11057 pMedium->i_getBase()->i_getName().c_str()).raw(), 11058 aWeight); // weight 11056 11059 } 11057 11060 … … 11061 11064 11062 11065 /* need a diff */ 11063 aProgress->SetNextOperation(BstrFmt(tr("Creating differencing hard disk for '%s'"),11064 pMedium->i_getBase()->i_getName().c_str()).raw(),11065 aWeight); // weight11066 pProgressControl->SetNextOperation(BstrFmt(tr("Creating differencing hard disk for '%s'"), 11067 pMedium->i_getBase()->i_getName().c_str()).raw(), 11068 aWeight); // weight 11066 11069 11067 11070 Utf8Str strFullSnapshotFolder; -
trunk/src/VBox/Main/src-server/MachineImplCloneVM.cpp
r73743 r74804 1290 1290 /* Wait until the async process has finished. */ 1291 1291 srcLock.release(); 1292 rc = d->pProgress-> i_waitForOtherProgressCompletion(progress2);1292 rc = d->pProgress->WaitForOtherProgressCompletion(progress2, 0 /* indefinite wait */); 1293 1293 srcLock.acquire(); 1294 1294 if (FAILED(rc)) throw rc; -
trunk/src/VBox/Main/src-server/MachineImplMoveVM.cpp
r74530 r74804 1114 1114 */ 1115 1115 /* Wait until the other process has finished. */ 1116 rc = m_pProgress-> i_waitForOtherProgressCompletion(moveDiskProgress);1116 rc = m_pProgress->WaitForOtherProgressCompletion(moveDiskProgress, 0 /* indefinite wait */); 1117 1117 } 1118 1118 -
trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
r70236 r74804 1747 1747 LogRel(("Machine: skipped saving state as part of online snapshot\n")); 1748 1748 1749 if ( !task.m_pProgress->i_notifyPointOfNoReturn())1749 if (FAILED(task.m_pProgress->NotifyPointOfNoReturn())) 1750 1750 throw setError(E_FAIL, tr("Canceled")); 1751 1751
Note:
See TracChangeset
for help on using the changeset viewer.