/*----------------------------------------------------------------------------- * * File: wiacache.cpp * Author: Samuel Clement (samclem) * Date: Thu Sep 09 16:15:11 1999 * * Copyright (c) 1999 Microsoft Corporation * * Description: * * This contains the implementation of the CWiaCacheManager. Which handles * managing items/data that we want to cache for performance reasons * * History: * 09 Sep 1999: Created. *----------------------------------------------------------------------------*/ #include "stdafx.h" DeclareTag( tagWiaCache, "!WiaCache", "Wia cache debug information" ); CWiaCacheManager* CWiaCacheManager::sm_pManagerInstance = NULL; /*----------------------------------------------------------------------------- * CWiaCacheManager * * This creates a new CWiaCacheManager object. This simply initalizes all * the variables to a known state. Initialize handles actually creating * the objects that we need. *--(samclem)-----------------------------------------------------------------*/ CWiaCacheManager::CWiaCacheManager() : m_hThumbHeap( 0 ) { TraceTag((0,"** Creating WiaCache" )); TRACK_OBJECT( "CWiaCacheManager - SINGLETON" ); } /*----------------------------------------------------------------------------- * ~CWiaCacheManager * * This destroyes the CWiaCacheManager object. This will handle taking all * the memory it has away with it. including any thumbnail memory we might be * carrying around. *--(samclem)-----------------------------------------------------------------*/ CWiaCacheManager::~CWiaCacheManager() { TraceTag((0, "** Destroying WiaCache" )); // Destroying the heap will free any memory // allocated by the heap, so this will keep us // from leaking if ( m_hThumbHeap ) { HeapDestroy( m_hThumbHeap ); m_hThumbHeap = 0; } // destroy our critical section DeleteCriticalSection( &m_cs ); } /*----------------------------------------------------------------------------- * CWiaCacheManager::Initialize * * This is called following a call to new in order to get this object ready * to use. Without calling this the cache manager will be unusable. *--(samclem)-----------------------------------------------------------------*/ bool CWiaCacheManager::Initialize() { SYSTEM_INFO si; // initialize our critical section __try { if(!InitializeCriticalSectionAndSpinCount( &m_cs, MINLONG )) { return false; } } __except(EXCEPTION_EXECUTE_HANDLER) { return false; } // we need to create the heap we are going to allocate // out thumbnail memory from GetSystemInfo( &si ); m_hThumbHeap = TW32( HeapCreate( HEAP_NO_SERIALIZE, si.dwPageSize, 0 ), HANDLE(0) ); return ( m_hThumbHeap != 0 ); } /*----------------------------------------------------------------------------- * CWiaCacheManager::GetDevice * * This returns a cached pointer to the device. This returns true if the * device was found, (and the out param is valid) or false if we didn't * find it. Example: * * CWiaCacheManager* pCache = CWiaCacheManager::GetInstance(); * IWiaItem* pItem = NULL; * * if ( pCache->GetDevice( bstrId, &pItem ) ) * { * // use pItem * . * . * pItem->Release(); * } * else * { * // create pItem and use * . * . * pCache->AddDevice( bstrId, pItem ); * pItem->Release(); * } * * bstrId: the id of the device that we want. * ppDevice: Out, recieves the cached device pointer. *--(samclem)-----------------------------------------------------------------*/ bool CWiaCacheManager::GetDevice( CComBSTR bstrId, IWiaItem** ppDevice ) { return FALSE; // // NOTE: We've effectively disabled the device cache by always returning // FALSE here and not calling AddDevice anywhere else. // /* bool fRet = true; Assert( ppDevice ); // our member class does most of the work for us, however we need // to ensure that we are thread safe Lock(); *ppDevice = m_icItemCache.GetFromCache( bstrId ); Unlock(); if ( !(*ppDevice) ) fRet = false; else (*ppDevice)->AddRef(); return fRet; */ } /*----------------------------------------------------------------------------- * CWiaCacheManager::AddDevice * * This adds a device item pointer to the cache. See GetDevice() for an * complete example. Returns true if we successfully added the device * * bstrId: the ID of the new device to add * pDevice: The pointer to add to the cache *--(samclem)-----------------------------------------------------------------*/ bool CWiaCacheManager::AddDevice( CComBSTR bstrId, IWiaItem* pDevice ) { bool fRet = true; Assert( pDevice ); // again our member class does a majority of the work so all we // need to do is to call through. However, we make sure that // we are thread safe when we do that Lock(); fRet = m_icItemCache.AddToCache( bstrId, pDevice ); Unlock(); return fRet; } /*----------------------------------------------------------------------------- * CWiaCacheManager::RemoveDevice * * This removes a device from the cache. This returns true of the item * was found in the cache, or false if it was not. * * bstrId: the ID of the device to remove from the cache *--(samclem)-----------------------------------------------------------------*/ bool CWiaCacheManager::RemoveDevice( CComBSTR bstrId ) { bool fRet = false; Lock(); // remove the item from the cache fRet = m_icItemCache.RemoveFromCache( bstrId ); Unlock(); return fRet; } /*----------------------------------------------------------------------------- * CWiaCacheManager::GetThumbnail * * This attempts to get a thumbnail from the cache. There might not * be one there, in which case this simply returns 'false' * * bstrFullItemName: the name of the item we want the thumb for * ppbThumb: Out, pointer to the thumbnail bites * pcbThumb: Out, recieves the size of the thumbnail *--(samclem)-----------------------------------------------------------------*/ bool CWiaCacheManager::GetThumbnail( CComBSTR bstrFullItemName, BYTE** ppbThumb, DWORD* pcbThumb ) { bool fRet = false; THUMBNAILCACHEITEM* ptci = 0; Assert( ppbThumb && pcbThumb ); *ppbThumb = 0; *pcbThumb = 0; Lock(); ptci = m_tcThumbnails[bstrFullItemName]; if ( ptci ) { *ppbThumb = ptci->pbThumb; *pcbThumb = ptci->cbThumb; fRet = true; } Unlock(); return fRet; } /*----------------------------------------------------------------------------- * CWiaCacheManager::AddThumbnail * * This attempts to add a thumbnail to the cache. this will return true * if the item was successfully added or false if it failed. * * bstrFullItemName: the name of the item to cache the thumb for * pbThumb: Pointer to the thumbnail memory * cbThumb: the number of bytes in the thumbnail. *--(samclem)-----------------------------------------------------------------*/ bool CWiaCacheManager::AddThumbnail( CComBSTR bstrFullItemName, BYTE* pbThumb, DWORD cbThumb ) { bool fRet = false; THUMBNAILCACHEITEM* ptci = 0; Assert( pbThumb && cbThumb ); Assert( m_hThumbHeap && "Need a valid thumbnail heap" ); RemoveThumbnail( bstrFullItemName ); Lock(); ptci = reinterpret_cast(TW32(HeapAlloc( m_hThumbHeap, HEAP_NO_SERIALIZE, sizeof( THUMBNAILCACHEITEM ) ), LPVOID(0) ) ); if ( ptci ) { ptci->pbThumb = pbThumb; ptci->cbThumb = cbThumb; m_tcThumbnails[bstrFullItemName] = ptci; fRet = true; } Unlock(); return fRet; } /*----------------------------------------------------------------------------- * CWiaCacheManager::RemoveThumbnail * * THis removes a thumbnail from the cache. This will return true if found * an item to remove, or false if it removed nothing. * * bstrFullItemName: the name of the item to remove from the cache. *--(samclem)-----------------------------------------------------------------*/ bool CWiaCacheManager::RemoveThumbnail( CComBSTR bstrFullItemName ) { bool fRet = false; THUMBNAILCACHEITEM* ptci = 0; Lock(); ptci = m_tcThumbnails[bstrFullItemName]; if ( ptci ) { m_tcThumbnails.erase( bstrFullItemName ); TW32( HeapFree( m_hThumbHeap, HEAP_NO_SERIALIZE, ptci ), FALSE ); fRet = true; } Unlock(); return fRet; } /*----------------------------------------------------------------------------- * CWiaCacheManager::AllocThumbnail * * This allocates memory for a thumbnail from our thumbnail heap. * * cbThumb: the size of the thumbnail to allocate * ppbThumb: Out, recieves the pointer to the memory *--(samclem)-----------------------------------------------------------------*/ bool CWiaCacheManager::AllocThumbnail( DWORD cbThumb, BYTE** ppbThumb ) { Assert( m_hThumbHeap && "Error: NULL thumbnail heap" ); Assert( ppbThumb && cbThumb != 0 ); Lock(); *ppbThumb = reinterpret_cast(TW32( HeapAlloc( m_hThumbHeap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, cbThumb ), LPVOID(0) )); Unlock(); return ( *ppbThumb != NULL ); } /*----------------------------------------------------------------------------- * CWiaCacheManager::FreeThumbnail * * This frees the thumbnail memory. This _SHOULD_NOT_ be called if the * thumbnail is cached. This should only be called to cleanup after an error * generating the thumbnail. * * pbThumb: the memory to free *--(samclem)-----------------------------------------------------------------*/ void CWiaCacheManager::FreeThumbnail( BYTE* pbThumb ) { Assert( m_hThumbHeap && "Error: NULL thumbnail heap" ); Assert( pbThumb ); Lock(); TW32( HeapFree( m_hThumbHeap, HEAP_NO_SERIALIZE, pbThumb ), FALSE ); Unlock(); } /*----------------------------------------------------------------------------- * CWiaCacheManager::Init [static] * * This is called to initalize the cache manager. This simply creates and * instance of the cache manager and then initalizes it. * * Notes: This can only be called once *--(samclem)-----------------------------------------------------------------*/ bool CWiaCacheManager::Init() { Assert( !sm_pManagerInstance && "\nInit() can only be called once. Expected NULL instance" ); sm_pManagerInstance = new CWiaCacheManager(); if ( !sm_pManagerInstance ) return false; return sm_pManagerInstance->Initialize(); } /*----------------------------------------------------------------------------- * CWiaCacheManager::Uninit [static] * * This is called to uninitialize the cache manager. basically this is called * to destroy the instance we have. If we have one. * * Notes: This should only be called once *--(samclem)-----------------------------------------------------------------*/ bool CWiaCacheManager::Uninit() { if ( sm_pManagerInstance ) delete sm_pManagerInstance; sm_pManagerInstance = 0; return true; }