// ask data producer to send CHUNKSIZE elements
// просим источник данных послать CHUNKSIZE элементов
ULONG cFetched;
hr = ped->Next(CHUNKSIZE, rgd, &cFetched);
// adjust cFetched to address sloppy objects
// настраиваем cFetched на исправление некорректных объектов
if (hr == S_OK) cFetched = CHUNKSIZE;
if (SUCCEEDED(hr))
// S_OK or S_FALSE
// S_OK или S_FALSE
// consume/use received elements
// потребляем/используем полученные элементы
for (ULONG n = О; п < cFetched; n++) *psum += rgd[n];
}
while (hr == S_OK);
// S_FALSE or error terminates
// завершается по S_FALSE или по ошибке
}
Отметим, что подпрограмма
Одно из преимуществ использования идиомы
Разработчик объекта может создать специальный класс, который генерирует по требованию простые числа и реализует интерфейс
class PrimeGenerator : public IEnumLong {
LONG m_cRef;
// СОМ reference count
// счетчик ссылок СОМ
long m_nCurrentPrime;
// the cursor
// курсор long m_nMin;
// minimum prime value
// минимальное значение простого числа
long m_nMax;
// maximum prime value
// максимальное значение простого числа
public:
PrimeGenerator(long nMin, long nMax, long nCurrentPrime) : m_cRef(0), m_nMin(nMin), m_nMax(nMax),
m_nCurrentPrime(nCurrentPrime) { }
// IUnknown methods
// методы IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
STDHETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// IEnumLong methods
// методы IEnumLong
STDMETHODIMP Next(ULONG, long *, ULONG *);
STDMETHODIMP Skip(ULONG);
STDMETHODIMP Reset(void);
STDMETHODIMP Clone(IEnumLong **ppe);
};
Реализация генератора
STDMETHODIMP PrimeGenerator::Next(ULONG cElems, long *prgElems, ULONG *pcFetched) {
// ensure that pcFetched is valid if cElems > 1
// удостоверяемся, что pcFetched легален, если cElems больше единицы
if (cElems > 1 && pcFetched == 0) return E_INVALIDARG;
// fill the buffer
// заполняем буфер
ULONG cFetched = 0;
while (cFetched < cElems && m_nCurrentPrime <= m_nMax) {
prgElems[cFetched] = GetNextPrime(m_nCurrentPrime);
m_nCurrentPrime = prgElems[cFetchcd++];
} if (pcFetched)
// some callers may pass NULL
// некоторые вызывающие программы могут передавать NULL
*pcFetched = cFetched;
return cFetched == cElems ? S_OK : S_FALSE;
}
Отметим, что даже если имеются миллионы допустимых значений, одновременно в памяти будет находиться лишь малое их число.
Методу генератора
STDMETHODIMP PrimeGenerator::Skip(ULONG cElems) {
ULONG cEaten = 0; while (cEaten < cElems && m_nCurrentPrime <= m_nMax) {
m_nCurrentPrime = GetNextPrime(m_nCurrentPrime);
cEaten++; }
return cEaten == cElems ? S_OK : S_FALSE;
}
Метод
STDMETHODIMP PrimeGenerator::Reset(void) {
m_nCurrentPrime = m_nMin;
return S_OK;
}