Listing 2: Implementation of cache manager


/* mru.cpp
 * Copyright (c) 1995 T.W. Nelson.  Permission
 * is hereby granted to use this code in any
 * manner provided the user display this
 * copyright notice in the source
 */


#include "mru.h"

MruCache::MruCache(int nn, int objsz)
{
    Cm = new TIGenDoubleList
                   <CacheNode,StdAlloc>;
    Itr = new TIGenDoubleListIterator
                   <CacheNode,StdAlloc>(*Cm);
    _nodes = nn;
    if( _nodes < 3 )
        _nodes = 3;    /* adjust to at least
                          3 nodes */
    for( int i = _nodes; i; i-- )
        Cm->PutHead( new CacheNode(objsz) );
    Mru = Cm->PeekHead();
    Lru = Cm->PeekTail();
    #if defined( TESTING )
    _hits = _miss = _adds = 0;
    #endif
}

MruCache::~MruCache()
{
    Cm->Flush(1); /* destroy all
                     cache nodes */
    delete Cm;
    delete Itr;
}
void MruCache::Flush()
{  /* Free all nodes for re-use. */
    CacheNode * p;
    Itr->Restart();
    while( (p = (*Itr)++) != 0 )
    {   if( p->_stat == CacheNode::Mark )
            Proc(p); /* process the node */
        p->_stat = CacheNode::Release;
    }
}

CacheNode *MruCache::Search(ulong tag)
{
    CacheNode * p;
    Itr->Restart();
    while( (p = (*Itr)++) != 0 )
    {   if( p->_tag == tag )
        {

            #if defined( TESTING )
            _hits++;        /* found it */
            #endif

            /* make it mru */
            return make_mru( p ); 
        }
    }

    #if defined( TESTING )
    _miss++;               /* missed again */
    #endif

    /* return not found */
    return (CacheNode *) 0; 
}

CacheNode *MruCache::make_mru(CacheNode *p)
{
    if( p == Mru )
        return p;     /* already MRU, OK */

    Cm->Unlink( p );  /* Disconnect node
                         at 'p' */

    if( p == Lru )
        /* LRU = prev node */
        Lru = Cm->PeekTail(); 

    /* re-connect 'p' as new MRU ...... */
    Cm->PutHead( p );
    Mru = p;
    return p;

CacheNode *MruCache::AddNew( ulong tag )
{
    CacheNode *p = Lru;
    if( p->_stat == CacheNode::Mark )
            Proc(p);   /* process the node */

    p->_stat = CacheNode::Release;

    #if defined( TESTING )
    _adds++;
    #endif
    p->_tag = tag;       /* re-number it */
    return make_mru(p);
}

CacheNode *
MruCache::Mark( ulong tag,
                CacheNode::Status flag ) 
{
    CacheNode * p;
    Itr->Restart();

    while( (p = (*Itr)++) != 0 )
    {   if( p->_tag == tag )
        {   p->_stat = flag;
            return p;
        }
    }
    return (CacheNode *) 0;
}

//End of File