RDT changes in VS Orcas

The Running Document Table is used in VS to control the state of opened documents.  This is only accessible via interfaces exposed in the VSSDK and the VS Automation Model.  End-users only see the effects of the RDT in places like the dialog that pops up asking the user if they'd like to save changes before closing the IDE. 

The underlying implementation in previous version of VS had some problems with reentrancy protection being inconsistent.  Additionally various entry points weren't very robust with error handling (some would crash, other return error results, etc).

One of the excellent developers in the Developer Tools Platform team responsible for the base VS platform took it upon himself to make a clean sweep through this area of the codebase and came up with a number of improvements.  He sent me a document with the changes that he thought the 3rd party community might be impacted by.  I wanted to share that information with you.

One important point to make here is that the interface methods of IVsRunningDocumentTable have not changed.  Binary compatibility is preserved so you don't have to worry about your code not compiling in Orcas.  If you don't use that interfaces in any way, then you don't have to worry about this at all.  But if you do use the RDT interfaces, then you need to check your code on how you interacted with the RDT to see if any of these changes affect your runtime behavior.

Here's a synopsis of an email thread that discusses the changes introduced in VS Orcas.  These changes were available in the Sept 2006 CTP of VS (and all susquent versions).

Thread affinity for the RDT has been tightened. With the exception of the following methods, all RDT interface methods must be called on the main thread, else RPC_E_WRONG_THREAD will be returned:

  • GetDocumentInfo
  • FindAndLockDocument (with RDT_NoLock)
  • FindAndLockDocumentEx (with RDT_NoLock, as long as the document exists and has a hierarchy/itemid)
  • FindOrRegisterAndLockDocument (with RDT_NoLock, as long as the document exists and has a hierarchy/itemid)
  • GetRunningDocumentsEnum
  • All methods on IEnumRunningDocuments.

This restriction was only inconsistently applied in previous versions.

The externally-visible change in behavior for the RDT will include, but is not limited to, the following:

· The RDT lock will be faithfully acquired on any call into the RDT . This is handled sloppilyin the RDT in previous versions, and more rigorous treatment of the RDT lock has the potential forintroducingdeadlock where none existed in previous versions.

· The RDT lock will not be held when calling out of the RDT. Thisalsohas the potential of causing deadlockwhere none existed in previous versions.

· Interfaces held by the RDT will be released (i.e. not leaked) for documents left in the RDTwhen it isdestroyed. This only happens on shutdown, so this should be a no-op for packages.

· IVsRunningDocumentTable::RegisterAndLockDocumentwillrequire an IVsHierarchywhen a document is registered with an edit lock. The documentation specifies this, but the code did not enforce it. There are several other code paths where this invariant can be violated as well. Increasing enforcement could be an issue for packages.

· IVsRunningDocumentTable::UnlockDocument willnotallow unlocking of a lockifa lock ofthe specifiedtype is not held. In previous versions you can UnlockDocument(RDT_EditLock) even though you never acquired an edit lock. Fixing thiscould be an issue for packages as well.

What is the new behavior if the call is made and the type of lock specified is not held? The following code illustrates the differences:

pRDT->RegisterAndLockDocument (RDT_EditLock, ..., &cookie);

pRDT->UnlockDocument (RDT_ReadLock, cookie);

pRDT->GetDocumentInfo (cookie, ..., &cReadLocks, &cEditLocks, ...);
pRDT->UnlockDocument (RDT_EditLock, cookie);

In previous versions, the Unlock(RDT_ReadLock) would return S_OK, the GetDocumentInfo would return cReadLocks=0xFFFFFFFF and cEditLocks=1. After the Unlock(RDT_EditLock), the document is still in the RDT (visible to enumerators, etc.).
In VS Orcas, the behavior will change so Unlock(RDT_ReadLock) will return failure, meaning GetDocumentInfo will correctly return cReadLocks=0 and cEditLocks=1. After the Unlock(RDT_EditLock), the document is no longer in the RDT, event sinks have gotten OnAfterLastUnlock, etc.

· IVsRunningDocumentTable::UnregisterDocumentLockHolder will AV with an invalid cookie. The fix would turn the AV into an E_INVALIDARG. This should present no issues for packages.

· Documents enumerated by IEnumRunningDocuments will be enumerated in a different order.There is no order expressed or implied by the interface definition, and the current order is based on the hash of the document name so it’s unlikely that the current behavior is stable enough for a package to have dependencies on it, butit’s theoretically possible.