New Caching Mechanism

class e_Cache;

class e_CacheSlot {

    friend 
class e_Cache;

public:
    e_CacheSlot( 
int slotSize )
    {
        slot_size 
= slotSize;
        slot_mem 
= new char [ slot_size ];
        next_slot 
= NULL;
        last_time 
= 0;
        file_id 
= 0;
        locked 
= 0;
    }

    
virtual ~e_CacheSlot()
    {
        
if( slot_mem )
        {
            delete [] slot_mem;
            slot_mem 
= NULL;
        }
    }

    
virtual void    deleteThis() = 0;

    
void    clearThis()
    {
        
//    backup slot_mem to disk and delete the memory

        
char    file_name[ MAX_FILE_NAME_LEN ];

        sprintf( file_name, 
"%d", file_id );
        
        FILE    
*fp = fopen( file_name, "wb" );

        fwrite( slot_mem, slot_size, 
1, fp );

        fclose( fp );

        delete [] slot_mem;
        slot_mem 
= NULL;
    }

    
void    accessBegin( e_Cache *pCache )
    {
        
++ locked;

        
if( slot_mem == NULL )
        {
            
//    allocate memory

            slot_mem 
= new char [ slot_size ];

            
//    reload data from disk

            
char    file_name[ MAX_FILE_NAME_LEN ];

            sprintf( file_name, 
"%d", file_id );
        
            FILE    
*fp = fopen( file_name, "rb" );

            fread( slot_mem, slot_size, 
1, fp );

            fclose( fp );

            
//    delete oldest item

            pCache
->purge_memory( slot_size );
        }
    }

    
void    accessEnd( e_Cache *pCache )
    {
        last_time 
= pCache->get_current_time();

        
-- locked;
    }

public:
    
char            *slot_mem;

private:
    e_CacheSlot        
*next_slot;
    
int                slot_size;
    ULONG            last_time;
    
int                file_id;
    
int                locked;
};

//    a cache for a thread, each thread should has its own cache by this design
class e_Cache {
public:
    e_Cache( 
int cacheSize )
    {
        slots 
= NULL;
        limit 
= cacheSize;
        current_time 
= 0;
        current_file_id 
= 0;
        memory_size 
= 0;
    }

    
~e_Cache()
    {
        e_CacheSlot    
*pSlot;

        
while( ( pSlot = slots ) != NULL )
        {
            slots 
= pSlot->next;

            pSlot
->deleteThis();
        }
    }

    ULONG    get_current_time()
    {
        
return ( ++ current_time );
    }

    
void    add_slot( e_CacheSlot *newSlot )
    {
        
if( newSlot )
        {
            newSlot
->next_slot = slots;
            slots 
= newSlot;
            newSlot
->file_id = ( ++ current_file_id );

            purge_memory( newSlot
->slot_size );
        }
    }

    
void    purge_memory( int newAddSize )
    {
        memory_size 
+= newAddSize;

        
//    if there's no enough memory, delete oldest items

        
if( memory_size > limit && slots )
        {
            e_CacheSlot        
*oldestSlot = slots;
            e_CacheSlot        
*pSlot = slots->next_slot;

            
while( pSlot )
            {
                
if( pSlot->locked == 0 && pSlot->last_time < oldestSlot->last_time )
                {
                    oldestSlot 
= pSlot;
                }

                pSlot 
= pSlot->next_slot;
            }

            
if( oldestSlot->locked == 0 )
            {
                oldestSlot
->clearThis();
                memory_size 
-= oldestSlot->slot_size;
            }
        }
    }

private:
    e_CacheSlot        
*slots;
    
int                limit;
    ULONG            memory_size;
    ULONG            current_time;
    
int                current_file_id;
};
原文地址:https://www.cnblogs.com/len3d/p/1290912.html