/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2008 jOpenDocument, by ILM Informatique. All rights reserved. * * The contents of this file are subject to the terms of the GNU * General Public License Version 3 only ("GPL"). * You may not use this file except in compliance with the License. * You can obtain a copy of the License at http://www.gnu.org/licenses/gpl-3.0.html * See the License for the specific language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each file. * */ package org.jopendocument.util.cache; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * A watcher invalidates cache results when its data is modified. * * @param <K> cache key type. * @param <D> source data type, eg SQLTable. */ abstract public class CacheWatcher<K, D> { private final ICache<K, ?, D> c; private final Set<K> keys; private final D data; protected CacheWatcher(ICache<K, ?, D> c, D data) { this.c = c; this.keys = new HashSet<K>(); this.data = data; } public final D getData() { return this.data; } synchronized boolean isEmpty() { return this.keys.isEmpty(); } synchronized final void add(K key) { this.keys.add(key); } synchronized final void remove(K key) { this.keys.remove(key); } public final synchronized void die() { this.dying(); this.clearCache(); } protected void dying() { } protected final void clearCache() { // synch on the cache since otherwise we take and release its lock on each iteration // but keep ours all the time. Thus if another thread call a synchronized method of the // cache inbetween an iteration and tries to access us, a deadlock occurs. synchronized (this.c) { synchronized (this) { final Iterator<K> iter = this.keys.iterator(); while (iter.hasNext()) { final K key = iter.next(); iter.remove(); this.c.clear(key); } } } } }