summaryrefslogtreecommitdiff
path: root/src/VBox/Main/src-all/ProgressImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/src-all/ProgressImpl.cpp')
-rw-r--r--src/VBox/Main/src-all/ProgressImpl.cpp889
1 files changed, 122 insertions, 767 deletions
diff --git a/src/VBox/Main/src-all/ProgressImpl.cpp b/src/VBox/Main/src-all/ProgressImpl.cpp
index 3d78b2bc..fa3ecea8 100644
--- a/src/VBox/Main/src-all/ProgressImpl.cpp
+++ b/src/VBox/Main/src-all/ProgressImpl.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -18,15 +18,18 @@
#include <iprt/types.h>
+
#if defined(VBOX_WITH_XPCOM)
#include <nsIServiceManager.h>
#include <nsIExceptionService.h>
#include <nsCOMPtr.h>
#endif /* defined(VBOX_WITH_XPCOM) */
-#include "ProgressCombinedImpl.h"
+#include "ProgressImpl.h"
-#include "VirtualBoxImpl.h"
+#if !defined(VBOX_COM_INPROC)
+# include "VirtualBoxImpl.h"
+#endif
#include "VirtualBoxErrorInfoImpl.h"
#include "Logging.h"
@@ -36,181 +39,25 @@
#include <iprt/cpp/utils.h>
#include <VBox/err.h>
+#include "AutoCaller.h"
-////////////////////////////////////////////////////////////////////////////////
-// ProgressBase class
-////////////////////////////////////////////////////////////////////////////////
-// constructor / destructor
-////////////////////////////////////////////////////////////////////////////////
-
-ProgressBase::ProgressBase()
+Progress::Progress()
#if !defined(VBOX_COM_INPROC)
: mParent(NULL)
#endif
{
}
-ProgressBase::~ProgressBase()
+Progress::~Progress()
{
}
-/**
- * Subclasses must call this method from their FinalConstruct() implementations.
- */
-HRESULT ProgressBase::FinalConstruct()
-{
- mCancelable = FALSE;
- mCompleted = FALSE;
- mCanceled = FALSE;
- mResultCode = S_OK;
-
- m_cOperations
- = m_ulTotalOperationsWeight
- = m_ulOperationsCompletedWeight
- = m_ulCurrentOperation
- = m_ulCurrentOperationWeight
- = m_ulOperationPercent
- = m_cMsTimeout
- = 0;
-
- // get creation timestamp
- m_ullTimestamp = RTTimeMilliTS();
-
- m_pfnCancelCallback = NULL;
- m_pvCancelUserArg = NULL;
-
- return BaseFinalConstruct();
-}
-
-// protected initializer/uninitializer for internal purposes only
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Initializes the progress base object.
- *
- * Subclasses should call this or any other #protectedInit() method from their
- * init() implementations.
- *
- * @param aAutoInitSpan AutoInitSpan object instantiated by a subclass.
- * @param aParent Parent object (only for server-side Progress objects).
- * @param aInitiator Initiator of the task (for server-side objects. Can be
- * NULL which means initiator = parent, otherwise must not
- * be NULL).
- * @param aDescription ask description.
- * @param aID Address of result GUID structure (optional).
- *
- * @return COM result indicator.
- */
-HRESULT ProgressBase::protectedInit(AutoInitSpan &aAutoInitSpan,
-#if !defined(VBOX_COM_INPROC)
- VirtualBox *aParent,
-#endif
- IUnknown *aInitiator,
- CBSTR aDescription,
- OUT_GUID aId /* = NULL */)
-{
- /* Guarantees subclasses call this method at the proper time */
- NOREF(aAutoInitSpan);
-
- AutoCaller autoCaller(this);
- AssertReturn(autoCaller.state() == InInit, E_FAIL);
-
-#if !defined(VBOX_COM_INPROC)
- AssertReturn(aParent, E_INVALIDARG);
-#else
- AssertReturn(aInitiator, E_INVALIDARG);
-#endif
-
- AssertReturn(aDescription, E_INVALIDARG);
-
-#if !defined(VBOX_COM_INPROC)
- /* share parent weakly */
- unconst(mParent) = aParent;
-#endif
-
-#if !defined(VBOX_COM_INPROC)
- /* assign (and therefore addref) initiator only if it is not VirtualBox
- * (to avoid cycling); otherwise mInitiator will remain null which means
- * that it is the same as the parent */
- if (aInitiator)
- {
- ComObjPtr<VirtualBox> pVirtualBox(mParent);
- if (!(pVirtualBox == aInitiator))
- unconst(mInitiator) = aInitiator;
- }
-#else
- unconst(mInitiator) = aInitiator;
-#endif
-
- unconst(mId).create();
- if (aId)
- mId.cloneTo(aId);
-
-#if !defined(VBOX_COM_INPROC)
- /* add to the global collection of progress operations (note: after
- * creating mId) */
- mParent->addProgress(this);
-#endif
-
- unconst(mDescription) = aDescription;
-
- return S_OK;
-}
-
-/**
- * Initializes the progress base object.
- *
- * This is a special initializer that doesn't initialize any field. Used by one
- * of the Progress::init() forms to create sub-progress operations combined
- * together using a CombinedProgress instance, so it doesn't require the parent,
- * initiator, description and doesn't create an ID.
- *
- * Subclasses should call this or any other #protectedInit() method from their
- * init() implementations.
- *
- * @param aAutoInitSpan AutoInitSpan object instantiated by a subclass.
- */
-HRESULT ProgressBase::protectedInit(AutoInitSpan &aAutoInitSpan)
-{
- /* Guarantees subclasses call this method at the proper time */
- NOREF(aAutoInitSpan);
-
- return S_OK;
-}
-
-/**
- * Uninitializes the instance.
- *
- * Subclasses should call this from their uninit() implementations.
- *
- * @param aAutoUninitSpan AutoUninitSpan object instantiated by a subclass.
- *
- * @note Using the mParent member after this method returns is forbidden.
- */
-void ProgressBase::protectedUninit(AutoUninitSpan &aAutoUninitSpan)
-{
- /* release initiator (effective only if mInitiator has been assigned in
- * init()) */
- unconst(mInitiator).setNull();
-
-#if !defined(VBOX_COM_INPROC)
- if (mParent)
- {
- /* remove the added progress on failure to complete the initialization */
- if (aAutoUninitSpan.initFailed() && !mId.isEmpty())
- mParent->removeProgress(mId.ref());
-
- unconst(mParent) = NULL;
- }
-#endif
-}
-
// IProgress properties
/////////////////////////////////////////////////////////////////////////////
-STDMETHODIMP ProgressBase::COMGETTER(Id)(BSTR *aId)
+STDMETHODIMP Progress::COMGETTER(Id)(BSTR *aId)
{
CheckComArgOutPointerValid(aId);
@@ -223,7 +70,7 @@ STDMETHODIMP ProgressBase::COMGETTER(Id)(BSTR *aId)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(Description)(BSTR *aDescription)
+STDMETHODIMP Progress::COMGETTER(Description)(BSTR *aDescription)
{
CheckComArgOutPointerValid(aDescription);
@@ -236,7 +83,7 @@ STDMETHODIMP ProgressBase::COMGETTER(Description)(BSTR *aDescription)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(Initiator)(IUnknown **aInitiator)
+STDMETHODIMP Progress::COMGETTER(Initiator)(IUnknown **aInitiator)
{
CheckComArgOutPointerValid(aInitiator);
@@ -260,7 +107,7 @@ STDMETHODIMP ProgressBase::COMGETTER(Initiator)(IUnknown **aInitiator)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(Cancelable)(BOOL *aCancelable)
+STDMETHODIMP Progress::COMGETTER(Cancelable)(BOOL *aCancelable)
{
CheckComArgOutPointerValid(aCancelable);
@@ -283,7 +130,7 @@ STDMETHODIMP ProgressBase::COMGETTER(Cancelable)(BOOL *aCancelable)
*
* @return fractional percentage as a double value.
*/
-double ProgressBase::calcTotalPercent()
+double Progress::calcTotalPercent()
{
// avoid division by zero
if (m_ulTotalOperationsWeight == 0)
@@ -301,7 +148,7 @@ double ProgressBase::calcTotalPercent()
*
* The caller should hold the object write lock.
*/
-void ProgressBase::checkForAutomaticTimeout(void)
+void Progress::checkForAutomaticTimeout(void)
{
if ( m_cMsTimeout
&& mCancelable
@@ -312,7 +159,7 @@ void ProgressBase::checkForAutomaticTimeout(void)
}
-STDMETHODIMP ProgressBase::COMGETTER(TimeRemaining)(LONG *aTimeRemaining)
+STDMETHODIMP Progress::COMGETTER(TimeRemaining)(LONG *aTimeRemaining)
{
CheckComArgOutPointerValid(aTimeRemaining);
@@ -335,7 +182,7 @@ STDMETHODIMP ProgressBase::COMGETTER(TimeRemaining)(LONG *aTimeRemaining)
uint64_t ullTimeTotal = (uint64_t)(ullTimeElapsed * 100 / dPercentDone);
uint64_t ullTimeRemaining = ullTimeTotal - ullTimeElapsed;
-// Log(("ProgressBase::GetTimeRemaining: dPercentDone %RI32, ullTimeNow = %RI64, ullTimeElapsed = %RI64, ullTimeTotal = %RI64, ullTimeRemaining = %RI64\n",
+// Log(("Progress::GetTimeRemaining: dPercentDone %RI32, ullTimeNow = %RI64, ullTimeElapsed = %RI64, ullTimeTotal = %RI64, ullTimeRemaining = %RI64\n",
// (uint32_t)dPercentDone, ullTimeNow, ullTimeElapsed, ullTimeTotal, ullTimeRemaining));
*aTimeRemaining = (LONG)(ullTimeRemaining / 1000);
@@ -345,7 +192,7 @@ STDMETHODIMP ProgressBase::COMGETTER(TimeRemaining)(LONG *aTimeRemaining)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(Percent)(ULONG *aPercent)
+STDMETHODIMP Progress::COMGETTER(Percent)(ULONG *aPercent)
{
CheckComArgOutPointerValid(aPercent);
@@ -378,7 +225,7 @@ STDMETHODIMP ProgressBase::COMGETTER(Percent)(ULONG *aPercent)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(Completed)(BOOL *aCompleted)
+STDMETHODIMP Progress::COMGETTER(Completed)(BOOL *aCompleted)
{
CheckComArgOutPointerValid(aCompleted);
@@ -392,7 +239,7 @@ STDMETHODIMP ProgressBase::COMGETTER(Completed)(BOOL *aCompleted)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(Canceled)(BOOL *aCanceled)
+STDMETHODIMP Progress::COMGETTER(Canceled)(BOOL *aCanceled)
{
CheckComArgOutPointerValid(aCanceled);
@@ -406,7 +253,7 @@ STDMETHODIMP ProgressBase::COMGETTER(Canceled)(BOOL *aCanceled)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(ResultCode)(LONG *aResultCode)
+STDMETHODIMP Progress::COMGETTER(ResultCode)(LONG *aResultCode)
{
CheckComArgOutPointerValid(aResultCode);
@@ -424,7 +271,7 @@ STDMETHODIMP ProgressBase::COMGETTER(ResultCode)(LONG *aResultCode)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(ErrorInfo)(IVirtualBoxErrorInfo **aErrorInfo)
+STDMETHODIMP Progress::COMGETTER(ErrorInfo)(IVirtualBoxErrorInfo **aErrorInfo)
{
CheckComArgOutPointerValid(aErrorInfo);
@@ -442,7 +289,7 @@ STDMETHODIMP ProgressBase::COMGETTER(ErrorInfo)(IVirtualBoxErrorInfo **aErrorInf
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(OperationCount)(ULONG *aOperationCount)
+STDMETHODIMP Progress::COMGETTER(OperationCount)(ULONG *aOperationCount)
{
CheckComArgOutPointerValid(aOperationCount);
@@ -456,7 +303,7 @@ STDMETHODIMP ProgressBase::COMGETTER(OperationCount)(ULONG *aOperationCount)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(Operation)(ULONG *aOperation)
+STDMETHODIMP Progress::COMGETTER(Operation)(ULONG *aOperation)
{
CheckComArgOutPointerValid(aOperation);
@@ -470,7 +317,7 @@ STDMETHODIMP ProgressBase::COMGETTER(Operation)(ULONG *aOperation)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(OperationDescription)(BSTR *aOperationDescription)
+STDMETHODIMP Progress::COMGETTER(OperationDescription)(BSTR *aOperationDescription)
{
CheckComArgOutPointerValid(aOperationDescription);
@@ -484,7 +331,7 @@ STDMETHODIMP ProgressBase::COMGETTER(OperationDescription)(BSTR *aOperationDescr
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(OperationPercent)(ULONG *aOperationPercent)
+STDMETHODIMP Progress::COMGETTER(OperationPercent)(ULONG *aOperationPercent)
{
CheckComArgOutPointerValid(aOperationPercent);
@@ -501,7 +348,7 @@ STDMETHODIMP ProgressBase::COMGETTER(OperationPercent)(ULONG *aOperationPercent)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(OperationWeight)(ULONG *aOperationWeight)
+STDMETHODIMP Progress::COMGETTER(OperationWeight)(ULONG *aOperationWeight)
{
CheckComArgOutPointerValid(aOperationWeight);
@@ -515,7 +362,7 @@ STDMETHODIMP ProgressBase::COMGETTER(OperationWeight)(ULONG *aOperationWeight)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMSETTER(Timeout)(ULONG aTimeout)
+STDMETHODIMP Progress::COMSETTER(Timeout)(ULONG aTimeout)
{
AutoCaller autoCaller(this);
if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -531,7 +378,7 @@ STDMETHODIMP ProgressBase::COMSETTER(Timeout)(ULONG aTimeout)
return S_OK;
}
-STDMETHODIMP ProgressBase::COMGETTER(Timeout)(ULONG *aTimeout)
+STDMETHODIMP Progress::COMGETTER(Timeout)(ULONG *aTimeout)
{
CheckComArgOutPointerValid(aTimeout);
@@ -558,7 +405,7 @@ STDMETHODIMP ProgressBase::COMGETTER(Timeout)(ULONG *aTimeout)
* @param pfnCallback The function to be called upon cancelation.
* @param pvUser The callback argument.
*/
-bool ProgressBase::setCancelCallback(void (*pfnCallback)(void *), void *pvUser)
+bool Progress::setCancelCallback(void (*pfnCallback)(void *), void *pvUser)
{
AutoCaller autoCaller(this);
AssertComRCReturn(autoCaller.rc(), false);
@@ -574,13 +421,29 @@ bool ProgressBase::setCancelCallback(void (*pfnCallback)(void *), void *pvUser)
return true;
}
-////////////////////////////////////////////////////////////////////////////////
-// Progress class
-////////////////////////////////////////////////////////////////////////////////
-
HRESULT Progress::FinalConstruct()
{
- HRESULT rc = ProgressBase::FinalConstruct();
+ mCancelable = FALSE;
+ mCompleted = FALSE;
+ mCanceled = FALSE;
+ mResultCode = S_OK;
+
+ m_cOperations
+ = m_ulTotalOperationsWeight
+ = m_ulOperationsCompletedWeight
+ = m_ulCurrentOperation
+ = m_ulCurrentOperationWeight
+ = m_ulOperationPercent
+ = m_cMsTimeout
+ = 0;
+
+ // get creation timestamp
+ m_ullTimestamp = RTTimeMilliTS();
+
+ m_pfnCancelCallback = NULL;
+ m_pvCancelUserArg = NULL;
+
+ HRESULT rc = Progress::BaseFinalConstruct();
if (FAILED(rc)) return rc;
mCompletedSem = NIL_RTSEMEVENTMULTI;
@@ -636,16 +499,16 @@ void Progress::FinalRelease()
* Even simpler, if you need no sub-operations at all, pass in cOperations =
* ulTotalOperationsWeight = ulFirstOperationWeight = 1.
*
- * @param aParent See ProgressBase::init().
- * @param aInitiator See ProgressBase::init().
- * @param aDescription See ProgressBase::init().
+ * @param aParent See Progress::init().
+ * @param aInitiator See Progress::init().
+ * @param aDescription See Progress::init().
* @param aCancelable Flag whether the task maybe canceled.
* @param cOperations Number of operations within this task (at least 1).
* @param ulTotalOperationsWeight Total weight of operations; must be the sum of ulFirstOperationWeight and
* what is later passed with each subsequent setNextOperation() call.
* @param bstrFirstOperationDescription Description of the first operation.
* @param ulFirstOperationWeight Weight of first sub-operation.
- * @param aId See ProgressBase::init().
+ * @param aId See Progress::init().
*/
HRESULT Progress::init(
#if !defined(VBOX_COM_INPROC)
@@ -676,11 +539,55 @@ HRESULT Progress::init(
HRESULT rc = S_OK;
- rc = ProgressBase::protectedInit(autoInitSpan,
+// rc = Progress::init(
+//#if !defined(VBOX_COM_INPROC)
+// aParent,
+//#endif
+// aInitiator, aDescription, FALSE, aId);
+// NA
#if !defined(VBOX_COM_INPROC)
- aParent,
+ AssertReturn(aParent, E_INVALIDARG);
+#else
+ AssertReturn(aInitiator, E_INVALIDARG);
+#endif
+
+ AssertReturn(aDescription, E_INVALIDARG);
+
+#if !defined(VBOX_COM_INPROC)
+ /* share parent weakly */
+ unconst(mParent) = aParent;
#endif
- aInitiator, aDescription, aId);
+
+#if !defined(VBOX_COM_INPROC)
+ /* assign (and therefore addref) initiator only if it is not VirtualBox
+ * * (to avoid cycling); otherwise mInitiator will remain null which means
+ * * that it is the same as the parent */
+ if (aInitiator)
+ {
+ ComObjPtr<VirtualBox> pVirtualBox(mParent);
+ if (!(pVirtualBox == aInitiator))
+ unconst(mInitiator) = aInitiator;
+ }
+#else
+ unconst(mInitiator) = aInitiator;
+#endif
+
+ unconst(mId).create();
+ if (aId)
+ mId.cloneTo(aId);
+
+#if !defined(VBOX_COM_INPROC)
+ /* add to the global collection of progress operations (note: after
+ * * creating mId) */
+ mParent->addProgress(this);
+#endif
+
+ unconst(mDescription) = aDescription;
+
+
+// end of assertion
+
+
if (FAILED(rc)) return rc;
mCancelable = aCancelable;
@@ -710,7 +617,7 @@ HRESULT Progress::init(
* the whole task.
*
* Objects initialized with this method are then combined together into the
- * single task using a CombinedProgress instance, so it doesn't require the
+ * single task using a Progress instance, so it doesn't require the
* parent, initiator, description and doesn't create an ID. Note that calling
* respective getter methods on an object initialized with this method is
* useless. Such objects are used only to provide a separate wait semaphore and
@@ -731,8 +638,9 @@ HRESULT Progress::init(BOOL aCancelable,
AssertReturn(autoInitSpan.isOk(), E_FAIL);
HRESULT rc = S_OK;
+ /* Guarantees subclasses call this method at the proper time */
+ NOREF(autoInitSpan);
- rc = ProgressBase::protectedInit(autoInitSpan);
if (FAILED(rc)) return rc;
mCancelable = aCancelable;
@@ -759,6 +667,7 @@ HRESULT Progress::init(BOOL aCancelable,
return rc;
}
+
/**
* Uninitializes the instance and sets the ready flag to FALSE.
*
@@ -783,9 +692,23 @@ void Progress::uninit()
RTSemEventMultiDestroy(mCompletedSem);
- ProgressBase::protectedUninit(autoUninitSpan);
+ /* release initiator (effective only if mInitiator has been assigned in
+ * * init()) */
+ unconst(mInitiator).setNull();
+
+#if !defined(VBOX_COM_INPROC)
+ if (mParent)
+ {
+ /* remove the added progress on failure to complete the initialization */
+ if (autoUninitSpan.initFailed() && mId.isValid() && !mId.isZero())
+ mParent->removeProgress(mId.ref());
+
+ unconst(mParent) = NULL;
+ }
+#endif
}
+
// IProgress properties
/////////////////////////////////////////////////////////////////////////////
@@ -962,7 +885,7 @@ STDMETHODIMP Progress::WaitForAsyncProgressCompletion(IProgress *pProgressAsync)
* in the meantime more than one async operation was finished. So we
* have to loop as long as we reached the same operation count. */
ULONG curOp;
- for(;;)
+ for (;;)
{
rc = pProgressAsync->COMGETTER(Operation(&curOp));
if (FAILED(rc)) return rc;
@@ -1321,571 +1244,3 @@ bool Progress::notifyPointOfNoReturn(void)
return true;
}
-////////////////////////////////////////////////////////////////////////////////
-// CombinedProgress class
-////////////////////////////////////////////////////////////////////////////////
-
-HRESULT CombinedProgress::FinalConstruct()
-{
- HRESULT rc = ProgressBase::FinalConstruct();
- if (FAILED(rc)) return rc;
-
- mProgress = 0;
- mCompletedOperations = 0;
-
- return BaseFinalConstruct();
-}
-
-void CombinedProgress::FinalRelease()
-{
- uninit();
- BaseFinalRelease();
-}
-
-// public initializer/uninitializer for internal purposes only
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Initializes this object based on individual combined progresses.
- * Must be called only from #init()!
- *
- * @param aAutoInitSpan AutoInitSpan object instantiated by a subclass.
- * @param aParent See ProgressBase::init().
- * @param aInitiator See ProgressBase::init().
- * @param aDescription See ProgressBase::init().
- * @param aId See ProgressBase::init().
- */
-HRESULT CombinedProgress::protectedInit(AutoInitSpan &aAutoInitSpan,
-#if !defined(VBOX_COM_INPROC)
- VirtualBox *aParent,
-#endif
- IUnknown *aInitiator,
- CBSTR aDescription, OUT_GUID aId)
-{
- LogFlowThisFunc(("aDescription={%ls} mProgresses.size()=%d\n",
- aDescription, mProgresses.size()));
-
- HRESULT rc = S_OK;
-
- rc = ProgressBase::protectedInit(aAutoInitSpan,
-#if !defined(VBOX_COM_INPROC)
- aParent,
-#endif
- aInitiator, aDescription, aId);
- if (FAILED(rc)) return rc;
-
- mProgress = 0; /* the first object */
- mCompletedOperations = 0;
-
- mCompleted = FALSE;
- mCancelable = TRUE; /* until any progress returns FALSE */
- mCanceled = FALSE;
-
- m_cOperations = 0; /* will be calculated later */
-
- m_ulCurrentOperation = 0;
- rc = mProgresses[0]->COMGETTER(OperationDescription)(m_bstrOperationDescription.asOutParam());
- if (FAILED(rc)) return rc;
-
- for (size_t i = 0; i < mProgresses.size(); i ++)
- {
- if (mCancelable)
- {
- BOOL cancelable = FALSE;
- rc = mProgresses[i]->COMGETTER(Cancelable)(&cancelable);
- if (FAILED(rc)) return rc;
-
- if (!cancelable)
- mCancelable = FALSE;
- }
-
- {
- ULONG opCount = 0;
- rc = mProgresses[i]->COMGETTER(OperationCount)(&opCount);
- if (FAILED(rc)) return rc;
-
- m_cOperations += opCount;
- }
- }
-
- rc = checkProgress();
- if (FAILED(rc)) return rc;
-
- return rc;
-}
-
-/**
- * Initializes the combined progress object given two normal progress
- * objects.
- *
- * @param aParent See ProgressBase::init().
- * @param aInitiator See ProgressBase::init().
- * @param aDescription See ProgressBase::init().
- * @param aProgress1 First normal progress object.
- * @param aProgress2 Second normal progress object.
- * @param aId See ProgressBase::init().
- */
-HRESULT CombinedProgress::init(
-#if !defined(VBOX_COM_INPROC)
- VirtualBox *aParent,
-#endif
- IUnknown *aInitiator,
- CBSTR aDescription,
- IProgress *aProgress1,
- IProgress *aProgress2,
- OUT_GUID aId /* = NULL */)
-{
- /* Enclose the state transition NotReady->InInit->Ready */
- AutoInitSpan autoInitSpan(this);
- AssertReturn(autoInitSpan.isOk(), E_FAIL);
-
- mProgresses.resize(2);
- mProgresses[0] = aProgress1;
- mProgresses[1] = aProgress2;
-
- HRESULT rc = protectedInit(autoInitSpan,
-#if !defined(VBOX_COM_INPROC)
- aParent,
-#endif
- aInitiator,
- aDescription,
- aId);
-
- /* Confirm a successful initialization when it's the case */
- if (SUCCEEDED(rc))
- autoInitSpan.setSucceeded();
-
- return rc;
-}
-
-/**
- * Uninitializes the instance and sets the ready flag to FALSE.
- *
- * Called either from FinalRelease() or by the parent when it gets destroyed.
- */
-void CombinedProgress::uninit()
-{
- LogFlowThisFunc(("\n"));
-
- /* Enclose the state transition Ready->InUninit->NotReady */
- AutoUninitSpan autoUninitSpan(this);
- if (autoUninitSpan.uninitDone())
- return;
-
- mProgress = 0;
- mProgresses.clear();
-
- ProgressBase::protectedUninit(autoUninitSpan);
-}
-
-// IProgress properties
-////////////////////////////////////////////////////////////////////////////////
-
-STDMETHODIMP CombinedProgress::COMGETTER(Percent)(ULONG *aPercent)
-{
- CheckComArgOutPointerValid(aPercent);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* checkProgress needs a write lock */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- if (mCompleted && SUCCEEDED(mResultCode))
- *aPercent = 100;
- else
- {
- HRESULT rc = checkProgress();
- if (FAILED(rc)) return rc;
-
- /* global percent =
- * (100 / m_cOperations) * mOperation +
- * ((100 / m_cOperations) / 100) * m_ulOperationPercent */
- *aPercent = (100 * m_ulCurrentOperation + m_ulOperationPercent) / m_cOperations;
- }
-
- return S_OK;
-}
-
-STDMETHODIMP CombinedProgress::COMGETTER(Completed)(BOOL *aCompleted)
-{
- CheckComArgOutPointerValid(aCompleted);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* checkProgress needs a write lock */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- HRESULT rc = checkProgress();
- if (FAILED(rc)) return rc;
-
- return ProgressBase::COMGETTER(Completed)(aCompleted);
-}
-
-STDMETHODIMP CombinedProgress::COMGETTER(Canceled)(BOOL *aCanceled)
-{
- CheckComArgOutPointerValid(aCanceled);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* checkProgress needs a write lock */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- HRESULT rc = checkProgress();
- if (FAILED(rc)) return rc;
-
- return ProgressBase::COMGETTER(Canceled)(aCanceled);
-}
-
-STDMETHODIMP CombinedProgress::COMGETTER(ResultCode)(LONG *aResultCode)
-{
- CheckComArgOutPointerValid(aResultCode);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* checkProgress needs a write lock */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- HRESULT rc = checkProgress();
- if (FAILED(rc)) return rc;
-
- return ProgressBase::COMGETTER(ResultCode)(aResultCode);
-}
-
-STDMETHODIMP CombinedProgress::COMGETTER(ErrorInfo)(IVirtualBoxErrorInfo **aErrorInfo)
-{
- CheckComArgOutPointerValid(aErrorInfo);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* checkProgress needs a write lock */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- HRESULT rc = checkProgress();
- if (FAILED(rc)) return rc;
-
- return ProgressBase::COMGETTER(ErrorInfo)(aErrorInfo);
-}
-
-STDMETHODIMP CombinedProgress::COMGETTER(Operation)(ULONG *aOperation)
-{
- CheckComArgOutPointerValid(aOperation);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* checkProgress needs a write lock */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- HRESULT rc = checkProgress();
- if (FAILED(rc)) return rc;
-
- return ProgressBase::COMGETTER(Operation)(aOperation);
-}
-
-STDMETHODIMP CombinedProgress::COMGETTER(OperationDescription)(BSTR *aOperationDescription)
-{
- CheckComArgOutPointerValid(aOperationDescription);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* checkProgress needs a write lock */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- HRESULT rc = checkProgress();
- if (FAILED(rc)) return rc;
-
- return ProgressBase::COMGETTER(OperationDescription)(aOperationDescription);
-}
-
-STDMETHODIMP CombinedProgress::COMGETTER(OperationPercent)(ULONG *aOperationPercent)
-{
- CheckComArgOutPointerValid(aOperationPercent);
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- /* checkProgress needs a write lock */
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- HRESULT rc = checkProgress();
- if (FAILED(rc)) return rc;
-
- return ProgressBase::COMGETTER(OperationPercent)(aOperationPercent);
-}
-
-STDMETHODIMP CombinedProgress::COMSETTER(Timeout)(ULONG aTimeout)
-{
- NOREF(aTimeout);
- AssertFailed();
- return E_NOTIMPL;
-}
-
-STDMETHODIMP CombinedProgress::COMGETTER(Timeout)(ULONG *aTimeout)
-{
- CheckComArgOutPointerValid(aTimeout);
-
- AssertFailed();
- return E_NOTIMPL;
-}
-
-// IProgress methods
-/////////////////////////////////////////////////////////////////////////////
-
-/**
- * @note XPCOM: when this method is called not on the main XPCOM thread, it
- * simply blocks the thread until mCompletedSem is signalled. If the
- * thread has its own event queue (hmm, what for?) that it must run, then
- * calling this method will definitely freeze event processing.
- */
-STDMETHODIMP CombinedProgress::WaitForCompletion(LONG aTimeout)
-{
- LogFlowThisFuncEnter();
- LogFlowThisFunc(("aTtimeout=%d\n", aTimeout));
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- /* if we're already completed, take a shortcut */
- if (!mCompleted)
- {
- HRESULT rc = S_OK;
- bool forever = aTimeout < 0;
- int64_t timeLeft = aTimeout;
- int64_t lastTime = RTTimeMilliTS();
-
- while (!mCompleted && (forever || timeLeft > 0))
- {
- alock.release();
- rc = mProgresses.back()->WaitForCompletion(forever ? -1 : (LONG) timeLeft);
- alock.acquire();
-
- if (SUCCEEDED(rc))
- rc = checkProgress();
-
- if (FAILED(rc)) break;
-
- if (!forever)
- {
- int64_t now = RTTimeMilliTS();
- timeLeft -= now - lastTime;
- lastTime = now;
- }
- }
-
- if (FAILED(rc)) return rc;
- }
-
- LogFlowThisFuncLeave();
-
- return S_OK;
-}
-
-/**
- * @note XPCOM: when this method is called not on the main XPCOM thread, it
- * simply blocks the thread until mCompletedSem is signalled. If the
- * thread has its own event queue (hmm, what for?) that it must run, then
- * calling this method will definitely freeze event processing.
- */
-STDMETHODIMP CombinedProgress::WaitForOperationCompletion(ULONG aOperation, LONG aTimeout)
-{
- LogFlowThisFuncEnter();
- LogFlowThisFunc(("aOperation=%d, aTimeout=%d\n", aOperation, aTimeout));
-
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- if (aOperation >= m_cOperations)
- return setError(E_FAIL,
- tr("Operation number must be in range [0, %d]"), m_ulCurrentOperation - 1);
-
- /* if we're already completed or if the given operation is already done,
- * then take a shortcut */
- if (!mCompleted && aOperation >= m_ulCurrentOperation)
- {
- HRESULT rc = S_OK;
-
- /* find the right progress object to wait for */
- size_t progress = mProgress;
- ULONG operation = 0, completedOps = mCompletedOperations;
- do
- {
- ULONG opCount = 0;
- rc = mProgresses[progress]->COMGETTER(OperationCount)(&opCount);
- if (FAILED(rc))
- return rc;
-
- if (completedOps + opCount > aOperation)
- {
- /* found the right progress object */
- operation = aOperation - completedOps;
- break;
- }
-
- completedOps += opCount;
- progress ++;
- ComAssertRet(progress < mProgresses.size(), E_FAIL);
- }
- while (1);
-
- LogFlowThisFunc(("will wait for mProgresses [%d] (%d)\n",
- progress, operation));
-
- bool forever = aTimeout < 0;
- int64_t timeLeft = aTimeout;
- int64_t lastTime = RTTimeMilliTS();
-
- while (!mCompleted && aOperation >= m_ulCurrentOperation &&
- (forever || timeLeft > 0))
- {
- alock.release();
- /* wait for the appropriate progress operation completion */
- rc = mProgresses[progress]-> WaitForOperationCompletion(operation,
- forever ? -1 : (LONG) timeLeft);
- alock.acquire();
-
- if (SUCCEEDED(rc))
- rc = checkProgress();
-
- if (FAILED(rc)) break;
-
- if (!forever)
- {
- int64_t now = RTTimeMilliTS();
- timeLeft -= now - lastTime;
- lastTime = now;
- }
- }
-
- if (FAILED(rc)) return rc;
- }
-
- LogFlowThisFuncLeave();
-
- return S_OK;
-}
-
-STDMETHODIMP CombinedProgress::Cancel()
-{
- AutoCaller autoCaller(this);
- if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
- AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
- if (!mCancelable)
- return setError(E_FAIL, tr("Operation cannot be canceled"));
-
- if (!mCanceled)
- {
- LogThisFunc(("Canceling\n"));
- mCanceled = TRUE;
-/** @todo Teleportation: Shouldn't this be propagated to mProgresses? If
- * powerUp creates passes a combined progress object to the client, I
- * won't get called back since I'm only getting the powerupProgress ...
- * Or what? */
- if (m_pfnCancelCallback)
- m_pfnCancelCallback(m_pvCancelUserArg);
-
- }
- else
- LogThisFunc(("Already canceled\n"));
-
- return S_OK;
-}
-
-// private methods
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Fetches the properties of the current progress object and, if it is
- * successfully completed, advances to the next uncompleted or unsuccessfully
- * completed object in the vector of combined progress objects.
- *
- * @note Must be called from under this object's write lock!
- */
-HRESULT CombinedProgress::checkProgress()
-{
- /* do nothing if we're already marked ourselves as completed */
- if (mCompleted)
- return S_OK;
-
- AssertReturn(mProgress < mProgresses.size(), E_FAIL);
-
- ComPtr<IProgress> progress = mProgresses[mProgress];
- ComAssertRet(!progress.isNull(), E_FAIL);
-
- HRESULT rc = S_OK;
- BOOL fCompleted = FALSE;
-
- do
- {
- rc = progress->COMGETTER(Completed)(&fCompleted);
- if (FAILED(rc))
- return rc;
-
- if (fCompleted)
- {
- rc = progress->COMGETTER(Canceled)(&mCanceled);
- if (FAILED(rc))
- return rc;
-
- LONG iRc;
- rc = progress->COMGETTER(ResultCode)(&iRc);
- if (FAILED(rc))
- return rc;
- mResultCode = iRc;
-
- if (FAILED(mResultCode))
- {
- rc = progress->COMGETTER(ErrorInfo)(mErrorInfo.asOutParam());
- if (FAILED(rc))
- return rc;
- }
-
- if (FAILED(mResultCode) || mCanceled)
- {
- mCompleted = TRUE;
- }
- else
- {
- ULONG opCount = 0;
- rc = progress->COMGETTER(OperationCount)(&opCount);
- if (FAILED(rc))
- return rc;
-
- mCompletedOperations += opCount;
- mProgress ++;
-
- if (mProgress < mProgresses.size())
- progress = mProgresses[mProgress];
- else
- mCompleted = TRUE;
- }
- }
- }
- while (fCompleted && !mCompleted);
-
- rc = progress->COMGETTER(OperationPercent)(&m_ulOperationPercent);
- if (SUCCEEDED(rc))
- {
- ULONG operation = 0;
- rc = progress->COMGETTER(Operation)(&operation);
- if (SUCCEEDED(rc) && mCompletedOperations + operation > m_ulCurrentOperation)
- {
- m_ulCurrentOperation = mCompletedOperations + operation;
- rc = progress->COMGETTER(OperationDescription)(m_bstrOperationDescription.asOutParam());
- }
- }
-
- return rc;
-}
-/* vi: set tabstop=4 shiftwidth=4 expandtab: */