/* lru.c * LRU cache * (c) 2002 Karel 'Clock' Kulhavy * This file is a part of the Links program, released under GPL. */ #include "cfg.h" #ifdef G #include "links.h" static inline void row_insert(struct lru_entry **row, struct lru_entry *ptr) { ptr->next = *row; if (ptr->next) ptr->next->previous = &ptr->next; ptr->previous = row; *row = ptr; } static inline void row_delete(struct lru_entry *ptr) { if (ptr->next) ptr->next->previous = ptr->previous; *ptr->previous = ptr->next; } void lru_insert(struct lru *cache, void *entry, struct lru_entry **row, unsigned bytes_consumed) { struct lru_entry *new_entry = mem_alloc(sizeof(*new_entry)); new_entry->above = NULL; new_entry->below = cache->top; new_entry->data = entry; new_entry->bytes_consumed = bytes_consumed; if (new_entry->below) new_entry->below->above = new_entry; else cache->bottom = new_entry; row_insert(row, new_entry); cache->top = new_entry; cache->bytes += bytes_consumed; cache->items++; } /* Returns bottom (or NULL if the cache is empty) but doesn't * unlink it. */ void *lru_get_bottom(struct lru *cache) { if (!cache->bottom) return NULL; return cache->bottom->data; } /* Destroys bottom on nonempty cache. If the cache is empty, segmentation * fault results. */ void lru_destroy_bottom(struct lru *cache) { struct lru_entry *it = cache->bottom; cache->bytes -= cache->bottom->bytes_consumed; cache->items--; cache->bottom = it->above; if (cache->bottom) cache->bottom->below = NULL; else cache->top = NULL; row_delete(it); mem_free(it); } /* Returns a value of "data" * template is what we search for. */ void *lru_lookup(struct lru *cache, void *templat, struct lru_entry **row) { struct lru_entry *ptr = *row; while (ptr) { if (!cache->compare_function(ptr->data,templat)) { /* Found */ if (ptr->above) { if (ptr->below) { ptr->below->above = ptr->above; } else { cache->bottom = ptr->above; } ptr->above->below = ptr->below; ptr->above = NULL; ptr->below = cache->top; cache->top->above = ptr; cache->top = ptr; } if (ptr != *row) { row_delete(ptr); row_insert(row, ptr); } return ptr->data; } ptr = ptr->next; } return NULL; } void lru_init(struct lru *cache, int (*compare_function)(void *entry, void *templat)) { cache->compare_function = compare_function; cache->top = NULL; cache->bottom = NULL; cache->bytes = 0; cache->items = 0; } #endif