Сущность технологии COM



         

Управление потоками данных - часть 4


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); };

Реализация генератора Next будет просто порождать запрошенное количество простых чисел:

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; }

Отметим, что даже если имеются миллионы допустимых значений, одновременно в памяти будет находиться лишь малое их число.

Методу генератора Skip нужно просто генерировать и отбрасывать запрошенное количество элементов:

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; }

Метод Reset устанавливает курсор на начальное значение:

STDMETHODIMP PrimeGenerator::Reset(void) { m_nCurrentPrime = m_nMin; return S_OK; }

а метод Clone создает новый генератор простых чисел на основе минимума, максимума и текущих значений, выданных существующим генератором:

STDMETHODIMP PrimeGenerator::Clone(IEnumLong **ppe) { assert(ppe); *рре = new PrimeGenerator(m_nMin, m_nMax, m_nCurrent); if (*ppe) (*ppe)->AddRef(); return S_OK; }

При наличии реализации PrimeGenerator реализация метода GetPrimes текущим объектом становится тривиальной:

STDMETHODIMP MyClass::GetPrimes(long пМin, long nMax, IEnumLong **ppe) { assert(ppe); *ppe = new PrimeGenerator (nMin, nMax, nMin); if (*ppe) (*ppe)->AddRef(); return S_OK; }

Большая часть этой реализации находится теперь в классе PrimeGenerator, а не в классе объекта.




Содержание  Назад  Вперед