|
|
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
#if !defined(AFX_STDAFX_H__B7E9C4D4_B8E5_48DE_A578_B75F8096FB42__INCLUDED_)
#define AFX_STDAFX_H__B7E9C4D4_B8E5_48DE_A578_B75F8096FB42__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define STRICT
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
#define _ATL_APARTMENT_THREADED
#if 0
#define _ATL_DEBUG_INTERFACES 1
#endif
#include <atlbase.h>
//You may derive a class from CComModule and use it if you want to override
//something, but do not change the name of _Module
extern CComModule _Module; #include <atlcom.h>
#include <comdef.h>
#import "msado21.tlb" rename("EOF", "EndOfFile") raw_method_prefix("") high_method_prefix("_")
#import "sqldmo.rll" raw_method_prefix("") high_method_prefix("_") rename("GetUserName", "_GetUserName")
#import "msadox.dll" raw_method_prefix("") high_method_prefix("_")
#include <icrsint.h>
#undef END_ADO_BINDING
#define END_ADO_BINDING() {0, ADODB::adEmpty, 0, 0, 0, 0, 0, 0, 0, FALSE}};\
return rgADOBindingEntries;} #include <oledb.h>
#include <map>
#include <list>
#include <vector>
using namespace std;
#define THIS_FILE __FILE__
#define sizeofarray(a) (sizeof(a)/sizeof((a)[0]))
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
class ILRUCache { public: virtual void Lock() = 0; virtual void Unlock() = 0; virtual void AddToCache(IUnknown *punk) = 0; virtual void RemoveFromCache(IUnknown *punk) = 0; };
class DECLSPEC_UUID("321ADAAD-5334-4227-8982-585A9A3F4C02") ILRUCachedObject : public IUnknown { public: virtual HRESULT put_Cache(ILRUCache *pcache) = 0; #if 0
virtual ULONG RefCount() = 0; #endif
};
template <class T> class CComObjectCachedLRU : public T, public ILRUCachedObject { public: CComObjectCachedLRU<T>() { m_pcache = NULL; }
// Set refcount to 1 to protect destruction
~CComObjectCachedLRU() { m_dwRef = 1L; FinalRelease(); #ifdef _ATL_DEBUG_INTERFACES
_Module.DeleteNonAddRefThunk(_GetRawUnknown()); #endif
} //If InternalAddRef or InternalRelease is undefined then your class
//doesn't derive from CComObjectRoot
STDMETHOD_(ULONG, AddRef)() { m_csCached.Lock(); ULONG l = InternalAddRef(); if (m_dwRef == 2) { _Module.Lock(); if (m_pcache != NULL) m_pcache->RemoveFromCache(GetControllingUnknown()); } m_csCached.Unlock(); return l; } STDMETHOD_(ULONG, Release)() { m_csCached.Lock(); InternalRelease(); ULONG l = m_dwRef; if (l > 1) { m_csCached.Unlock(); return l; }
if (l == 1) { if (m_pcache != NULL) { _Module.Unlock(); // Can't reference any member variables after call to AddToCache()
// because AddToCache() might Release() this object down to
// zero refs... that would cause the object to be deleted.
ILRUCache *pcache = m_pcache;
pcache->Lock(); m_csCached.Unlock(); pcache->AddToCache(GetControllingUnknown()); pcache->Unlock(); } else { m_csCached.Unlock(); }
return l; }
if (l == 0) { m_csCached.Unlock(); delete this; // Return right away so member variables aren't accidently referenced.
return l; } _ASSERTE(TRUE); // Should never get here.
return 0; } //if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP
STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject) { HRESULT hr; hr = _InternalQueryInterface(iid, ppvObject); if (hr == E_NOINTERFACE) { if (iid == __uuidof(ILRUCachedObject)) { *ppvObject = (void *)(ILRUCachedObject *)this; AddRef(); hr = S_OK; } } return hr; }
static HRESULT WINAPI CreateInstance(CComObjectCachedLRU<T>** pp);
// ILRUCachedObject
virtual HRESULT put_Cache(ILRUCache *pcache) { // NOTE: No reference count
m_pcache = pcache; return S_OK; }
#if 0
virtual ULONG RefCount() { return m_dwRef; } #endif
protected: CComGlobalsThreadModel::AutoCriticalSection m_csCached; ILRUCache *m_pcache; };
template <class T> HRESULT WINAPI CComObjectCachedLRU<T>::CreateInstance(CComObjectCachedLRU<T>** pp) { ATLASSERT(pp != NULL); HRESULT hRes = E_OUTOFMEMORY; CComObjectCachedLRU<T>* p = NULL; ATLTRY(p = new CComObjectCachedLRU<T>()) if (p != NULL) { p->SetVoid(NULL); p->InternalFinalConstructAddRef(); hRes = p->FinalConstruct(); p->InternalFinalConstructRelease(); if (hRes != S_OK) { delete p; p = NULL; } } *pp = p; return hRes; }
class CComObjectCacheByID : public ILRUCache { typedef map<long, IUnknown *> t_mapIdUnk; typedef map<IUnknown *, long> t_mapUnkId; typedef list<IUnknown *> t_listCache; public: CComObjectCacheByID(long cKeep) { m_cKeep = cKeep; } void _Lock() { m_csCached.Lock(); } void _Unlock() { m_csCached.Unlock(); } long Count() { return m_mapIdUnk.size(); } IUnknown * Item(long i) { t_mapIdUnk::iterator it; it = m_mapIdUnk.begin(); while (i--) it++; if (it == m_mapIdUnk.end()) return NULL; IUnknown *punk = ((*it).second);
// If it is in the cache then return NULL
t_listCache::iterator it2; it2 = m_listCache.begin(); while (it2 != m_listCache.end()) { if (*it2 == punk) return NULL; it2++; } punk->AddRef(); return punk; } long CachedCount() { return m_listCache.size(); }
HRESULT Cache(long id, IUnknown *punk) { HRESULT hr = S_OK; Lock();
// Need the canonical IUnknown
punk->QueryInterface(__uuidof(IUnknown), (void **) &punk);
t_mapIdUnk::iterator it = m_mapIdUnk.find(id); if (it != m_mapIdUnk.end()) { // If it is already there... just return...
hr = (punk == ((*it).second)) ? S_FALSE : E_INVALIDARG;
// ... but don't forget to release the ref count
// from the above QueryInterface() call.
punk->Release(); } else { CComQIPtr<ILRUCachedObject> pobj(punk);
pobj->put_Cache(this);
// Just keep one ref count (from QueryInterface() above) for both pointers.
m_mapIdUnk[id] = punk; m_mapUnkId[punk] = id; } Unlock();
return hr; } long get_ID(IUnknown *pobj) { long id = 0; Lock(); CComPtr<IUnknown> punk; pobj->QueryInterface(__uuidof(IUnknown), (void **) &punk); t_mapUnkId::iterator it = m_mapUnkId.find(punk); if (it != m_mapUnkId.end()) id = (*it).second; Unlock(); return id; } IUnknown * get_Unknown(long idObj) { CComPtr<IUnknown> punk; Lock(); t_mapIdUnk::iterator it = m_mapIdUnk.find(idObj); if (it != m_mapIdUnk.end()) punk = ((*it).second); Unlock(); return punk.Detach(); }
void Uncache(IUnknown *punk) { Lock(); t_mapUnkId::iterator it = m_mapUnkId.find(punk); if (it != m_mapUnkId.end()) { long idObj = ((*it).second);
t_mapIdUnk::iterator it2 = m_mapIdUnk.find(idObj); if (it2 != m_mapIdUnk.end()) m_mapIdUnk.erase(it2);
m_mapUnkId.erase(it);
RemoveFromCache(punk);
// Just one Release for both maps because only one ref count is held
// for all references from the cache.
punk->Release(); } Unlock(); } void Uncache(long idObj) { Lock(); t_mapIdUnk::iterator it = m_mapIdUnk.find(idObj); if (it != m_mapIdUnk.end()) { IUnknown *punk = ((*it).second);
t_mapUnkId::iterator it2 = m_mapUnkId.find(punk); if (it2 != m_mapUnkId.end()) m_mapUnkId.erase(it2);
m_mapIdUnk.erase(it);
RemoveFromCache(punk);
// Just one Release for both maps because only one ref count is held
// for all references from the cache.
punk->Release(); } Unlock(); } void Keep(long cKeep) { m_cKeep = cKeep; if (m_cKeep >= 0) { long cPurge = m_listCache.size() - m_cKeep; while (cPurge-- > 0) { Uncache(m_listCache.back()); } } } // ILRUCache interface
virtual void Lock() { _Lock(); } virtual void Unlock() { _Unlock(); } virtual void AddToCache(IUnknown *punk) { // if m_cKeep < 0 then keep infinite
// if m_cKeep == 0 then keep none
// else keep m_cKeep
if (m_cKeep == 0) { // Not keeping any, so just release it.
Uncache(punk); } else { m_listCache.push_front(punk); Keep(m_cKeep); } } virtual void RemoveFromCache(IUnknown *punk) { t_listCache::iterator it; it = m_listCache.begin(); while (it != m_listCache.end()) { if (*it == punk) { m_listCache.erase(it); return; } it++; } }
protected:
CComGlobalsThreadModel::AutoCriticalSection m_csCached; t_mapIdUnk m_mapIdUnk; t_mapUnkId m_mapUnkId; t_listCache m_listCache; long m_cKeep; };
#if 0 && defined(_DEBUG)
#define NewComObject(T) _NewComObject<T>(THIS_FILE, __LINE__)
template<class T> T * _NewComObject(LPCSTR lpszFileName, int nLine) { T* pT = NULL; try { pT = new(lpszFileName, nLine) CComObject<T>; } catch (CMemoryException *pe) { pe->Delete(); } return pT; } #define NewComObjectCachedLRU(T) _NewComObjectCachedLRU<T>(THIS_FILE, __LINE__)
template<class T> T * _NewComObjectCachedLRU(LPCSTR lpszFileName, int nLine) { CComObjectCachedLRU<T> *pT = NULL; try { pT = new(lpszFileName, nLine) CComObjectCachedLRU<T>(); } catch (CMemoryException *pe) { pe->Delete(); } return pT; } #else
#define NewComObject(T) _NewComObject<T>()
template<class T> T * _NewComObject() { CComObject<T> *pT = NULL; HRESULT hr = CComObject<T>::CreateInstance(&pT);
return pT; } #define NewComObjectCachedLRU(T) _NewComObjectCachedLRU<T>()
template<class T> T * _NewComObjectCachedLRU() { CComObjectCachedLRU<T> *pT = NULL; HRESULT hr = CComObjectCachedLRU<T>::CreateInstance(&pT); return pT; } #endif
#if 0
#define new DEBUG_NEW
#endif
template<class T> class MemCmpLess // : binary_function<T, T, bool>
{ public: bool operator()(const T & _X, const T & _Y) const { return (memcmp(&_X, &_Y, sizeof(T)) < 0); } };
class BSTRCmpLess // : binary_function<BSTR, BSTR, bool>
{ public: bool operator()(const BSTR & _X, const BSTR _Y) const { return (wcscmp(_X, _Y) < 0); } };
#define TRACE AtlTrace
#define TIMING 0
#include "timing.h"
#include "valid.h"
#include <mstvgs.h>
#include "_GuideStore.h"
#define LIBID_GUIDESTORELib LIBID_MSTVGS //UNDONE when cpp files that ref this are fixed.
#endif // !defined(AFX_STDAFX_H__B7E9C4D4_B8E5_48DE_A578_B75F8096FB42__INCLUDED)
|