This is FunctionCache.m in view mode; [Download] [Up]
/*
File FunctionCache.m
A cache remembers function values, f(x) = y, so that function evaluations can avoid lengthy recomputations. Each cache has a finite capacity. When a new value is added to the cache, the cache discards the value that has gone unused for the longest period of time. It uses a callback function to alert the application that a value is being discarded. In this way memory can be freed and reclaimed for other uses.
*/
#import <appkit/appkit.h>
#import <stdlib.h>
#import "FunctionCache.h"
/* 行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行 */
static void freeObject (void *);
/* 行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行 */
@implementation FunctionCache
- initKey: (const char *) key
value: (const char *) value
capacity: (unsigned) theCapacity
freeKey: (freeFunction) theFreeKey
freeValue: (freeFunction) theFreeValue;
{
[super init];
cache = [[HashTable alloc]
initKeyDesc: key
valueDesc: "!"
capacity: theCapacity ];
capacity = theCapacity;
freeKey = theFreeKey;
freeValue = theFreeValue;
worst = best = NULL;
return self;
}
- initKeyType: (int) key valueType: (int) value capacity: (unsigned) theCapacity;
{
freeFunction theFreeKey, theFreeValue;
char * type;
switch (key)
{
case ISASTRING: type = "*"; theFreeKey = free; break;
case ISAOBJECT: type = "@"; theFreeKey = freeObject; break;
default: type = NULL; theFreeKey = NULL; break;
}
switch (value)
{
case ISASTRING: theFreeValue = free; break;
case ISAOBJECT: theFreeValue = freeObject; break;
default: theFreeValue = NULL; break;
}
[self initKey: type
value: NULL
capacity: theCapacity
freeKey: theFreeKey
freeValue: theFreeValue ];
return self;
}
- free
{
[self setCapacity: 0];
[cache free];
return [super free];
}
- setCapacity: (unsigned) theCapacity
{
while ([cache count] > theCapacity) [self remove: worst->key];
capacity = theCapacity;
return self;
}
/* 行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行 */
- add: (void *) key value: (void *) value;
{
cacheElement * new;
new = (cacheElement *) malloc(sizeof(cacheElement));
new->key = key;
new->value = value;
new->previous = NULL;
new->next = best;
if (best != NULL) best->previous = new;
[self release: [self detach: [cache insertKey: key value: new]]];
best = new;
if (worst == NULL) worst = new;
if ([cache count] > capacity) [self remove: worst->key];
return self;
}
- remove: (void *) key;
{
[self release: [self detach: [cache removeKey: key]]];
return self;
}
- (void *) find: (void *) key;
{
cacheElement * cell;
if ((cell = (cacheElement *) [cache valueForKey: key]) != NULL)
{
[self detach: cell];
cell->next = best;
if (best != NULL) best->previous = cell;
best = cell;
if (worst == NULL) worst = cell;
}
return (cell == NULL) ? NULL:cell->value;
}
- (cacheElement *) detach: (cacheElement *) cell
{
if (cell != NULL)
{
if (cell->previous) cell->previous->next = cell->next;
if (cell->next) cell->next->previous = cell->previous;
if (best == cell) best = cell->next;
if (worst == cell) worst = cell->previous;
cell->previous = cell->next = NULL;
}
return cell;
}
- release: (cacheElement *) cell
{
if (cell != NULL)
{
if (freeKey != NULL) (* freeKey)(cell->key);
if (freeValue != NULL) (* freeValue)(cell->value);
free(cell);
}
return self;
}
@end
/* 行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行行 */
static void freeObject (object)
void * object;
{
[(id) object free];
}These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.