/* property-cache.c -- maintain the X property cache $Id: property-cache.c,v 1.2 2002/10/01 07:05:17 jsh Exp $ Copyright (C) 2002 John Harper. This file is part of sawfish. sawfish 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, or (at your option) any later version. sawfish 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 sawfish; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. Authors: John Harper */ #include "sawmill.h" #include #define CACHE_ASSOC 4 #define CACHE_SETS 127 #define CACHE_SIZE (CACHE_ASSOC * CACHE_SETS) #define CACHE_HASH(id,prop) ((((id) << 4) ^ ((prop) >> 3)) % CACHE_SETS) static repv *cache_ids; static repv *cache_props; static repv *cache_values; static repv cache_vec; static u_int cache_ages[CACHE_SIZE]; static u_int cache_updates[CACHE_SIZE]; static u_int cache_clock; static u_int cache_hits, cache_misses; repv property_cache_ref (repv id, repv prop) { u_int h, i; if (cache_vec == rep_NULL) return rep_NULL; h = CACHE_HASH (id, prop) * CACHE_ASSOC; DB (("prop ref: 0x%x,%s (%d) -> ", id, rep_STR (rep_SYM (prop)->name), h)); for (i = h; i < h + CACHE_ASSOC; i++) { if (cache_ids[i] == id && cache_props[i] == prop) { cache_hits++; DB (("hit\n")); cache_ages[i] = ++cache_clock; return cache_values[i]; } } DB (("miss\n")); cache_misses++; return rep_NULL; } void property_cache_set (repv id, repv prop, repv value, int invals) { u_int h, i, oldest, oldest_age; if (cache_vec == rep_NULL) { cache_vec = Fmake_vector (rep_MAKE_INT (CACHE_SIZE * 3), Qnil); rep_mark_static (&cache_vec); cache_ids = rep_VECT (cache_vec)->array; cache_props = cache_ids + CACHE_SIZE; cache_values = cache_props + CACHE_SIZE; } h = CACHE_HASH (id, prop) * CACHE_ASSOC; oldest_age = UINT_MAX; oldest = -1; for (i = h; i < h + CACHE_ASSOC; i++) { if (cache_ids[i] == id && cache_props[i] == prop) { cache_values[i] = value; cache_updates[i] += invals; return; } if (cache_ages[i] <= oldest_age) { oldest_age = cache_ages[i]; oldest = i; } } assert (oldest != -1); if (cache_ids[oldest] != 0) DB (("prop eject: 0x%x (%d)\n", cache_ids[oldest], oldest)); cache_ids[oldest] = id; cache_props[oldest] = prop; cache_values[oldest] = value; cache_ages[oldest] = ++cache_clock; cache_updates[oldest] = invals; DB (("set: 0x%x,%s (%d)\n", id, rep_STR (rep_SYM (prop)->name), oldest)); } void property_cache_invalidate_window (repv id) { int i; if (cache_vec == rep_NULL) return; for (i = 0; i < CACHE_SIZE; i++) { if (cache_ids[i] == id) { cache_ids[i] = 0; cache_props[i] = Qnil; cache_values[i] = Qnil; } } } void property_cache_invalidate (repv id, repv prop) { u_int h, i; if (cache_vec == rep_NULL) return; h = CACHE_HASH (id, prop) * CACHE_ASSOC; for (i = h; i < h + CACHE_ASSOC; i++) { if (cache_ids[i] == id && cache_props[i] == prop) { if (cache_updates[i] == 0) { cache_ids[i] = 0; cache_props[i] = Qnil; cache_values[i] = Qnil; } else cache_updates[i]--; } } }