| /*************************************************************************** |
| * __________ __ ___. |
| * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| * \/ \/ \/ \/ \/ |
| * |
| * Copyright (C) 2003 Tat Tang |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| ****************************************************************************/ |
| |
| #include "lru.h" |
| |
| struct lru_node |
| { |
| short _next; |
| short _prev; |
| unsigned char data[1]; /* place holder */ |
| }; |
| |
| #define lru_node_p(pl, x) \ |
| ((struct lru_node*)(pl->_base + pl->_slot_size * x)) |
| |
| /******************************************************************************* |
| * lru_create |
| ******************************************************************************/ |
| void lru_create(struct lru* pl, void *buf, short size, short data_size) |
| { |
| pl->_base = (unsigned char*) buf; |
| pl->_slot_size = data_size + LRU_SLOT_OVERHEAD; |
| |
| pl->_size = size; |
| |
| pl->_head = 0; |
| pl->_tail = pl->_size - 1; |
| |
| /* Initialise slots */ |
| int i; |
| for (i=0; i<pl->_size; i++) |
| { |
| lru_node_p(pl, i)->_next = i + 1; |
| } |
| |
| /* Fix up head and tail to form circular buffer */ |
| lru_node_p(pl, pl->_tail)->_next = pl->_head; |
| } |
| |
| /******************************************************************************* |
| * lru_traverse |
| ******************************************************************************/ |
| void lru_traverse(struct lru* pl, void (*callback)(void* data)) |
| { |
| short i; |
| struct lru_node* slot; |
| short loc = pl->_head; |
| |
| for (i = 0; i < pl->_size; i++) |
| { |
| slot = lru_node_p(pl, loc); |
| callback(slot->data); |
| loc = slot->_next; |
| } |
| } |
| |
| /******************************************************************************* |
| * lru_touch |
| ******************************************************************************/ |
| void lru_touch(struct lru* pl, short handle) |
| { |
| if (handle == pl->_head) |
| { |
| pl->_head = lru_node_p(pl, pl->_head)->_next; |
| pl->_tail = lru_node_p(pl, pl->_tail)->_next; |
| return; |
| } |
| |
| if (handle == pl->_tail) |
| { |
| return; |
| } |
| |
| /* Remove current node from linked list */ |
| struct lru_node* curr_node = lru_node_p(pl, handle); |
| |
| /* insert current node at tail */ |
| struct lru_node* tail_node = lru_node_p(pl, pl->_tail); |
| |
| curr_node->_next = tail_node->_next; |
| tail_node->_next = handle; |
| |
| pl->_tail = handle; |
| } |
| |
| /******************************************************************************* |
| * lru_data |
| ******************************************************************************/ |
| void *lru_data(struct lru* pl, short handle) |
| { |
| return lru_node_p(pl, handle)->data; |
| } |
| |