Changeset 22228 in vbox
- Timestamp:
- Aug 13, 2009 10:26:00 AM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 51030
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/MachineImpl.cpp
r22199 r22228 2645 2645 CheckComArgNotNull(aKey); 2646 2646 2647 AutoCaller autoCaller 2647 AutoCaller autoCaller(this); 2648 2648 CheckComRCReturnRC (autoCaller.rc()); 2649 2649 2650 Bstr val;2651 if (!aValue)2652 val = (const char *)"";2653 else2654 val = aValue;2655 2656 2650 Utf8Str strKey(aKey); 2657 Bstr oldVal(""); 2658 2659 /* VirtualBox::onExtraDataCanChange() and saveSettings() need mParent 2660 * lock (saveSettings() needs a write one). This object's write lock is 2661 * also necessary to serialize file access (prevent concurrent reads and 2662 * writes). */ 2663 AutoMultiWriteLock2 alock(mParent, this); 2664 2665 if (mType == IsSnapshotMachine) 2666 { 2667 HRESULT rc = checkStateDependency(MutableStateDep); 2668 CheckComRCReturnRC (rc); 2669 } 2670 2671 settings::ExtraDataItemsMap::const_iterator it = mData->m_pMachineConfigFile->mapExtraDataItems.find(strKey); 2672 if (it != mData->m_pMachineConfigFile->mapExtraDataItems.end()) 2673 { 2674 // key exists: 2675 const Utf8Str &strValue = it->second; 2676 oldVal = strValue; 2677 } 2678 2679 bool fChanged = (oldVal != val); 2680 if (fChanged) 2681 { 2682 /* ask for permission from all listeners */ 2651 Utf8Str strValue(aValue); 2652 Utf8Str strOldValue; // empty 2653 2654 // locking note: we only hold the read lock briefly to look up the old value, 2655 // then release it and call the onExtraCanChange callbacks. There is a small 2656 // chance of a race insofar as the callback might be called twice if two callers 2657 // change the same key at the same time, but that's a much better solution 2658 // than the deadlock we had here before. The actual changing of the extradata 2659 // is then performed under the write lock and race-free. 2660 2661 // look up the old value first; if nothing's changed then we need not do anything 2662 { 2663 AutoReadLock alock(this); // hold read lock only while looking up 2664 settings::ExtraDataItemsMap::const_iterator it = mData->m_pMachineConfigFile->mapExtraDataItems.find(strKey); 2665 if (it != mData->m_pMachineConfigFile->mapExtraDataItems.end()) 2666 strOldValue = it->second; 2667 } 2668 2669 bool fChanged; 2670 if (fChanged = (strOldValue != strValue)) 2671 { 2672 // ask for permission from all listeners outside the locks; 2673 // onExtraDataCanChange() only briefly requests the VirtualBox 2674 // lock to copy the list of callbacks to invoke 2683 2675 Bstr error; 2684 if (!mParent->onExtraDataCanChange(mData->mUuid, aKey, val, error)) 2676 Bstr bstrValue; 2677 if (aValue) 2678 bstrValue = aValue; 2679 else 2680 bstrValue = (const char *)""; 2681 2682 if (!mParent->onExtraDataCanChange(mData->mUuid, aKey, bstrValue, error)) 2685 2683 { 2686 2684 const char *sep = error.isEmpty() ? "" : ": "; … … 2691 2689 tr("Could not set extra data because someone refused the requested change of '%ls' to '%ls'%s%ls"), 2692 2690 aKey, 2693 val.raw(),2691 bstrValue.raw(), 2694 2692 sep, 2695 2693 err); 2696 2694 } 2697 2695 2698 mData->m_pMachineConfigFile->mapExtraDataItems[strKey] = val; 2696 // data is changing and change not vetoed: then write it out under the locks 2697 2698 /* VirtualBox::onExtraDataCanChange() and saveSettings() need mParent 2699 * lock (saveSettings() needs a write one). This object's write lock is 2700 * also necessary to serialize file access (prevent concurrent reads and 2701 * writes). */ 2702 AutoMultiWriteLock2 alock(mParent, this); 2703 2704 if (mType == IsSnapshotMachine) 2705 { 2706 HRESULT rc = checkStateDependency(MutableStateDep); 2707 CheckComRCReturnRC (rc); 2708 } 2709 2710 mData->m_pMachineConfigFile->mapExtraDataItems[strKey] = strValue; 2711 // creates a new key if needed 2699 2712 2700 2713 /* save settings on success */ … … 2703 2716 } 2704 2717 2705 / * fire a notification */2718 // fire notification outside the lock 2706 2719 if (fChanged) 2707 2720 mParent->onExtraDataChange(mData->mUuid, aKey, aValue); -
trunk/src/VBox/Main/VirtualBoxImpl.cpp
r22209 r22228 1511 1511 CheckComRCReturnRC(autoCaller.rc()); 1512 1512 1513 Guid emptyGuid;1514 Bstr val;1515 if (!aValue)1516 val = (const char *)"";1517 else1518 val = aValue;1519 1520 1513 Utf8Str strKey(aKey); 1521 Bstr oldVal(""); 1522 1523 /* serialize file access (prevent concurrent reads and writes) */ 1524 AutoWriteLock alock(this); 1525 1526 settings::ExtraDataItemsMap::const_iterator it = m_pMainConfigFile->mapExtraDataItems.find(strKey); 1527 if (it != m_pMainConfigFile->mapExtraDataItems.end()) 1528 { 1529 // key exists: 1530 const Utf8Str &strValue = it->second; 1531 oldVal = strValue; 1532 } 1533 1534 bool fChanged = (oldVal != val); 1535 if (fChanged) 1536 { 1537 /* ask for permission from all listeners */ 1514 Utf8Str strValue(aValue); 1515 Utf8Str strOldValue; // empty 1516 1517 // locking note: we only hold the read lock briefly to look up the old value, 1518 // then release it and call the onExtraCanChange callbacks. There is a small 1519 // chance of a race insofar as the callback might be called twice if two callers 1520 // change the same key at the same time, but that's a much better solution 1521 // than the deadlock we had here before. The actual changing of the extradata 1522 // is then performed under the write lock and race-free. 1523 1524 // look up the old value first; if nothing's changed then we need not do anything 1525 { 1526 AutoReadLock alock(this); // hold read lock only while looking up 1527 settings::ExtraDataItemsMap::const_iterator it = m_pMainConfigFile->mapExtraDataItems.find(strKey); 1528 if (it != m_pMainConfigFile->mapExtraDataItems.end()) 1529 strOldValue = it->second; 1530 } 1531 1532 bool fChanged; 1533 if (fChanged = (strOldValue != strValue)) 1534 { 1535 // ask for permission from all listeners outside the locks; 1536 // onExtraDataCanChange() only briefly requests the VirtualBox 1537 // lock to copy the list of callbacks to invoke 1538 1538 Bstr error; 1539 if (!onExtraDataCanChange(Guid::Empty, aKey, val, error)) 1539 Bstr bstrValue; 1540 if (aValue) 1541 bstrValue = aValue; 1542 else 1543 bstrValue = (const char *)""; 1544 1545 if (!onExtraDataCanChange(Guid::Empty, aKey, bstrValue, error)) 1540 1546 { 1541 1547 const char *sep = error.isEmpty() ? "" : ": "; … … 1546 1552 tr("Could not set extra data because someone refused the requested change of '%ls' to '%ls'%s%ls"), 1547 1553 aKey, 1548 val.raw(),1554 bstrValue.raw(), 1549 1555 sep, 1550 1556 err); 1551 1557 } 1552 1558 1553 m_pMainConfigFile->mapExtraDataItems[strKey] = val; 1559 // data is changing and change not vetoed: then write it out under the lock 1560 1561 AutoWriteLock alock(this); 1562 1563 m_pMainConfigFile->mapExtraDataItems[strKey] = strValue; 1564 // creates a new key if needed 1554 1565 1555 1566 /* save settings on success */ … … 1558 1569 } 1559 1570 1560 / * fire a notification */1571 // fire notification outside the lock 1561 1572 if (fChanged) 1562 1573 onExtraDataChange(Guid::Empty, aKey, aValue);
Note:
See TracChangeset
for help on using the changeset viewer.