//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
// Non MFC based generic cache class, January 1995
/* This class implements a simple cache. A cache object is instantiated
with the number of items it is to hold. An item is a pointer to an
object derived from CBaseObject (helps reduce memory leaks). The cache
can then have objects added to it and removed from it. The cache size
is fixed at construction time and may therefore run out or be flooded.
If it runs out it returns a NULL pointer, if it fills up it also returns
a NULL pointer instead of a pointer to the object just inserted */
#include <streams.h>
/* Constructor creates an array of pointers (to CBaseObject derived objects)
and then zero fills each position. The cache cannot be resized dynamically
so if the number of objects that you use varies widely during the lifetime
of the cache then there will be some inefficiency. Making the cache resize
would be an expensive operation especially with so little to be gained */
CCache::CCache(TCHAR *pName, INT iItems) :
CBaseObject(pName),
m_iCacheSize(iItems),
m_iUsed(0)
{
ASSERT(iItems > 0);
/* Create the array of pointers and set the cache size, if this does not
succeed then it should probably throw an exception otherwise there is
no way to propogate the error condition back to creating object */
m_ppObjects = (CBaseObject **) new BYTE[iItems * sizeof(CBaseObject *)];
ASSERT(m_ppObjects);
ZeroMemory((PVOID) m_ppObjects,iItems * sizeof(CBaseObject *));
}
/* Destructor causes the cached objects to be deleted (if not already done)
and then deletes the (variable length) array that was used to hold them */
CCache::~CCache()
{
RemoveAll();
delete m_ppObjects;
}
/* Add an item to the cache, if no space is found for it then we return NULL
otherwise we put the object in the free space. The object is meant to be
as small and lightweight as possible so it does not do any multithread
protection. This is assumed to be handled by the owning (list) object */
CBaseObject *CCache::AddToCache(CBaseObject *pObject)
{
/* Have we any room for this object */
if (m_iUsed == m_iCacheSize) {
return NULL;
}
/* Add the object to the end of the cache */
m_ppObjects[m_iUsed] = pObject;
m_iUsed++;
return pObject;
}
/* This is called to retrieve one of the objects we were given to look after
if there are none available then we return NULL otherwise the return the
object. NOTE we do not do any processing on the object so it will be in
exactly the same state when it is handed back as when it is installed */
CBaseObject *CCache::RemoveFromCache()
{
/* Are all the cache positions empty */
if (m_iUsed == 0) {
return NULL;
}
/* Return the last object put into the cache */
m_iUsed--;
ASSERT(m_ppObjects[m_iUsed]);
return m_ppObjects[m_iUsed];
}
/* Delete all the objects held in the cache, simply scans the list of objects
in the cache and deletes each of them in turn. The list class uses a cache
to manage node objects that are frequently created and destroyed and when
the list is finally deleted we will also go at which point we also delete
any remaining node objects. The objects must be derived from CBaseObject */
void CCache::RemoveAll()
{
while (m_iUsed--) {
ASSERT(m_ppObjects[m_iUsed]);
delete m_ppObjects[m_iUsed];
}
}