- Timestamp:
- Mar 29, 2010 8:10:35 PM (15 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/MediumImpl.cpp
r27774 r27803 178 178 179 179 /** 180 * Asynchronous task thread parameter bucket.181 * 182 * Note that instances of this class must be created using new() because the183 * 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. 184 184 * 185 185 * @note The constructor of this class adds a caller on the managed Medium 186 186 * object which is automatically released upon destruction. 187 187 */ 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; 188 class Medium::Task 189 { 190 public: 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; 207 233 208 234 // Whether the caller needs to call VirtualBox::saveSettings() after … … 211 237 bool *m_pfNeedsSaveSettings; 212 238 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; 304 240 305 241 protected: 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 245 private: 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; 310 254 }; 311 255 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 } 256 class Medium::CreateBaseTask : public Medium::Task 257 { 258 public: 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 271 private: 272 virtual HRESULT handler(); 273 }; 274 275 class Medium::CreateDiffTask : public Medium::Task 276 { 277 public: 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 296 private: 297 virtual HRESULT handler(); 298 299 AutoCaller mTargetCaller; 300 }; 301 302 class Medium::CloneTask : public Medium::Task 303 { 304 public: 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 339 private: 340 virtual HRESULT handler(); 341 342 AutoCaller mTargetCaller; 343 AutoCaller mParentCaller; 344 }; 345 346 class Medium::CompactTask : public Medium::Task 347 { 348 public: 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 360 private: 361 virtual HRESULT handler(); 362 }; 363 364 class Medium::ResetTask : public Medium::Task 365 { 366 public: 367 ResetTask(Medium *aMedium, 368 Progress *aProgress) 369 : Medium::Task(aMedium, aProgress) 370 {} 371 372 private: 373 virtual HRESULT handler(); 374 }; 375 376 class Medium::DeleteTask : public Medium::Task 377 { 378 public: 379 DeleteTask(Medium *aMedium, 380 Progress *aProgress) 381 : Medium::Task(aMedium, aProgress) 382 {} 383 384 private: 385 virtual HRESULT handler(); 386 }; 387 388 class Medium::MergeTask : public Medium::Task 389 { 390 public: 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 402 private: 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 */ 412 DECLCALLBACK(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*/ 448 DECLCALLBACK(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 */ 472 HRESULT Medium::CreateBaseTask::handler() 473 { 474 return mMedium->taskThreadCreateBase(*this); 475 } 476 477 /** 478 * Implementation code for the "create diff" task. 479 */ 480 HRESULT Medium::CreateDiffTask::handler() 481 { 482 return mMedium->taskThreadCreateDiff(*this); 483 } 484 485 /** 486 * Implementation code for the "clone" task. 487 */ 488 HRESULT Medium::CloneTask::handler() 489 { 490 return mMedium->taskThreadClone(*this); 491 } 492 493 /** 494 * Implementation code for the "compact" task. 495 */ 496 HRESULT Medium::CompactTask::handler() 497 { 498 return mMedium->taskThreadCompact(*this); 499 } 500 501 /** 502 * Implementation code for the "reset" task. 503 */ 504 HRESULT Medium::ResetTask::handler() 505 { 506 return mMedium->taskThreadReset(*this); 507 } 508 509 /** 510 * Implementation code for the "delete" task. 511 */ 512 HRESULT Medium::DeleteTask::handler() 513 { 514 return mMedium->taskThreadDelete(*this); 515 } 516 517 /** 518 * Implementation code for the "merge" task. 519 */ 520 HRESULT Medium::MergeTask::handler() 521 { 522 return mMedium->taskThreadMerge(*this); 523 } 524 371 525 372 526 //////////////////////////////////////////////////////////////////////////////// … … 1555 1709 STDMETHODIMP Medium::COMGETTER(Format)(BSTR *aFormat) 1556 1710 { 1557 if (aFormat == NULL) 1558 return E_POINTER; 1711 CheckComArgOutPointerValid(aFormat); 1559 1712 1560 1713 AutoCaller autoCaller(this); … … 1569 1722 STDMETHODIMP Medium::COMGETTER(Type)(MediumType_T *aType) 1570 1723 { 1571 if (aType == NULL) 1572 return E_POINTER; 1724 CheckComArgOutPointerValid(aType); 1573 1725 1574 1726 AutoCaller autoCaller(this); … … 1654 1806 STDMETHODIMP Medium::COMGETTER(Parent)(IMedium **aParent) 1655 1807 { 1656 if (aParent == NULL) 1657 return E_POINTER; 1808 CheckComArgOutPointerValid(aParent); 1658 1809 1659 1810 AutoCaller autoCaller(this); … … 1670 1821 STDMETHODIMP Medium::COMGETTER(Children)(ComSafeArrayOut(IMedium *, aChildren)) 1671 1822 { 1672 if (ComSafeArrayOutIsNull(aChildren)) 1673 return E_POINTER; 1823 CheckComArgOutSafeArrayPointerValid(aChildren); 1674 1824 1675 1825 AutoCaller autoCaller(this); … … 1687 1837 STDMETHODIMP Medium::COMGETTER(Base)(IMedium **aBase) 1688 1838 { 1689 if (aBase == NULL) 1690 return E_POINTER; 1839 CheckComArgOutPointerValid(aBase); 1691 1840 1692 1841 /* base() will do callers/locking */ … … 1699 1848 STDMETHODIMP Medium::COMGETTER(ReadOnly)(BOOL *aReadOnly) 1700 1849 { 1701 if (aReadOnly == NULL) 1702 return E_POINTER; 1850 CheckComArgOutPointerValid(aReadOnly); 1703 1851 1704 1852 AutoCaller autoCaller(this); … … 1797 1945 STDMETHODIMP Medium::COMGETTER(MachineIds)(ComSafeArrayOut(BSTR,aMachineIds)) 1798 1946 { 1799 if (ComSafeGUIDArrayOutIsNull(aMachineIds)) 1800 return E_POINTER; 1947 CheckComArgOutSafeArrayPointerValid(aMachineIds); 1801 1948 1802 1949 AutoCaller autoCaller(this); … … 2313 2460 ComObjPtr <Progress> progress; 2314 2461 progress.createObject(); 2315 /// @todo include fixed/dynamic2316 2462 HRESULT rc = progress->init(m->pVirtualBox, 2317 2463 static_cast<IMedium*>(this), … … 2322 2468 if (FAILED(rc)) return rc; 2323 2469 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); 2334 2477 if (FAILED(rc)) return rc; 2335 2478 2336 2479 /* go to Creating state on success */ 2337 2480 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);2344 2481 2345 2482 return S_OK; … … 2396 2533 HRESULT rc2 = UnlockRead(NULL); 2397 2534 AssertComRC(rc2); 2398 /* Note: on success, t askThread()will unlock this */2535 /* Note: on success, the task will unlock this */ 2399 2536 } 2400 2537 else … … 2450 2587 2451 2588 /* 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()); 2453 2590 2454 2591 for (Medium *hd = this; … … 2456 2593 hd = hd->m->pParent) 2457 2594 { 2458 rc = s rcChain->addImage(hd);2595 rc = sourceChain->addImage(hd); 2459 2596 if (FAILED(rc)) throw rc; 2460 2597 } 2461 rc = s rcChain->lockImagesRead();2598 rc = sourceChain->lockImagesRead(); 2462 2599 if (FAILED(rc)) throw rc; 2463 2600 2464 2601 /* Build the parent chain and lock images in the proper order. */ 2465 std::auto_ptr 2602 std::auto_ptr<ImageChain> parentChain(new ImageChain()); 2466 2603 2467 2604 for (Medium *hd = parent; … … 2494 2631 if (FAILED(rc)) throw rc; 2495 2632 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); 2507 2642 if (FAILED(rc)) throw rc; 2508 2643 … … 2512 2647 target->m->state = MediumState_Creating; 2513 2648 } 2514 2515 /* task is now owned (or already deleted) by taskThread() so release it */2516 task.release();2517 2649 } 2518 2650 catch (HRESULT aRC) … … 2548 2680 2549 2681 /* Build the image chain and lock images in the proper order. */ 2550 std::auto_ptr 2682 std::auto_ptr<ImageChain> imgChain(new ImageChain()); 2551 2683 2552 2684 /* we walk the image tree */ … … 2569 2701 if (FAILED(rc)) throw rc; 2570 2702 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); 2580 2709 if (FAILED(rc)) throw rc; 2581 2582 /* task is now owned (or already deleted) by taskThread() so release it */2583 task.release();2584 2710 } 2585 2711 catch (HRESULT aRC) … … 2645 2771 if (FAILED(rc)) throw rc; 2646 2772 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); 2653 2778 if (FAILED(rc)) throw rc; 2654 2655 /* task is now owned (or already deleted) by taskThread() so release it */2656 task.release();2657 2779 } 2658 2780 catch (HRESULT aRC) … … 2665 2787 HRESULT rc2 = UnlockWrite(NULL); 2666 2788 AssertComRC(rc2); 2667 /* Note: on success, t askThread()will unlock this */2789 /* Note: on success, the task will unlock this */ 2668 2790 } 2669 2791 else … … 3953 4075 3954 4076 /// @todo NEWMEDIA what to do if the parent is not 3955 /// accessible while the diff is? Probably ,nothing. The4077 /// accessible while the diff is? Probably nothing. The 3956 4078 /// real code will detect the mismatch anyway. 3957 4079 } … … 4208 4330 } 4209 4331 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()); 4212 4335 4213 4336 if (aWait) … … 4216 4339 m->state = MediumState_Deleting; 4217 4340 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() 4219 4342 } 4220 4343 else 4221 4344 { 4222 rc = task->startThread();4345 rc = startThread(task); 4223 4346 if (FAILED(rc)) return rc; 4224 4347 … … 4227 4350 } 4228 4351 4229 /* task is now owned (or already deleted) by taskThread() so release it */4230 task.release();4231 4232 4352 if (aProgress != NULL) 4233 4353 { … … 4245 4365 * As opposed to the CreateDiffStorage() method, this method doesn't try to lock 4246 4366 * this hard disk for reading assuming that the caller has already done so. This 4247 * is used when taking an online sna opshot (where all original hard disks are4367 * is used when taking an online snapshot (where all original hard disks are 4248 4368 * locked for writing and must remain such). Note however that if @a aWait is 4249 4369 * @c false and this method returns a success then the thread started by … … 4350 4470 } 4351 4471 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()); 4360 4476 4361 4477 /* register a task (it will deregister itself when done) */ … … 4373 4489 alock.release(); 4374 4490 4375 rc = task->runNow(pfNeedsSaveSettings);4491 rc = runNow(task, pfNeedsSaveSettings); 4376 4492 } 4377 4493 else 4378 4494 { 4379 rc = task->startThread();4495 rc = startThread(task); 4380 4496 if (FAILED(rc)) return rc; 4381 4497 … … 4383 4499 aTarget->m->state = MediumState_Creating; 4384 4500 } 4385 4386 /* task is now owned (or already deleted) by taskThread() so release it */4387 task.release();4388 4501 4389 4502 if (aProgress != NULL) … … 4470 4583 4471 4584 /* build the chain (will do necessary checks and state changes) */ 4472 std::auto_ptr 4473 4585 std::auto_ptr<MergeChain> chain(new MergeChain(forward, 4586 aIgnoreAttachments)); 4474 4587 { 4475 4588 Medium *last = forward ? aTarget : this; … … 4608 4721 } 4609 4722 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()); 4617 4726 4618 4727 /* Note: task owns aChain (will delete it when not needed) in all cases … … 4623 4732 if (aWait) 4624 4733 { 4625 rc = task->runNow(pfNeedsSaveSettings);4734 rc = runNow(task, pfNeedsSaveSettings); 4626 4735 } 4627 4736 else 4628 4737 { 4629 rc = task->startThread();4738 rc = startThread(task); 4630 4739 if (FAILED(rc)) return rc; 4631 4740 } 4632 4633 /* task is now owned (or already deleted) by taskThread() so release it */4634 task.release();4635 4741 4636 4742 if (aProgress != NULL) … … 4848 4954 } 4849 4955 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 percent4864 * 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 else4871 return VERR_INVALID_STATE;4872 }4873 }4874 4875 return VINF_SUCCESS;4876 }4877 4878 4956 /* static */ 4879 4957 DECLCALLBACK(bool) Medium::vdConfigAreKeysValid(void *pvUser, … … 4939 5017 4940 5018 /** 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 */ 5030 HRESULT 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 */ 5060 HRESULT 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. 4942 5071 * 4943 5072 * This only gets started from Medium::CreateBaseStorage() and always runs 4944 * asynchronously. As a result, we always save the VirtualBox.xml file when we're4945 * done here.5073 * asynchronously. As a result, we always save the VirtualBox.xml file when 5074 * we're done here. 4946 5075 * 4947 5076 * @param task 4948 * @param pvdOperationIfaces4949 5077 * @return 4950 5078 */ 4951 HRESULT Medium::taskThreadCreateBase( Task &task, void *pvdOperationIfaces)5079 HRESULT Medium::taskThreadCreateBase(CreateBaseTask &task) 4952 5080 { 4953 5081 HRESULT rc = S_OK; 4954 4955 PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;4956 5082 4957 5083 /* these parameters we need after creation */ … … 4999 5125 format.c_str(), 5000 5126 location.c_str(), 5001 task. d.size * _1M,5002 task. d.variant,5127 task.mSize * _1M, 5128 task.mVariant, 5003 5129 NULL, 5004 5130 &geo, … … 5007 5133 VD_OPEN_FLAGS_NORMAL, 5008 5134 NULL, 5009 vdOperationIfaces);5135 task.mVDOperationIfaces); 5010 5136 if (RT_FAILURE(vrc)) 5011 5137 { … … 5065 5191 5066 5192 /** 5067 * Implementation code called from Medium::taskThreadfor the "create diff" task.5193 * Implementation code for the "create diff" task. 5068 5194 * 5069 5195 * This task always gets started from Medium::createDiffStorage() and can run 5070 * synchronously or asynchrously depending on the "wait" parameter passed to that5071 * function. If we run synchronously, the caller expects the bool *pfNeedsSaveSettings5072 * to be set before returning; otherwise (in asynchronous mode), we save the settings5073 * 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. 5074 5200 * 5075 5201 * @param task 5076 * @param pvdOperationIfaces5077 5202 * @return 5078 5203 */ 5079 HRESULT Medium::taskThreadCreateDiff( Task &task, void *pvdOperationIfaces, bool fIsAsync)5204 HRESULT Medium::taskThreadCreateDiff(CreateDiffTask &task) 5080 5205 { 5081 5206 HRESULT rc = S_OK; 5082 5207 5083 PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;5084 5085 5208 bool fNeedsSaveSettings = false; 5086 5209 5087 ComObjPtr<Medium> &pTarget = task.d.target;5210 const ComObjPtr<Medium> &pTarget = task.mTarget; 5088 5211 5089 5212 uint64_t size = 0, logicalSize = 0; … … 5146 5269 if (FAILED(rc)) throw rc; 5147 5270 5148 /** @todo add VD_IMAGE_FLAGS_DIFF to the image flags, to5149 * be on the safe side. */5150 5271 vrc = VDCreateDiff(hdd, 5151 5272 targetFormat.c_str(), 5152 5273 targetLocation.c_str(), 5153 task. d.variant,5274 task.mVariant | VD_IMAGE_FLAGS_DIFF, 5154 5275 NULL, 5155 5276 targetId.raw(), … … 5157 5278 VD_OPEN_FLAGS_NORMAL, 5158 5279 pTarget->m->vdDiskIfaces, 5159 vdOperationIfaces);5280 task.mVDOperationIfaces); 5160 5281 if (RT_FAILURE(vrc)) 5161 5282 throw setError(E_FAIL, … … 5220 5341 } 5221 5342 5222 if ( fIsAsync)5343 if (task.isAsync()) 5223 5344 { 5224 5345 /* unlock ourselves when done (unless in MediumState_LockedWrite … … 5253 5374 5254 5375 /** 5255 * Implementation code called from Medium::taskThreadfor the "merge" task.5376 * Implementation code for the "merge" task. 5256 5377 * 5257 5378 * This task always gets started from Medium::mergeTo() and can run 5258 * synchronously or asynchrously depending on the "wait" parameter passed to that5259 * function. If we run synchronously, the caller expects the bool *pfNeedsSaveSettings5260 * to be set before returning; otherwise (in asynchronous mode), we save the settings5261 * 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. 5262 5383 * 5263 5384 * @param task 5264 * @param pvdOperationIfaces5265 5385 * @return 5266 5386 */ 5267 HRESULT Medium::taskThreadMerge( Task &task, void *pvdOperationIfaces, bool fIsAsync)5387 HRESULT Medium::taskThreadMerge(MergeTask &task) 5268 5388 { 5269 5389 HRESULT rc = S_OK; 5270 5271 PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;5272 5390 5273 5391 /* The lock is also used as a signal from the task initiator (which … … 5280 5398 } 5281 5399 5282 MergeChain *chain = task. d.chain.get();5400 MergeChain *chain = task.mMergeChain.get(); 5283 5401 5284 5402 try … … 5340 5458 } 5341 5459 5342 vrc = VDMerge(hdd, chain->sourceIdx(), chain->targetIdx(), vdOperationIfaces); 5460 vrc = VDMerge(hdd, chain->sourceIdx(), chain->targetIdx(), 5461 task.mVDOperationIfaces); 5343 5462 if (RT_FAILURE(vrc)) 5344 5463 throw vrc; 5345 5464 5346 5465 /* update parent UUIDs */ 5347 /// @todo VDMerge should handle the5348 /// multiple children case5349 5466 if (!chain->isForward()) 5350 5467 { … … 5486 5603 * the caller's responsibility) */ 5487 5604 if (*it == this) 5488 task.m _autoCaller.release();5605 task.mMediumCaller.release(); 5489 5606 5490 5607 /* release the caller added by MergeChain before uninit() */ 5491 5608 (*it)->releaseCaller(); 5492 5609 5493 if ( fIsAsync|| *it != this)5610 if (task.isAsync() || *it != this) 5494 5611 (*it)->uninit(); 5495 5612 5496 5613 /* delete (to prevent uninitialization in MergeChain 5497 5614 * dtor) and advance to the next item */ 5498 5615 it = chain->erase(it); 5499 5616 } 5500 5617 } 5501 5618 5502 if ( fIsAsync)5619 if (task.isAsync()) 5503 5620 { 5504 5621 // in asynchronous mode, save settings now … … 5524 5641 * don't own the merge chain, so release it in this case. */ 5525 5642 5526 if (! fIsAsync)5527 task. d.chain.release();5643 if (!task.isAsync()) 5644 task.mMergeChain.release(); 5528 5645 } 5529 5646 … … 5532 5649 5533 5650 /** 5534 * Implementation code called from Medium::taskThread for the "clone" task. 5651 * Implementation code for the "clone" task. 5652 * 5535 5653 * This only gets started from Medium::CloneTo() and always runs asynchronously. 5536 5654 * As a result, we always save the VirtualBox.xml file when we're done here. 5537 5655 * 5538 5656 * @param task 5539 * @param pvdOperationIfaces5540 5657 * @return 5541 5658 */ 5542 HRESULT Medium::taskThreadClone( Task &task, void *pvdOperationIfaces)5659 HRESULT Medium::taskThreadClone(CloneTask &task) 5543 5660 { 5544 5661 HRESULT rc = S_OK; 5545 5662 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; 5550 5665 5551 5666 bool fCreatingTarget = false; … … 5563 5678 fCreatingTarget = pTarget->m->state == MediumState_Creating; 5564 5679 5565 ImageChain *s rcChain = task.d.source.get();5566 ImageChain *parentChain = task. d.parent.get();5680 ImageChain *sourceChain = task.mSourceChain.get(); 5681 ImageChain *parentChain = task.mParentChain.get(); 5567 5682 5568 5683 /* The object may request a specific UUID (through a special form of … … 5584 5699 { 5585 5700 /* Open all hard disk images in the source chain. */ 5586 for (MediaList::const_iterator it = s rcChain->begin();5587 it != s rcChain->end();5701 for (MediaList::const_iterator it = sourceChain->begin(); 5702 it != sourceChain->end(); 5588 5703 ++it) 5589 5704 { … … 5657 5772 false, 5658 5773 0, 5659 task. d.variant,5774 task.mVariant, 5660 5775 targetId.raw(), 5661 5776 NULL, 5662 5777 pTarget->m->vdDiskIfaces, 5663 vdOperationIfaces);5778 task.mVDOperationIfaces); 5664 5779 if (RT_FAILURE(vrc)) 5665 5780 throw setError(E_FAIL, … … 5745 5860 * that we get a deadlock in Appliance::Import when Medium::Close 5746 5861 * is called & the source chain is released at the same time. */ 5747 task. d.source.reset();5862 task.mSourceChain.reset(); 5748 5863 5749 5864 return rc; … … 5751 5866 5752 5867 /** 5753 * Implementation code called from Medium::taskThreadfor the "delete" task.5868 * Implementation code for the "delete" task. 5754 5869 * 5755 5870 * 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 5759 5875 * @return 5760 5876 */ 5761 HRESULT Medium::taskThreadDelete( )5877 HRESULT Medium::taskThreadDelete(DeleteTask &task) 5762 5878 { 5763 5879 HRESULT rc = S_OK; … … 5817 5933 5818 5934 /** 5819 * Implementation code called from Medium::taskThreadfor the "reset" task.5935 * Implementation code for the "reset" task. 5820 5936 * 5821 5937 * This always gets started asynchronously from Medium::Reset(). 5822 5938 * 5823 5939 * @param task 5824 * @param pvdOperationIfaces5825 5940 * @return 5826 5941 */ 5827 HRESULT Medium::taskThreadReset( void *pvdOperationIfaces, bool fIsAsync)5942 HRESULT Medium::taskThreadReset(ResetTask &task) 5828 5943 { 5829 5944 HRESULT rc = S_OK; 5830 5831 PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;5832 5945 5833 5946 uint64_t size = 0, logicalSize = 0; … … 5898 6011 VD_OPEN_FLAGS_NORMAL, 5899 6012 m->vdDiskIfaces, 5900 vdOperationIfaces);6013 task.mVDOperationIfaces); 5901 6014 if (RT_FAILURE(vrc)) 5902 6015 throw setError(E_FAIL, … … 5918 6031 m->logicalSize = logicalSize; 5919 6032 5920 if ( fIsAsync)6033 if (task.isAsync()) 5921 6034 { 5922 6035 /* unlock ourselves when done */ … … 5932 6045 5933 6046 /** 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 5936 6050 * @return 5937 6051 */ 5938 HRESULT Medium::taskThreadCompact( Task &task, void *pvdOperationIfaces)6052 HRESULT Medium::taskThreadCompact(CompactTask &task) 5939 6053 { 5940 6054 HRESULT rc = S_OK; 5941 5942 PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces;5943 6055 5944 6056 /* Lock all in {parent,child} order. The lock is also used as a … … 5947 6059 AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS); 5948 6060 5949 ImageChain *imgChain = task. d.images.get();6061 ImageChain *imgChain = task.mImageChain.get(); 5950 6062 5951 6063 try … … 5990 6102 thisLock.leave(); 5991 6103 5992 vrc = VDCompact(hdd, VD_LAST_IMAGE, vdOperationIfaces);6104 vrc = VDCompact(hdd, VD_LAST_IMAGE, task.mVDOperationIfaces); 5993 6105 if (RT_FAILURE(vrc)) 5994 6106 { … … 6020 6132 } 6021 6133 6022 6023 /**6024 * Thread function for time-consuming tasks.6025 *6026 * The Task structure passed to @a pvUser must be allocated using new and will6027 * 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 (for6042 * 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 else6107 {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... later6117 #undef setError6118 }6119 6120 6134 /* vi: set tabstop=4 shiftwidth=4 expandtab: */ -
trunk/src/VBox/Main/include/MediumImpl.h
r27232 r27803 294 294 const char *pszFormat, va_list va); 295 295 296 static DECLCALLBACK(int) vdProgressCall(void *pvUser, unsigned uPercent);297 298 296 static DECLCALLBACK(bool) vdConfigAreKeysValid(void *pvUser, 299 297 const char *pszzValid); … … 303 301 char *pszValue, size_t cchValue); 304 302 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); 317 330 318 331 struct Data; // opaque data struct, defined in MediumImpl.cpp
Note:
See TracChangeset
for help on using the changeset viewer.