/* ARISA - Validity Cache * Copyright (C) 2004 Carl Ritson * * 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 program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /*** * The validity cache makes use of the fact that pointers such always be * atomic data types on modern hardware. If they aren't then... we have * a problem. ***/ #include "arisa.h" // Size is determined at compile time #define CACHE_SIZE 256 #define PAIRING_SIZE 32 static void **cache = NULL; static void **pairing = NULL; // these are for debugging //static int no_tests = 0; //static int no_hits = 0; //static int no_inserts = 0; //static int no_deletes = 0; static uint32_t hash_ptr(void *ptr) { uint8_t *p = (uint8_t *)&ptr; uint32_t hash; if(sizeof(void *) == 4) { hash = (p[0] * 37) + p[1]; hash = (hash * 37) + p[2]; hash = (hash * 37) + p[3]; } else if(sizeof(void *) == 8) { hash = (p[0] * 37) + p[1]; hash = (hash * 37) + p[2]; hash = (hash * 37) + p[3]; hash = (hash * 37) + p[4]; hash = (hash * 37) + p[5]; hash = (hash * 37) + p[6]; hash = (hash * 37) + p[7]; } return hash; } void validity_cache_init(void) { int i; cache = xalloc(sizeof(void *)*CACHE_SIZE); pairing = xalloc(sizeof(void *)*PAIRING_SIZE); for(i = 0; i < CACHE_SIZE; ++i) cache[i] = NULL; for(i = 0; i < PAIRING_SIZE; ++i) pairing[i] = NULL; } void validity_cache_free(void) { if(cache != NULL) { xfree(cache); cache = NULL; } if(pairing != NULL) { xfree(pairing); pairing = NULL; } } void validity_cache_manage(void) { // D("validity-cache; tests: %d, hits: %d, inserts: %d, deletes: %d", // no_tests,no_hits,no_inserts,no_deletes); } int validity_test(void *ptr) { // no_tests++; if(ptr != NULL && cache[hash_ptr(ptr) % CACHE_SIZE] == ptr) { // no_hits++; return 1; } else { return 0; } } void validity_insert(void *ptr) { // no_inserts++; if(ptr != NULL) cache[hash_ptr(ptr) % CACHE_SIZE] = ptr; } void validity_delete(void *ptr) { // no_deletes++; if(ptr != NULL) cache[hash_ptr(ptr) % CACHE_SIZE] = NULL; } int validity_pair_test(void *ptr1, void *ptr2) { if(ptr1 != NULL && ptr2 != NULL) { uint32_t h1 = hash_ptr(ptr1); uint32_t h2 = hash_ptr(ptr2); if(cache[h1 % CACHE_SIZE] == ptr1 && cache[h2 % CACHE_SIZE] == ptr2 && pairing[(h1+h2) % PAIRING_SIZE] == ptr2) return 1; } return 0; } void validity_pair_insert(void *ptr1, void *ptr2) { if(ptr1 != NULL && ptr2 != NULL) { uint32_t h1 = hash_ptr(ptr1); uint32_t h2 = hash_ptr(ptr2); cache[h1 % CACHE_SIZE] = ptr1; cache[h2 % CACHE_SIZE] = ptr2; pairing[(h1+h2) % PAIRING_SIZE] = ptr2; } } void validity_pair_delete(void *ptr1, void *ptr2) { if(ptr1 != NULL && ptr2 != NULL) { uint32_t h1 = hash_ptr(ptr1); uint32_t h2 = hash_ptr(ptr2); cache[h1 % CACHE_SIZE] = NULL; cache[h2 % CACHE_SIZE] = NULL; pairing[(h1+h2) % PAIRING_SIZE] = NULL; } }