You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
5.5 KiB
173 lines
5.5 KiB
// This is a part of the Active Template Library.
|
|
// Copyright (C) 1995-1999 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Active Template Library Reference and related
|
|
// electronic documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Active Template Library product.
|
|
|
|
// VCUE_Collection.h
|
|
//
|
|
// This header contains code that simplifies or enhances use of ATL's collection
|
|
// and enumerator classes, ICollectionOnSTLImpl, IEnumOnSTLImpl, CComEnumOnSTL, CComEnumImpl, and CComEnum
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#if !defined(_COLLECTION_H___36A49828_B15B_11D2_BA63_00C04F8EC847___INCLUDED_)
|
|
#define _COLLECTION_H___36A49828_B15B_11D2_BA63_00C04F8EC847___INCLUDED_
|
|
|
|
#if _MSC_VER >= 1000
|
|
#pragma once
|
|
#endif // _MSC_VER >= 1000
|
|
|
|
#include <AtlCom.h>
|
|
|
|
namespace VCUE
|
|
{
|
|
|
|
// CGenericDataHolder is a class that stores data
|
|
// The lifetime of objects of this class is managed via the IUnknown interface
|
|
// which makes objects of this class suitable as a source of shared data
|
|
// Clients that need access to the data can keep a CGenericDataHolder object alive
|
|
// just by holding a COM reference on that object
|
|
|
|
// This class is used (by default) by ICollectionOnSTLCopyImpl::get__NewEnum to provide data
|
|
// to be shared between an enumerator and its clones.
|
|
|
|
template < class DataType, class ThreadModel = CComObjectThreadModel >
|
|
class ATL_NO_VTABLE CGenericDataHolder :
|
|
public IUnknown,
|
|
public CComObjectRootEx< ThreadModel >
|
|
{
|
|
public:
|
|
typedef CGenericDataHolder< DataType, ThreadModel > thisClass;
|
|
|
|
BEGIN_COM_MAP(thisClass)
|
|
COM_INTERFACE_ENTRY(IUnknown)
|
|
END_COM_MAP()
|
|
|
|
template < class SourceType >
|
|
HRESULT Copy(const SourceType& c)
|
|
{
|
|
m_Data = c;
|
|
return S_OK;
|
|
|
|
} // HRESULT Copy(const SourceType& c)
|
|
|
|
DataType m_Data;
|
|
|
|
}; // class ATL_NO_VTABLE CGenericDataHolder
|
|
|
|
// CreateSTLEnumerator wraps the necessary creation, initialization
|
|
// and error handling code for the the creation of a CComEnumOnSTL-style enumerator
|
|
|
|
// *** EXAMPLE : Using CreateSTLEnumerator to implement get__NewEnum ***
|
|
// typedef CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT,
|
|
// _Copy<VARIANT>, std::vector<CComVariant> > VarVarEnum;
|
|
// std::vector<CComVariant> m_vec;
|
|
// STDMETHOD(get__NewEnum)(IUnknown** ppUnk)
|
|
// {
|
|
// return CreateSTLEnumerator<VarVarEnum>(ppUnk, this, m_vec);
|
|
// }
|
|
|
|
template <class EnumType, class CollType>
|
|
HRESULT CreateSTLEnumerator(IUnknown** ppUnk, IUnknown* pUnkForRelease, CollType& collection)
|
|
{
|
|
if (ppUnk == NULL)
|
|
return E_POINTER;
|
|
*ppUnk = NULL;
|
|
|
|
CComObject<EnumType>* pEnum = NULL;
|
|
HRESULT hr = CComObject<EnumType>::CreateInstance(&pEnum);
|
|
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = pEnum->Init(pUnkForRelease, collection);
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = pEnum->QueryInterface(ppUnk);
|
|
|
|
if (FAILED(hr))
|
|
delete pEnum;
|
|
|
|
return hr;
|
|
|
|
} // HRESULT CreateSTLEnumerator(IUnknown** ppUnk, IUnknown* pUnkForRelease, CollType& collection)
|
|
|
|
// CreateEnumerator wraps the necessary creation, initialization
|
|
// and error handling code for the the creation of a CComEnum-style enumerator
|
|
|
|
template <class EnumType, class ElementType>
|
|
HRESULT CreateEnumerator(IUnknown** ppUnk,
|
|
ElementType* begin, ElementType* end,
|
|
IUnknown* pUnk,
|
|
CComEnumFlags flags)
|
|
{
|
|
if (ppUnk == NULL)
|
|
return E_POINTER;
|
|
*ppUnk = NULL;
|
|
|
|
CComObject<EnumType>* pEnum = NULL;
|
|
HRESULT hr = CComObject<EnumType>::CreateInstance(&pEnum);
|
|
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = pEnum->Init(begin, end, pUnk, flags);
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = pEnum->QueryInterface(ppUnk);
|
|
|
|
if (FAILED(hr))
|
|
delete pEnum;
|
|
|
|
return hr;
|
|
|
|
} // CreateEnumerator
|
|
|
|
|
|
// ICollectionOnSTLCopyImpl derives from ICollectionOnSTLImpl and overrides get__NewEnum
|
|
// The new implementation provides each enumerator with its own copy of the collection data.
|
|
// (Note that this only applies to enumerators returned directly by get__NewEnum.
|
|
// Cloned enumerators use their parent's data as before.
|
|
// This is OK because the enumerator never changes the data)
|
|
|
|
// Use this class when:
|
|
// The collection can change while there are outstanding enumerators
|
|
// And You don't want to invalidate those enumerators when that happens
|
|
// And You are sure that the performance hit is worth it
|
|
// And You are sure that the way items are copied between containers works correctly
|
|
// (You can adjust this by passing a different class as the Holder parameter)
|
|
|
|
// Mostly you can use this class in exactly the same
|
|
// way that you would use ICollectionOnSTLImpl.
|
|
|
|
template <class T, class CollType, class ItemType, class CopyItem, class EnumType, class Holder = CGenericDataHolder< CollType > >
|
|
class ICollectionOnSTLCopyImpl :
|
|
public ICollectionOnSTLImpl<T, CollType, ItemType, CopyItem, EnumType>
|
|
{
|
|
public :
|
|
STDMETHOD(get__NewEnum)(IUnknown** ppUnk)
|
|
{
|
|
typedef CComObject< Holder > HolderObject;
|
|
HolderObject* p = NULL;
|
|
HRESULT hr = HolderObject::CreateInstance(&p);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = p->Copy(m_coll);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
return CreateSTLEnumerator<EnumType>(ppUnk, p, p->m_Data);
|
|
|
|
} // STDMETHOD(get__NewEnum)(IUnknown** ppUnk)
|
|
|
|
}; // class ICollectionOnSTLCopyImpl
|
|
|
|
}; // namespace VCUE
|
|
|
|
#endif // !defined(_COLLECTION_H___36A49828_B15B_11D2_BA63_00C04F8EC847___INCLUDED_)
|