VirtualBox

Changeset 27803 in vbox for trunk/src


Ignore:
Timestamp:
Mar 29, 2010 8:10:35 PM (15 years ago)
Author:
vboxsync
Message:

Main/Medium: big medium task cleanup, safe use of auto_ptr<Medium::Task>.

Location:
trunk/src/VBox/Main
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/MediumImpl.cpp

    r27774 r27803  
    178178
    179179/**
    180  * Asynchronous task thread parameter bucket.
    181  *
    182  * Note that instances of this class must be created using new() because the
    183  * task thread function will delete them when the task is complete!
     180 * Medium::Task class for asynchronous operations.
     181 *
     182 * @note Instances of this class must be created using new() because the
     183 *       task thread function will delete them when the task is complete.
    184184 *
    185185 * @note The constructor of this class adds a caller on the managed Medium
    186186 *       object which is automatically released upon destruction.
    187187 */
    188 struct Medium::Task : public com::SupportErrorInfoBase
    189 {
    190     enum Operation { CreateBase,
    191                      CreateDiff,
    192                      Merge,
    193                      Clone,
    194                      Delete,
    195                      Reset,
    196                      Compact
    197                    };
    198 
    199     Medium *that;
    200     AutoCaller m_autoCaller;
    201 
    202     ComObjPtr<Progress> m_pProgress;
    203     Operation m_operation;
    204 
    205     /** Where to save the result when executed using #runNow(). */
    206     HRESULT m_rc;
     188class Medium::Task
     189{
     190public:
     191    Task(Medium *aMedium, Progress *aProgress)
     192        : mMedium(aMedium),
     193          mMediumCaller(aMedium),
     194          mThread(NIL_RTTHREAD),
     195          mProgress(aProgress),
     196          mVDOperationIfaces(NULL),
     197          m_pfNeedsSaveSettings(NULL)
     198    {
     199        AssertReturnVoidStmt(aMedium, mRC = E_FAIL);
     200        mRC = mMediumCaller.rc();
     201        if (FAILED(mRC))
     202            return;
     203
     204        /* Set up a per-operation progress interface, can be used freely (for
     205         * binary operations you can use it either on the source or target). */
     206        mVDIfCallsProgress.cbSize = sizeof(VDINTERFACEPROGRESS);
     207        mVDIfCallsProgress.enmInterface = VDINTERFACETYPE_PROGRESS;
     208        mVDIfCallsProgress.pfnProgress = vdProgressCall;
     209        int vrc = VDInterfaceAdd(&mVDIfProgress,
     210                                "Medium::Task::vdInterfaceProgress",
     211                                VDINTERFACETYPE_PROGRESS,
     212                                &mVDIfCallsProgress,
     213                                mProgress,
     214                                &mVDOperationIfaces);
     215        AssertRC(vrc);
     216        if (RT_FAILURE(vrc))
     217            mRC = E_FAIL;
     218    }
     219
     220    // Make all destructors virtual. Just in case.
     221    virtual ~Task()
     222    {}
     223
     224    HRESULT rc() const { return mRC; }
     225    bool isOk() const { return SUCCEEDED(rc()); }
     226
     227    static int fntMediumTask(RTTHREAD aThread, void *pvUser);
     228
     229    bool isAsync() { return mThread != NIL_RTTHREAD; }
     230
     231    const ComObjPtr<Medium> mMedium;
     232    AutoCaller mMediumCaller;
    207233
    208234    // Whether the caller needs to call VirtualBox::saveSettings() after
     
    211237    bool *m_pfNeedsSaveSettings;
    212238
    213     Task(Medium *aThat,
    214          Progress *aProgress,
    215          Operation aOperation)
    216         : that(aThat),
    217           m_autoCaller(aThat),
    218           m_pProgress(aProgress),
    219           m_operation(aOperation),
    220           m_rc(S_OK),
    221           m_pfNeedsSaveSettings(NULL)
    222     { }
    223 
    224     ~Task();
    225 
    226     void setData(Medium *aTarget)
    227     {
    228         d.target = aTarget;
    229         HRESULT rc = d.target->addCaller();
    230         AssertComRC(rc);
    231     }
    232 
    233     void setData(Medium *aTarget, Medium *aParent)
    234     {
    235         d.target = aTarget;
    236         HRESULT rc = d.target->addCaller();
    237         AssertComRC(rc);
    238         d.parentDisk = aParent;
    239         if (aParent)
    240         {
    241             rc = d.parentDisk->addCaller();
    242             AssertComRC(rc);
    243         }
    244     }
    245 
    246     void setData(MergeChain *aChain)
    247     {
    248         AssertReturnVoid(aChain != NULL);
    249         d.chain.reset(aChain);
    250     }
    251 
    252     void setData(ImageChain *aSrcChain, ImageChain *aParentChain)
    253     {
    254         AssertReturnVoid(aSrcChain != NULL);
    255         AssertReturnVoid(aParentChain != NULL);
    256         d.source.reset(aSrcChain);
    257         d.parent.reset(aParentChain);
    258     }
    259 
    260     void setData(ImageChain *aImgChain)
    261     {
    262         AssertReturnVoid(aImgChain != NULL);
    263         d.images.reset(aImgChain);
    264     }
    265 
    266     HRESULT startThread();
    267     HRESULT runNow(bool *pfNeedsSaveSettings);
    268 
    269     struct Data
    270     {
    271         Data() : size(0) {}
    272 
    273         /* CreateBase */
    274 
    275         uint64_t size;
    276 
    277         /* CreateBase, CreateDiff, Clone */
    278 
    279         MediumVariant_T variant;
    280 
    281         /* CreateDiff, Clone */
    282 
    283         ComObjPtr<Medium> target;
    284 
    285         /* Clone */
    286 
    287         /** Media to open, in {parent,child} order */
    288         std::auto_ptr<ImageChain> source;
    289         /** Media which are parent of target, in {parent,child} order */
    290         std::auto_ptr<ImageChain> parent;
    291         /** The to-be parent medium object */
    292         ComObjPtr<Medium> parentDisk;
    293 
    294         /* Merge */
    295 
    296         /** Media to merge, in {parent,child} order */
    297         std::auto_ptr<MergeChain> chain;
    298 
    299         /* Compact */
    300 
    301         /** Media to open, in {parent,child} order */
    302         std::auto_ptr<ImageChain> images;
    303     } d;
     239    PVDINTERFACE mVDOperationIfaces;
    304240
    305241protected:
    306 
    307     // SupportErrorInfoBase interface
    308     const GUID &mainInterfaceID() const { return COM_IIDOF(IMedium); }
    309     const char *componentName() const { return Medium::ComponentName(); }
     242    HRESULT mRC;
     243    RTTHREAD mThread;
     244
     245private:
     246    virtual HRESULT handler() = 0;
     247
     248    const ComObjPtr<Progress> mProgress;
     249
     250    static DECLCALLBACK(int) vdProgressCall(void *pvUser, unsigned uPercent);
     251
     252    VDINTERFACE mVDIfProgress;
     253    VDINTERFACEPROGRESS mVDIfCallsProgress;
    310254};
    311255
    312 Medium::Task::~Task()
    313 {
    314     /* remove callers added by setData() */
    315     if (!d.target.isNull())
    316         d.target->releaseCaller();
    317 }
    318 
    319 /**
    320  * Starts a new thread driven by the Medium::taskThread() function and passes
    321  * this Task instance as an argument.
    322  *
    323  * Note that if this method returns success, this Task object becomes an ownee
    324  * of the started thread and will be automatically deleted when the thread
    325  * terminates.
    326  *
    327  * @note When the task is executed by this method, IProgress::notifyComplete()
    328  *       is automatically called for the progress object associated with this
    329  *       task when the task is finished to signal the operation completion for
    330  *       other threads asynchronously waiting for it.
    331  */
    332 HRESULT Medium::Task::startThread()
    333 {
    334     int vrc = RTThreadCreate(NULL, Medium::taskThread, this,
    335                              0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
    336                              "Medium::Task");
    337     ComAssertMsgRCRet(vrc,
    338                       ("Could not create Medium::Task thread (%Rrc)\n", vrc),
    339                       E_FAIL);
    340 
    341     return S_OK;
    342 }
    343 
    344 /**
    345  * Runs Medium::taskThread() by passing it this Task instance as an argument
    346  * on the current thread instead of creating a new one.
    347  *
    348  * This call implies that it is made on another temporary thread created for
    349  * some asynchronous task. Avoid calling it from a normal thread since the task
    350  * operatinos are potentially lengthy and will block the calling thread in this
    351  * case.
    352  *
    353  * Note that this Task object will be deleted by taskThread() when this method
    354  * returns!
    355  *
    356  * @note When the task is executed by this method, IProgress::notifyComplete()
    357  *       is not called for the progress object associated with this task when
    358  *       the task is finished. Instead, the result of the operation is returned
    359  *       by this method directly and it's the caller's responsibility to
    360  *       complete the progress object in this case.
    361  */
    362 HRESULT Medium::Task::runNow(bool *pfNeedsSaveSettings)
    363 {
    364     m_pfNeedsSaveSettings = pfNeedsSaveSettings;
    365 
    366     /* NIL_RTTHREAD indicates synchronous call. */
    367     Medium::taskThread(NIL_RTTHREAD, this);
    368 
    369     return m_rc;
    370 }
     256class Medium::CreateBaseTask : public Medium::Task
     257{
     258public:
     259    CreateBaseTask(Medium *aMedium,
     260                   Progress *aProgress,
     261                   uint64_t aSize,
     262                   MediumVariant_T aVariant)
     263        : Medium::Task(aMedium, aProgress),
     264          mSize(aSize),
     265          mVariant(aVariant)
     266    {}
     267
     268    uint64_t mSize;
     269    MediumVariant_T mVariant;
     270
     271private:
     272    virtual HRESULT handler();
     273};
     274
     275class Medium::CreateDiffTask : public Medium::Task
     276{
     277public:
     278    CreateDiffTask(Medium *aMedium,
     279                   Progress *aProgress,
     280                   Medium *aTarget,
     281                   MediumVariant_T aVariant)
     282        : Medium::Task(aMedium, aProgress),
     283          mTarget(aTarget),
     284          mTargetCaller(aTarget),
     285          mVariant(aVariant)
     286    {
     287        AssertReturnVoidStmt(aTarget != NULL, mRC = E_FAIL);
     288        mRC = mTargetCaller.rc();
     289        if (FAILED(mRC))
     290            return;
     291    }
     292
     293    const ComObjPtr<Medium> mTarget;
     294    MediumVariant_T mVariant;
     295
     296private:
     297    virtual HRESULT handler();
     298
     299    AutoCaller mTargetCaller;
     300};
     301
     302class Medium::CloneTask : public Medium::Task
     303{
     304public:
     305    CloneTask(Medium *aMedium,
     306              Progress *aProgress,
     307              Medium *aTarget,
     308              Medium *aParent,
     309              ImageChain *aSourceChain,
     310              ImageChain *aParentChain,
     311              MediumVariant_T aVariant)
     312        : Medium::Task(aMedium, aProgress),
     313          mTarget(aTarget),
     314          mTargetCaller(aTarget),
     315          mParent(aParent),
     316          mParentCaller(aParent),
     317          mSourceChain(aSourceChain),
     318          mParentChain(aParentChain),
     319          mVariant(aVariant)
     320    {
     321        AssertReturnVoidStmt(aTarget != NULL, mRC = E_FAIL);
     322        mRC = mTargetCaller.rc();
     323        if (FAILED(mRC))
     324            return;
     325        /* aParent may be NULL */
     326        mRC = mParentCaller.rc();
     327        if (FAILED(mRC))
     328            return;
     329        AssertReturnVoidStmt(aSourceChain != NULL, mRC = E_FAIL);
     330        AssertReturnVoidStmt(aParentChain != NULL, mRC = E_FAIL);
     331    }
     332
     333    const ComObjPtr<Medium> mTarget;
     334    const ComObjPtr<Medium> mParent;
     335    std::auto_ptr<ImageChain> mSourceChain;
     336    std::auto_ptr<ImageChain> mParentChain;
     337    MediumVariant_T mVariant;
     338
     339private:
     340    virtual HRESULT handler();
     341
     342    AutoCaller mTargetCaller;
     343    AutoCaller mParentCaller;
     344};
     345
     346class Medium::CompactTask : public Medium::Task
     347{
     348public:
     349    CompactTask(Medium *aMedium,
     350                Progress *aProgress,
     351                ImageChain *aImageChain)
     352        : Medium::Task(aMedium, aProgress),
     353          mImageChain(aImageChain)
     354    {
     355        AssertReturnVoidStmt(aImageChain != NULL, mRC = E_FAIL);
     356    }
     357
     358    std::auto_ptr<ImageChain> mImageChain;
     359
     360private:
     361    virtual HRESULT handler();
     362};
     363
     364class Medium::ResetTask : public Medium::Task
     365{
     366public:
     367    ResetTask(Medium *aMedium,
     368              Progress *aProgress)
     369        : Medium::Task(aMedium, aProgress)
     370    {}
     371
     372private:
     373    virtual HRESULT handler();
     374};
     375
     376class Medium::DeleteTask : public Medium::Task
     377{
     378public:
     379    DeleteTask(Medium *aMedium,
     380               Progress *aProgress)
     381        : Medium::Task(aMedium, aProgress)
     382    {}
     383
     384private:
     385    virtual HRESULT handler();
     386};
     387
     388class Medium::MergeTask : public Medium::Task
     389{
     390public:
     391    MergeTask(Medium *aMedium,
     392              Progress *aProgress,
     393              MergeChain *aMergeChain)
     394        : Medium::Task(aMedium, aProgress),
     395          mMergeChain(aMergeChain)
     396    {
     397        AssertReturnVoidStmt(aMergeChain != NULL, mRC = E_FAIL);
     398    }
     399
     400    std::auto_ptr<MergeChain> mMergeChain;
     401
     402private:
     403    virtual HRESULT handler();
     404};
     405
     406/**
     407 * Thread function for time-consuming medium tasks.
     408 *
     409 * @param pvUser    Pointer to the std::auto_ptr<Medium::Task> instance.
     410 */
     411/* static */
     412DECLCALLBACK(int) Medium::Task::fntMediumTask(RTTHREAD aThread, void *pvUser)
     413{
     414    LogFlowFuncEnter();
     415    /* pvUser is a pointer to a std::auto_ptr<Medium::Task>, which is so
     416     * hard to understand that we just clear this situation now by copying
     417     * it. This means the old object loses ownership, and task owns it. */
     418    AssertReturn(pvUser, (int)E_INVALIDARG);
     419    std::auto_ptr<Medium::Task> *pTask =
     420        static_cast<std::auto_ptr<Medium::Task> *>(pvUser);
     421    std::auto_ptr<Medium::Task> task(pTask->release());
     422    AssertReturn(task.get(), (int)E_INVALIDARG);
     423
     424    task->mThread = aThread;
     425
     426    HRESULT rc = task->handler();
     427
     428    /* complete the progress if run asynchronously */
     429    if (task->isAsync())
     430    {
     431        if (!task->mProgress.isNull())
     432            task->mProgress->notifyComplete(rc);
     433    }
     434
     435    LogFlowFunc(("rc=%Rhrc\n", rc));
     436    LogFlowFuncLeave();
     437
     438    return (int)rc;
     439}
     440
     441/**
     442 * PFNVDPROGRESS callback handler for Task operations.
     443 *
     444 * @param pvUser      Pointer to the Progress instance.
     445 * @param uPercent    Completetion precentage (0-100).
     446 */
     447/*static*/
     448DECLCALLBACK(int) Medium::Task::vdProgressCall(void *pvUser, unsigned uPercent)
     449{
     450    Progress *that = static_cast<Progress *>(pvUser);
     451
     452    if (that != NULL)
     453    {
     454        /* update the progress object, capping it at 99% as the final percent
     455         * is used for additional operations like setting the UUIDs and similar. */
     456        HRESULT rc = that->SetCurrentOperationProgress(uPercent * 99 / 100);
     457        if (FAILED(rc))
     458        {
     459            if (rc == E_FAIL)
     460                return VERR_CANCELLED;
     461            else
     462                return VERR_INVALID_STATE;
     463        }
     464    }
     465
     466    return VINF_SUCCESS;
     467}
     468
     469/**
     470 * Implementation code for the "create base" task.
     471 */
     472HRESULT Medium::CreateBaseTask::handler()
     473{
     474    return mMedium->taskThreadCreateBase(*this);
     475}
     476
     477/**
     478 * Implementation code for the "create diff" task.
     479 */
     480HRESULT Medium::CreateDiffTask::handler()
     481{
     482    return mMedium->taskThreadCreateDiff(*this);
     483}
     484
     485/**
     486 * Implementation code for the "clone" task.
     487 */
     488HRESULT Medium::CloneTask::handler()
     489{
     490    return mMedium->taskThreadClone(*this);
     491}
     492
     493/**
     494 * Implementation code for the "compact" task.
     495 */
     496HRESULT Medium::CompactTask::handler()
     497{
     498    return mMedium->taskThreadCompact(*this);
     499}
     500
     501/**
     502 * Implementation code for the "reset" task.
     503 */
     504HRESULT Medium::ResetTask::handler()
     505{
     506    return mMedium->taskThreadReset(*this);
     507}
     508
     509/**
     510 * Implementation code for the "delete" task.
     511 */
     512HRESULT Medium::DeleteTask::handler()
     513{
     514    return mMedium->taskThreadDelete(*this);
     515}
     516
     517/**
     518 * Implementation code for the "merge" task.
     519 */
     520HRESULT Medium::MergeTask::handler()
     521{
     522    return mMedium->taskThreadMerge(*this);
     523}
     524
    371525
    372526////////////////////////////////////////////////////////////////////////////////
     
    15551709STDMETHODIMP Medium::COMGETTER(Format)(BSTR *aFormat)
    15561710{
    1557     if (aFormat == NULL)
    1558         return E_POINTER;
     1711    CheckComArgOutPointerValid(aFormat);
    15591712
    15601713    AutoCaller autoCaller(this);
     
    15691722STDMETHODIMP Medium::COMGETTER(Type)(MediumType_T *aType)
    15701723{
    1571     if (aType == NULL)
    1572         return E_POINTER;
     1724    CheckComArgOutPointerValid(aType);
    15731725
    15741726    AutoCaller autoCaller(this);
     
    16541806STDMETHODIMP Medium::COMGETTER(Parent)(IMedium **aParent)
    16551807{
    1656     if (aParent == NULL)
    1657         return E_POINTER;
     1808    CheckComArgOutPointerValid(aParent);
    16581809
    16591810    AutoCaller autoCaller(this);
     
    16701821STDMETHODIMP Medium::COMGETTER(Children)(ComSafeArrayOut(IMedium *, aChildren))
    16711822{
    1672     if (ComSafeArrayOutIsNull(aChildren))
    1673         return E_POINTER;
     1823    CheckComArgOutSafeArrayPointerValid(aChildren);
    16741824
    16751825    AutoCaller autoCaller(this);
     
    16871837STDMETHODIMP Medium::COMGETTER(Base)(IMedium **aBase)
    16881838{
    1689     if (aBase == NULL)
    1690         return E_POINTER;
     1839    CheckComArgOutPointerValid(aBase);
    16911840
    16921841    /* base() will do callers/locking */
     
    16991848STDMETHODIMP Medium::COMGETTER(ReadOnly)(BOOL *aReadOnly)
    17001849{
    1701     if (aReadOnly == NULL)
    1702         return E_POINTER;
     1850    CheckComArgOutPointerValid(aReadOnly);
    17031851
    17041852    AutoCaller autoCaller(this);
     
    17971945STDMETHODIMP Medium::COMGETTER(MachineIds)(ComSafeArrayOut(BSTR,aMachineIds))
    17981946{
    1799     if (ComSafeGUIDArrayOutIsNull(aMachineIds))
    1800         return E_POINTER;
     1947    CheckComArgOutSafeArrayPointerValid(aMachineIds);
    18011948
    18021949    AutoCaller autoCaller(this);
     
    23132460    ComObjPtr <Progress> progress;
    23142461    progress.createObject();
    2315     /// @todo include fixed/dynamic
    23162462    HRESULT rc = progress->init(m->pVirtualBox,
    23172463                                static_cast<IMedium*>(this),
     
    23222468    if (FAILED(rc)) return rc;
    23232469
    2324     /* setup task object and thread to carry out the operation
    2325      * asynchronously */
    2326 
    2327     std::auto_ptr <Task> task(new Task(this, progress, Task::CreateBase));
    2328     AssertComRCReturnRC(task->m_autoCaller.rc());
    2329 
    2330     task->d.size = aLogicalSize;
    2331     task->d.variant = aVariant;
    2332 
    2333     rc = task->startThread();
     2470    /* setup task object to carry out the operation asynchronously */
     2471    std::auto_ptr<Medium::Task> task(new CreateBaseTask(this, progress,
     2472                                                        aLogicalSize,
     2473                                                        aVariant));
     2474    AssertComRCReturnRC(task->rc());
     2475
     2476    rc = startThread(task);
    23342477    if (FAILED(rc)) return rc;
    23352478
    23362479    /* go to Creating state on success */
    23372480    m->state = MediumState_Creating;
    2338 
    2339     /* task is now owned by taskThread() so release it */
    2340     task.release();
    2341 
    2342     /* return progress to the caller */
    2343     progress.queryInterfaceTo(aProgress);
    23442481
    23452482    return S_OK;
     
    23962533        HRESULT rc2 = UnlockRead(NULL);
    23972534        AssertComRC(rc2);
    2398         /* Note: on success, taskThread() will unlock this */
     2535        /* Note: on success, the task will unlock this */
    23992536    }
    24002537    else
     
    24502587
    24512588        /* Build the source chain and lock images in the proper order. */
    2452         std::auto_ptr <ImageChain> srcChain(new ImageChain());
     2589        std::auto_ptr<ImageChain> sourceChain(new ImageChain());
    24532590
    24542591        for (Medium *hd = this;
     
    24562593             hd = hd->m->pParent)
    24572594        {
    2458             rc = srcChain->addImage(hd);
     2595            rc = sourceChain->addImage(hd);
    24592596            if (FAILED(rc)) throw rc;
    24602597        }
    2461         rc = srcChain->lockImagesRead();
     2598        rc = sourceChain->lockImagesRead();
    24622599        if (FAILED(rc)) throw rc;
    24632600
    24642601        /* Build the parent chain and lock images in the proper order. */
    2465         std::auto_ptr <ImageChain> parentChain(new ImageChain());
     2602        std::auto_ptr<ImageChain> parentChain(new ImageChain());
    24662603
    24672604        for (Medium *hd = parent;
     
    24942631        if (FAILED(rc)) throw rc;
    24952632
    2496         /* setup task object and thread to carry out the operation
    2497          * asynchronously */
    2498 
    2499         std::auto_ptr<Task> task(new Task(this, progress, Task::Clone));
    2500         AssertComRCThrowRC(task->m_autoCaller.rc());
    2501 
    2502         task->setData(target, parent);
    2503         task->d.variant = aVariant;
    2504         task->setData(srcChain.release(), parentChain.release());
    2505 
    2506         rc = task->startThread();
     2633        /* setup task object to carry out the operation asynchronously */
     2634        std::auto_ptr<Medium::Task> task(new CloneTask(this, progress,
     2635                                                       target, parent,
     2636                                                       sourceChain.release(),
     2637                                                       parentChain.release(),
     2638                                                       aVariant));
     2639        AssertComRCReturnRC(task->rc());
     2640
     2641        rc = startThread(task);
    25072642        if (FAILED(rc)) throw rc;
    25082643
     
    25122647            target->m->state = MediumState_Creating;
    25132648        }
    2514 
    2515         /* task is now owned (or already deleted) by taskThread() so release it */
    2516         task.release();
    25172649    }
    25182650    catch (HRESULT aRC)
     
    25482680
    25492681        /* Build the image chain and lock images in the proper order. */
    2550         std::auto_ptr <ImageChain> imgChain(new ImageChain());
     2682        std::auto_ptr<ImageChain> imgChain(new ImageChain());
    25512683
    25522684        /* we walk the image tree */
     
    25692701        if (FAILED(rc)) throw rc;
    25702702
    2571         /* setup task object and thread to carry out the operation
    2572          * asynchronously */
    2573 
    2574         std::auto_ptr <Task> task(new Task(this, progress, Task::Compact));
    2575         AssertComRCThrowRC(task->m_autoCaller.rc());
    2576 
    2577         task->setData(imgChain.release());
    2578 
    2579         rc = task->startThread();
     2703        /* setup task object to carry out the operation asynchronously */
     2704        std::auto_ptr<Medium::Task> task(new CompactTask(this, progress,
     2705                                                         imgChain.release()));
     2706        AssertComRCReturnRC(task->rc());
     2707
     2708        rc = startThread(task);
    25802709        if (FAILED(rc)) throw rc;
    2581 
    2582         /* task is now owned (or already deleted) by taskThread() so release it */
    2583         task.release();
    25842710    }
    25852711    catch (HRESULT aRC)
     
    26452771        if (FAILED(rc)) throw rc;
    26462772
    2647         /* setup task object and thread to carry out the operation
    2648          * asynchronously */
    2649         std::auto_ptr<Task> task(new Task(this, progress, Task::Reset));
    2650         AssertComRCThrowRC(task->m_autoCaller.rc());
    2651 
    2652         rc = task->startThread();
     2773        /* setup task object to carry out the operation asynchronously */
     2774        std::auto_ptr<Medium::Task> task(new ResetTask(this, progress));
     2775        AssertComRCReturnRC(task->rc());
     2776
     2777        rc = startThread(task);
    26532778        if (FAILED(rc)) throw rc;
    2654 
    2655         /* task is now owned (or already deleted) by taskThread() so release it */
    2656         task.release();
    26572779    }
    26582780    catch (HRESULT aRC)
     
    26652787        HRESULT rc2 = UnlockWrite(NULL);
    26662788        AssertComRC(rc2);
    2667         /* Note: on success, taskThread() will unlock this */
     2789        /* Note: on success, the task will unlock this */
    26682790    }
    26692791    else
     
    39534075
    39544076                    /// @todo NEWMEDIA what to do if the parent is not
    3955                     /// accessible while the diff is? Probably, nothing. The
     4077                    /// accessible while the diff is? Probably nothing. The
    39564078                    /// real code will detect the mismatch anyway.
    39574079                }
     
    42084330    }
    42094331
    4210     std::auto_ptr<Task> task(new Task(this, progress, Task::Delete));
    4211     AssertComRCReturnRC(task->m_autoCaller.rc());
     4332    /* setup task object to carry out the operation asynchronously */
     4333    std::auto_ptr<Medium::Task> task(new DeleteTask(this, progress));
     4334    AssertComRCReturnRC(task->rc());
    42124335
    42134336    if (aWait)
     
    42164339        m->state = MediumState_Deleting;
    42174340
    4218         rc = task->runNow(NULL /* pfNeedsSaveSettings*/ );        // there is no save settings to do in taskThreadDelete()
     4341        rc = runNow(task, NULL /* pfNeedsSaveSettings*/ );        // there is no save settings to do in taskThreadDelete()
    42194342    }
    42204343    else
    42214344    {
    4222         rc = task->startThread();
     4345        rc = startThread(task);
    42234346        if (FAILED(rc)) return rc;
    42244347
     
    42274350    }
    42284351
    4229     /* task is now owned (or already deleted) by taskThread() so release it */
    4230     task.release();
    4231 
    42324352    if (aProgress != NULL)
    42334353    {
     
    42454365 * As opposed to the CreateDiffStorage() method, this method doesn't try to lock
    42464366 * this hard disk for reading assuming that the caller has already done so. This
    4247  * is used when taking an online snaopshot (where all original hard disks are
     4367 * is used when taking an online snapshot (where all original hard disks are
    42484368 * locked for writing and must remain such). Note however that if @a aWait is
    42494369 * @c false and this method returns a success then the thread started by
     
    43504470    }
    43514471
    4352     /* set up task object and thread to carry out the operation
    4353      * asynchronously */
    4354 
    4355     std::auto_ptr<Task> task(new Task(this, progress, Task::CreateDiff));
    4356     AssertComRCReturnRC(task->m_autoCaller.rc());
    4357 
    4358     task->setData(aTarget);
    4359     task->d.variant = aVariant;
     4472    /* setup task object to carry out the operation asynchronously */
     4473    std::auto_ptr<Medium::Task> task(new CreateDiffTask(this, progress,
     4474                                                        aTarget, aVariant));
     4475    AssertComRCReturnRC(task->rc());
    43604476
    43614477    /* register a task (it will deregister itself when done) */
     
    43734489        alock.release();
    43744490
    4375         rc = task->runNow(pfNeedsSaveSettings);
     4491        rc = runNow(task, pfNeedsSaveSettings);
    43764492    }
    43774493    else
    43784494    {
    4379         rc = task->startThread();
     4495        rc = startThread(task);
    43804496        if (FAILED(rc)) return rc;
    43814497
     
    43834499        aTarget->m->state = MediumState_Creating;
    43844500    }
    4385 
    4386     /* task is now owned (or already deleted) by taskThread() so release it */
    4387     task.release();
    43884501
    43894502    if (aProgress != NULL)
     
    44704583
    44714584    /* build the chain (will do necessary checks and state changes) */
    4472     std::auto_ptr <MergeChain> chain(new MergeChain(forward,
    4473                                                       aIgnoreAttachments));
     4585    std::auto_ptr<MergeChain> chain(new MergeChain(forward,
     4586                                                   aIgnoreAttachments));
    44744587    {
    44754588        Medium *last = forward ? aTarget : this;
     
    46084721    }
    46094722
    4610     /* setup task object and thread to carry out the operation
    4611      * asynchronously */
    4612 
    4613     std::auto_ptr <Task> task(new Task(this, progress, Task::Merge));
    4614     AssertComRCReturnRC(task->m_autoCaller.rc());
    4615 
    4616     task->setData(aChain);
     4723    /* setup task object to carry out the operation asynchronously */
     4724    std::auto_ptr<Medium::Task> task(new MergeTask(this, progress, aChain));
     4725    AssertComRCReturnRC(task->rc());
    46174726
    46184727    /* Note: task owns aChain (will delete it when not needed) in all cases
     
    46234732    if (aWait)
    46244733    {
    4625         rc = task->runNow(pfNeedsSaveSettings);
     4734        rc = runNow(task, pfNeedsSaveSettings);
    46264735    }
    46274736    else
    46284737    {
    4629         rc = task->startThread();
     4738        rc = startThread(task);
    46304739        if (FAILED(rc)) return rc;
    46314740    }
    4632 
    4633     /* task is now owned (or already deleted) by taskThread() so release it */
    4634     task.release();
    46354741
    46364742    if (aProgress != NULL)
     
    48484954}
    48494955
    4850 /**
    4851  * PFNVDPROGRESS callback handler for Task operations.
    4852  *
    4853  * @param pvUser      Pointer to the Progress instance.
    4854  * @param uPercent    Completetion precentage (0-100).
    4855  */
    4856 /*static*/
    4857 DECLCALLBACK(int) Medium::vdProgressCall(void *pvUser, unsigned uPercent)
    4858 {
    4859     Progress *that = static_cast<Progress *>(pvUser);
    4860 
    4861     if (that != NULL)
    4862     {
    4863         /* update the progress object, capping it at 99% as the final percent
    4864          * is used for additional operations like setting the UUIDs and similar. */
    4865         HRESULT rc = that->SetCurrentOperationProgress(uPercent * 99 / 100);
    4866         if (FAILED(rc))
    4867         {
    4868             if (rc == E_FAIL)
    4869                 return VERR_CANCELLED;
    4870             else
    4871                 return VERR_INVALID_STATE;
    4872         }
    4873     }
    4874 
    4875     return VINF_SUCCESS;
    4876 }
    4877 
    48784956/* static */
    48794957DECLCALLBACK(bool) Medium::vdConfigAreKeysValid(void *pvUser,
     
    49395017
    49405018/**
    4941  * Implementation code called from Medium::taskThread for the "create base" task.
     5019 * Starts a new thread driven by the appropriate Medium::Task::handler() method.
     5020 *
     5021 * @note if this method returns success, this Medium::Task object becomes owned
     5022 *       by the started thread and will be automatically deleted when the
     5023 *       thread terminates.
     5024 *
     5025 * @note When the task is executed by this method, IProgress::notifyComplete()
     5026 *       is automatically called for the progress object associated with this
     5027 *       task when the task is finished to signal the operation completion for
     5028 *       other threads asynchronously waiting for it.
     5029 */
     5030HRESULT Medium::startThread(std::auto_ptr<Medium::Task> task)
     5031{
     5032    /// @todo use a more descriptive task name
     5033    int vrc = RTThreadCreate(NULL, Medium::Task::fntMediumTask, &task,
     5034                             0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
     5035                             "Medium::Task");
     5036    ComAssertMsgRCRet(vrc,
     5037                      ("Could not create Medium::Task thread (%Rrc)\n", vrc),
     5038                      E_FAIL);
     5039
     5040    return S_OK;
     5041}
     5042
     5043/**
     5044 * Runs Medium::Task::handler() on the current thread instead of creating
     5045 * a new one.
     5046 *
     5047 * This call implies that it is made on another temporary thread created for
     5048 * some asynchronous task. Avoid calling it from a normal thread since the task
     5049 * operations are potentially lengthy and will block the calling thread in this
     5050 * case.
     5051 *
     5052 * @note This Medium::Task object will be deleted when this method returns.
     5053 *
     5054 * @note When the task is executed by this method, IProgress::notifyComplete()
     5055 *       is not called for the progress object associated with this task when
     5056 *       the task is finished. Instead, the result of the operation is returned
     5057 *       by this method directly and it's the caller's responsibility to
     5058 *       complete the progress object in this case.
     5059 */
     5060HRESULT Medium::runNow(std::auto_ptr<Medium::Task> task,
     5061                       bool *pfNeedsSaveSettings)
     5062{
     5063    task->m_pfNeedsSaveSettings = pfNeedsSaveSettings;
     5064
     5065    /* NIL_RTTHREAD indicates synchronous call. */
     5066    return (HRESULT)Medium::Task::fntMediumTask(NIL_RTTHREAD, &task);
     5067}
     5068
     5069/**
     5070 * Implementation code for the "create base" task.
    49425071 *
    49435072 * This only gets started from Medium::CreateBaseStorage() and always runs
    4944  * asynchronously. As a result, we always save the VirtualBox.xml file when we're
    4945  * done here.
     5073 * asynchronously. As a result, we always save the VirtualBox.xml file when
     5074 * we're done here.
    49465075 *
    49475076 * @param task
    4948  * @param pvdOperationIfaces
    49495077 * @return
    49505078 */
    4951 HRESULT Medium::taskThreadCreateBase(Task &task, void *pvdOperationIfaces)
     5079HRESULT Medium::taskThreadCreateBase(CreateBaseTask &task)
    49525080{
    49535081    HRESULT rc = S_OK;
    4954 
    4955     PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;
    49565082
    49575083    /* these parameters we need after creation */
     
    49995125                               format.c_str(),
    50005126                               location.c_str(),
    5001                                task.d.size * _1M,
    5002                                task.d.variant,
     5127                               task.mSize * _1M,
     5128                               task.mVariant,
    50035129                               NULL,
    50045130                               &geo,
     
    50075133                               VD_OPEN_FLAGS_NORMAL,
    50085134                               NULL,
    5009                                vdOperationIfaces);
     5135                               task.mVDOperationIfaces);
    50105136            if (RT_FAILURE(vrc))
    50115137            {
     
    50655191
    50665192/**
    5067  * Implementation code called from Medium::taskThread for the "create diff" task.
     5193 * Implementation code for the "create diff" task.
    50685194 *
    50695195 * This task always gets started from Medium::createDiffStorage() and can run
    5070  * synchronously or asynchrously depending on the "wait" parameter passed to that
    5071  * function. If we run synchronously, the caller expects the bool *pfNeedsSaveSettings
    5072  * to be set before returning; otherwise (in asynchronous mode), we save the settings
    5073  * ourselves.
     5196 * synchronously or asynchrously depending on the "wait" parameter passed to
     5197 * that function. If we run synchronously, the caller expects the bool
     5198 * *pfNeedsSaveSettings to be set before returning; otherwise (in asynchronous
     5199 * mode), we save the settings ourselves.
    50745200 *
    50755201 * @param task
    5076  * @param pvdOperationIfaces
    50775202 * @return
    50785203 */
    5079 HRESULT Medium::taskThreadCreateDiff(Task &task, void *pvdOperationIfaces, bool fIsAsync)
     5204HRESULT Medium::taskThreadCreateDiff(CreateDiffTask &task)
    50805205{
    50815206    HRESULT rc = S_OK;
    50825207
    5083     PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;
    5084 
    50855208    bool fNeedsSaveSettings = false;
    50865209
    5087     ComObjPtr<Medium> &pTarget = task.d.target;
     5210    const ComObjPtr<Medium> &pTarget = task.mTarget;
    50885211
    50895212    uint64_t size = 0, logicalSize = 0;
     
    51465269            if (FAILED(rc)) throw rc;
    51475270
    5148             /** @todo add VD_IMAGE_FLAGS_DIFF to the image flags, to
    5149                 * be on the safe side. */
    51505271            vrc = VDCreateDiff(hdd,
    51515272                               targetFormat.c_str(),
    51525273                               targetLocation.c_str(),
    5153                                task.d.variant,
     5274                               task.mVariant | VD_IMAGE_FLAGS_DIFF,
    51545275                               NULL,
    51555276                               targetId.raw(),
     
    51575278                               VD_OPEN_FLAGS_NORMAL,
    51585279                               pTarget->m->vdDiskIfaces,
    5159                                vdOperationIfaces);
     5280                               task.mVDOperationIfaces);
    51605281            if (RT_FAILURE(vrc))
    51615282                throw setError(E_FAIL,
     
    52205341    }
    52215342
    5222     if (fIsAsync)
     5343    if (task.isAsync())
    52235344    {
    52245345        /* unlock ourselves when done (unless in MediumState_LockedWrite
     
    52535374
    52545375/**
    5255  * Implementation code called from Medium::taskThread for the "merge" task.
     5376 * Implementation code for the "merge" task.
    52565377 *
    52575378 * This task always gets started from Medium::mergeTo() and can run
    5258  * synchronously or asynchrously depending on the "wait" parameter passed to that
    5259  * function. If we run synchronously, the caller expects the bool *pfNeedsSaveSettings
    5260  * to be set before returning; otherwise (in asynchronous mode), we save the settings
    5261  * ourselves.
     5379 * synchronously or asynchrously depending on the "wait" parameter passed to
     5380 * that function. If we run synchronously, the caller expects the bool
     5381 * *pfNeedsSaveSettings to be set before returning; otherwise (in asynchronous
     5382 * mode), we save the settings ourselves.
    52625383 *
    52635384 * @param task
    5264  * @param pvdOperationIfaces
    52655385 * @return
    52665386 */
    5267 HRESULT Medium::taskThreadMerge(Task &task, void *pvdOperationIfaces, bool fIsAsync)
     5387HRESULT Medium::taskThreadMerge(MergeTask &task)
    52685388{
    52695389    HRESULT rc = S_OK;
    5270 
    5271     PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;
    52725390
    52735391    /* The lock is also used as a signal from the task initiator (which
     
    52805398    }
    52815399
    5282     MergeChain *chain = task.d.chain.get();
     5400    MergeChain *chain = task.mMergeChain.get();
    52835401
    52845402    try
     
    53405458            }
    53415459
    5342             vrc = VDMerge(hdd, chain->sourceIdx(), chain->targetIdx(), vdOperationIfaces);
     5460            vrc = VDMerge(hdd, chain->sourceIdx(), chain->targetIdx(),
     5461                          task.mVDOperationIfaces);
    53435462            if (RT_FAILURE(vrc))
    53445463                throw vrc;
    53455464
    53465465            /* update parent UUIDs */
    5347             /// @todo VDMerge should handle the
    5348             /// multiple children case
    53495466            if (!chain->isForward())
    53505467            {
     
    54865603             * the caller's responsibility) */
    54875604            if (*it == this)
    5488                 task.m_autoCaller.release();
     5605                task.mMediumCaller.release();
    54895606
    54905607            /* release the caller added by MergeChain before uninit() */
    54915608            (*it)->releaseCaller();
    54925609
    5493             if (fIsAsync || *it != this)
     5610            if (task.isAsync() || *it != this)
    54945611                (*it)->uninit();
    54955612
    54965613            /* delete (to prevent uninitialization in MergeChain
    5497                 * dtor) and advance to the next item */
     5614             * dtor) and advance to the next item */
    54985615            it = chain->erase(it);
    54995616        }
    55005617    }
    55015618
    5502     if (fIsAsync)
     5619    if (task.isAsync())
    55035620    {
    55045621        // in asynchronous mode, save settings now
     
    55245641         * don't own the merge chain, so release it in this case. */
    55255642
    5526         if (!fIsAsync)
    5527             task.d.chain.release();
     5643        if (!task.isAsync())
     5644            task.mMergeChain.release();
    55285645    }
    55295646
     
    55325649
    55335650/**
    5534  * Implementation code called from Medium::taskThread for the "clone" task.
     5651 * Implementation code for the "clone" task.
     5652 *
    55355653 * This only gets started from Medium::CloneTo() and always runs asynchronously.
    55365654 * As a result, we always save the VirtualBox.xml file when we're done here.
    55375655 *
    55385656 * @param task
    5539  * @param pvdOperationIfaces
    55405657 * @return
    55415658 */
    5542 HRESULT Medium::taskThreadClone(Task &task, void *pvdOperationIfaces)
     5659HRESULT Medium::taskThreadClone(CloneTask &task)
    55435660{
    55445661    HRESULT rc = S_OK;
    55455662
    5546     PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;
    5547 
    5548     ComObjPtr<Medium> &pTarget = task.d.target;
    5549     ComObjPtr<Medium> &pParent = task.d.parentDisk;
     5663    const ComObjPtr<Medium> &pTarget = task.mTarget;
     5664    const ComObjPtr<Medium> &pParent = task.mParent;
    55505665
    55515666    bool fCreatingTarget = false;
     
    55635678        fCreatingTarget = pTarget->m->state == MediumState_Creating;
    55645679
    5565         ImageChain *srcChain = task.d.source.get();
    5566         ImageChain *parentChain = task.d.parent.get();
     5680        ImageChain *sourceChain = task.mSourceChain.get();
     5681        ImageChain *parentChain = task.mParentChain.get();
    55675682
    55685683        /* The object may request a specific UUID (through a special form of
     
    55845699        {
    55855700            /* Open all hard disk images in the source chain. */
    5586             for (MediaList::const_iterator it = srcChain->begin();
    5587                  it != srcChain->end();
     5701            for (MediaList::const_iterator it = sourceChain->begin();
     5702                 it != sourceChain->end();
    55885703                 ++it)
    55895704            {
     
    56575772                             false,
    56585773                             0,
    5659                              task.d.variant,
     5774                             task.mVariant,
    56605775                             targetId.raw(),
    56615776                             NULL,
    56625777                             pTarget->m->vdDiskIfaces,
    5663                              vdOperationIfaces);
     5778                             task.mVDOperationIfaces);
    56645779                if (RT_FAILURE(vrc))
    56655780                    throw setError(E_FAIL,
     
    57455860     * that we get a deadlock in Appliance::Import when Medium::Close
    57465861     * is called & the source chain is released at the same time. */
    5747     task.d.source.reset();
     5862    task.mSourceChain.reset();
    57485863
    57495864    return rc;
     
    57515866
    57525867/**
    5753  * Implementation code called from Medium::taskThread for the "delete" task.
     5868 * Implementation code for the "delete" task.
    57545869 *
    57555870 * This task always gets started from Medium::deleteStorage() and can run
    5756  * synchronously or asynchrously depending on the "wait" parameter passed to that
    5757  * function.
    5758  *
     5871 * synchronously or asynchrously depending on the "wait" parameter passed to
     5872 * that function.
     5873 *
     5874 * @param task
    57595875 * @return
    57605876 */
    5761 HRESULT Medium::taskThreadDelete()
     5877HRESULT Medium::taskThreadDelete(DeleteTask &task)
    57625878{
    57635879    HRESULT rc = S_OK;
     
    58175933
    58185934/**
    5819  * Implementation code called from Medium::taskThread for the "reset" task.
     5935 * Implementation code for the "reset" task.
    58205936 *
    58215937 * This always gets started asynchronously from Medium::Reset().
    58225938 *
    58235939 * @param task
    5824  * @param pvdOperationIfaces
    58255940 * @return
    58265941 */
    5827 HRESULT Medium::taskThreadReset(void *pvdOperationIfaces, bool fIsAsync)
     5942HRESULT Medium::taskThreadReset(ResetTask &task)
    58285943{
    58295944    HRESULT rc = S_OK;
    5830 
    5831     PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;
    58325945
    58335946    uint64_t size = 0, logicalSize = 0;
     
    58986011                               VD_OPEN_FLAGS_NORMAL,
    58996012                               m->vdDiskIfaces,
    5900                                vdOperationIfaces);
     6013                               task.mVDOperationIfaces);
    59016014            if (RT_FAILURE(vrc))
    59026015                throw setError(E_FAIL,
     
    59186031    m->logicalSize = logicalSize;
    59196032
    5920     if (fIsAsync)
     6033    if (task.isAsync())
    59216034    {
    59226035        /* unlock ourselves when done */
     
    59326045
    59336046/**
    5934  * Implementation code called from Medium::taskThread for the "compact" task.
    5935  * @param pvdOperationIfaces
     6047 * Implementation code for the "compact" task.
     6048 *
     6049 * @param task
    59366050 * @return
    59376051 */
    5938 HRESULT Medium::taskThreadCompact(Task &task, void *pvdOperationIfaces)
     6052HRESULT Medium::taskThreadCompact(CompactTask &task)
    59396053{
    59406054    HRESULT rc = S_OK;
    5941 
    5942     PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;
    59436055
    59446056    /* Lock all in {parent,child} order. The lock is also used as a
     
    59476059    AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS);
    59486060
    5949     ImageChain *imgChain = task.d.images.get();
     6061    ImageChain *imgChain = task.mImageChain.get();
    59506062
    59516063    try
     
    59906102            thisLock.leave();
    59916103
    5992             vrc = VDCompact(hdd, VD_LAST_IMAGE, vdOperationIfaces);
     6104            vrc = VDCompact(hdd, VD_LAST_IMAGE, task.mVDOperationIfaces);
    59936105            if (RT_FAILURE(vrc))
    59946106            {
     
    60206132}
    60216133
    6022 
    6023 /**
    6024  * Thread function for time-consuming tasks.
    6025  *
    6026  * The Task structure passed to @a pvUser must be allocated using new and will
    6027  * be freed by this method before it returns.
    6028  *
    6029  * @param pvUser    Pointer to the Task instance.
    6030  */
    6031 /* static */
    6032 DECLCALLBACK(int) Medium::taskThread(RTTHREAD thread, void *pvUser)
    6033 {
    6034     std::auto_ptr<Task> task(static_cast<Task*>(pvUser));
    6035     AssertReturn(task.get(), VERR_GENERAL_FAILURE);
    6036 
    6037     bool fIsAsync = thread != NIL_RTTHREAD;
    6038 
    6039     Medium *that = task->that;
    6040 
    6041     /* Set up a per-operation progress interface, can be used freely (for
    6042      * binary operations you can use it either on the source or target). */
    6043     VDINTERFACEPROGRESS vdIfCallsProgress;
    6044     vdIfCallsProgress.cbSize = sizeof(VDINTERFACEPROGRESS);
    6045     vdIfCallsProgress.enmInterface = VDINTERFACETYPE_PROGRESS;
    6046     vdIfCallsProgress.pfnProgress = Medium::vdProgressCall;
    6047     VDINTERFACE vdIfProgress;
    6048     PVDINTERFACE vdOperationIfaces = NULL;
    6049     int vrc1 = VDInterfaceAdd(&vdIfProgress,
    6050                              "Medium::vdInterfaceProgress",
    6051                              VDINTERFACETYPE_PROGRESS,
    6052                              &vdIfCallsProgress,
    6053                              task->m_pProgress,
    6054                              &vdOperationIfaces);
    6055     AssertRCReturn(vrc1, E_FAIL);
    6056 
    6057     /* Note: no need in AutoCaller because Task does that */
    6058 
    6059     LogFlowFuncEnter();
    6060     LogFlowFunc(("{%p}: operation=%d\n", that, task->m_operation));
    6061 
    6062     HRESULT rc = S_OK;
    6063 
    6064     switch (task->m_operation)
    6065     {
    6066         ////////////////////////////////////////////////////////////////////////
    6067 
    6068         case Task::CreateBase:
    6069             rc = that->taskThreadCreateBase(*task, (void*)vdOperationIfaces);
    6070         break;
    6071 
    6072         case Task::CreateDiff:
    6073             rc = that->taskThreadCreateDiff(*task, (void*)vdOperationIfaces, fIsAsync);
    6074         break;
    6075 
    6076         case Task::Merge:
    6077             rc = that->taskThreadMerge(*task, (void*)vdOperationIfaces, fIsAsync);
    6078         break;
    6079 
    6080         case Task::Clone:
    6081             rc = that->taskThreadClone(*task, (void*)vdOperationIfaces);
    6082         break;
    6083 
    6084         case Task::Delete:
    6085             rc = that->taskThreadDelete();
    6086         break;
    6087 
    6088         case Task::Reset:
    6089             rc = that->taskThreadReset((void*)vdOperationIfaces, fIsAsync);
    6090         break;
    6091 
    6092         case Task::Compact:
    6093             rc = that->taskThreadCompact(*task, (void*)vdOperationIfaces);
    6094         break;
    6095 
    6096         default:
    6097             AssertFailedReturn(VERR_GENERAL_FAILURE);
    6098     }
    6099 
    6100     /* complete the progress if run asynchronously */
    6101     if (fIsAsync)
    6102     {
    6103         if (!task->m_pProgress.isNull())
    6104             task->m_pProgress->notifyComplete(rc);
    6105     }
    6106     else
    6107     {
    6108         task->m_rc = rc;
    6109     }
    6110 
    6111     LogFlowFunc(("rc=%Rhrc\n", rc));
    6112     LogFlowFuncLeave();
    6113 
    6114     return VINF_SUCCESS;
    6115 
    6116     /// @todo ugly hack, fix ComAssert... later
    6117     #undef setError
    6118 }
    6119 
    61206134/* vi: set tabstop=4 shiftwidth=4 expandtab: */
  • trunk/src/VBox/Main/include/MediumImpl.h

    r27232 r27803  
    294294                                          const char *pszFormat, va_list va);
    295295
    296     static DECLCALLBACK(int) vdProgressCall(void *pvUser, unsigned uPercent);
    297 
    298296    static DECLCALLBACK(bool) vdConfigAreKeysValid(void *pvUser,
    299297                                                   const char *pszzValid);
     
    303301                                           char *pszValue, size_t cchValue);
    304302
    305     struct Task;
    306     friend struct Task;
    307 
    308     HRESULT taskThreadCreateBase(Task &task, void *pvdOperationIfaces);
    309     HRESULT taskThreadCreateDiff(Task &task, void *pvdOperationIfaces, bool fIsAsync);
    310     HRESULT taskThreadMerge(Task &task, void *pvdOperationIfaces, bool fIsAsync);
    311     HRESULT taskThreadClone(Task &task, void *pvdOperationIfaces);
    312     HRESULT taskThreadDelete();
    313     HRESULT taskThreadReset(void *pvdOperationIfaces, bool fIsAsync);
    314     HRESULT taskThreadCompact(Task &task, void *pvdOperationIfaces);
    315 
    316     static DECLCALLBACK(int) taskThread(RTTHREAD thread, void *pvUser);
     303    class Task;
     304    class CreateBaseTask;
     305    class CreateDiffTask;
     306    class CloneTask;
     307    class CompactTask;
     308    class ResetTask;
     309    class DeleteTask;
     310    class MergeTask;
     311    friend class Task;
     312    friend class CreateBaseTask;
     313    friend class CreateDiffTask;
     314    friend class CloneTask;
     315    friend class CompactTask;
     316    friend class ResetTask;
     317    friend class DeleteTask;
     318    friend class MergeTask;
     319
     320    HRESULT startThread(std::auto_ptr<Task> task);
     321    HRESULT runNow(std::auto_ptr<Task> task, bool *pfNeedsSaveSettings);
     322
     323    HRESULT taskThreadCreateBase(CreateBaseTask &task);
     324    HRESULT taskThreadCreateDiff(CreateDiffTask &task);
     325    HRESULT taskThreadMerge(MergeTask &task);
     326    HRESULT taskThreadClone(CloneTask &task);
     327    HRESULT taskThreadDelete(DeleteTask &task);
     328    HRESULT taskThreadReset(ResetTask &task);
     329    HRESULT taskThreadCompact(CompactTask &task);
    317330
    318331    struct Data;            // opaque data struct, defined in MediumImpl.cpp
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette