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;
};
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;
};