March 22nd, 2004

Why an object cannot be its own enumerator

I’ve seen people using the following cheat when forced to implement an enumerator:

class MyClass :
  public IDataObject, public IEnumFORMATETC, ...
{
  ...
  HRESULT EnumFormatEtc(DWORD dwDirection,
                 IEnumFORMATETC** ppenumOut)
  {
    _dwDirection = dwDirection;
    Reset();
    *ppenumOut = this;
    AddRef();
    return S_OK;
  }
};

Why create a separate enumerator object when you can just be your own enumerator? It’s so much easier.

And it’s wrong.

Consider what happens if two people try to enumerate your formats at the same time: The two enumerators are really the same enumerator, so operations on one will interfere with the other. For example, consider this odd code fragment (error checking deleted for expository purposes) which looks to see if the data object exposes the same data under multiple aspects:

IDataObject *pdto = <MyClass instance>;
// Obtain two enumerators since we will run
// each one independently.
IEnumFORMATETC* penum1;
IEnumFORMATETC* penum2;
pdto->EnumFormatEtc(DATADIR_GET, &penum1);
pdto->EnumFormatEtc(DATADIR_GET, &penum2);
FORMATETC fe1, fe2;
while (penum1->Next(1, &fe1, NULL) == S_OK) {
  penum2->Reset(); // start a new pass
  while (penum2->Next(1, &fe2, NULL) == S_OK) {
    if (fe1.cfFormat == fe2.cfFormat &&
        cf1.dwAspect != cf2.dwAspect) {
        // found it!
    }
  }
}
penum1->Release();
penum2->Release();

When the code does a penum2->Reset(), this also inadvertently resets the first enumerator. The loop runs through penum2 (which therefore also runs through penum1), and when it’s done, the enumerator is left at the end of the list.

Then we loop back and call penum1->Next(), which immediately returns failure since the inner loop ran it to completion.

Result: The loop fails to find anything because the second enumerator corrupted the first.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

0 comments

Discussion are closed.