jtulach@319: package org.apidesign.javamonitorflaws; jtulach@319: jtulach@319: import java.util.HashMap; jtulach@319: import java.util.Map; jtulach@319: jtulach@319: /** Classical caching support class that makes sure there is jtulach@319: * always one "To" value for each "From" one returned from the {@link #get} jtulach@319: * method. However it does not prevent multiple threads to call jtulach@319: * {@link #createItem} multiple times for the same "From" value. jtulach@319: *

jtulach@319: * In contrast to {@link Cache}, this is correctly synchronized. jtulach@319: * jtulach@319: * @author Jaroslav Tulach jtulach@319: */ jtulach@319: // BEGIN: monitor.pitfalls.CacheOK jtulach@319: public abstract class CacheOK { jtulach@320: private final Object LOCK = new Object(); jtulach@319: jtulach@319: private Map cache; jtulach@319: jtulach@319: protected abstract To createItem(From f); jtulach@319: jtulach@319: public final To get(From f) { jtulach@319: To t = inspectValue(f); jtulach@319: if (t != null) { jtulach@319: return t; jtulach@319: } jtulach@319: To newT = createItem(f); jtulach@319: return registerValue(f, newT); jtulach@319: } jtulach@319: jtulach@319: jtulach@319: private To inspectValue(From f) { jtulach@319: synchronized (LOCK) { jtulach@319: if (cache == null) { jtulach@319: cache = new HashMap(); jtulach@319: } jtulach@319: return cache.get(f); jtulach@319: } jtulach@319: } jtulach@319: jtulach@319: private To registerValue(From f, To newT) { jtulach@319: synchronized (LOCK) { jtulach@319: To t = cache.get(f); jtulach@319: if (t == null) { jtulach@319: cache.put(f, newT); jtulach@319: return newT; jtulach@319: } else { jtulach@319: return t; jtulach@319: } jtulach@319: } jtulach@319: } jtulach@319: } jtulach@319: // END: monitor.pitfalls.CacheOK