Martin Desruisseaux a écrit :
So there is my proposal: I will commit a ObjectCache2 class (without any ObjectCacheEntry class) so you can see my point. It will use the modified workflow that I tried to explain in my previous email.

There is the proposal (not commited because it use Java 5 features).

* No ObjectCacheEntry.

* Less objects keep around (no Lock objects retained after
  the cached object creation).

* Less locking than the original DefaultObjectCache
  during read operation.

I have not tested; it is just in order to show my point.

Your previous emails suggest that you think that I didn't understood your goals. I believe that I understood your goals from the begining, but that I have been unable to explain why I believe that a ReadWriteLock in ObjectCacheEntry is an unneeded overhead for your goals. Please read again my "modified workflow" in my yesterday email, and I would appreciate if you can point me a flaw in this workflow regarding your goals.

        Martin
/*
 *    GeoTools - OpenSource mapping toolkit
 *    http://geotools.org
 *    (C) 2007, GeoTools Project Managment Committee (PMC)
 *   
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation;
 *    version 2.1 of the License.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 */
package org.geotools.util;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;


/**
 * Caching implementation for [EMAIL PROTECTED] ObjectCache}. This instance is used when
 * actual caching is desired.
 * 
 * 
 * @author Cory Horner (Refractions Research)
 * @author Martin Desruisseaux (Geomatys)
 * @version $Id: DefaultObjectCache2.java 26114 2007-07-01 21:37:35Z desruisseaux $
 * @since 2.4
 * @source $URL: http://svn.geotools.org/geotools/trunk/gt/modules/library/metadata/src/main/java/org/geotools/util/DefaultObjectCache2.java $
 */
final class DefaultObjectCache2<K,V> {
    /**
     * The cached values for each key.
     */
    private final Map<K,V> cache;

    /**
     * The locks for some keys.
     */
    private final Map<K,ReentrantLock> locks;

    /**
     * Creates a new cache.
     */
    public DefaultObjectCache2() {
        cache = new ConcurrentHashMap<K,V>();
        locks = new HashMap<K,ReentrantLock>();
    }

    /**
     * Creates a new cache using the indicated initialSize.
     */
    public DefaultObjectCache2(final int initialSize) {
        cache = new ConcurrentHashMap<K,V>(initialSize);
        locks = new HashMap<K,ReentrantLock>(); // Do not use initialSize, because this map will be smaller.
    }

    /**
     * Removes all entries from this map.
     */
    public void clear() {
        cache.clear();
        // Do not clear the locks map, since some locks may still in use.
    }

    /**
     * Returns the object from the cache.
     * The contents (of course) may be null.
     */
    public V get(final K key) {
        return cache.get(key);
    }

    /**
     * Acquires the lock for the given key. This method will block if
     * an other thread already hold the lock.
     */
    public void lock(final K key) {
        ReentrantLock lock;
        synchronized (locks) {
            lock = locks.get(key);
            if (lock == null) {
                lock = new ReentrantLock();
                locks.put(key, lock);
            }
        }
        lock.lock(); // Must be outside the above synchronized section, since this call may block.
    }

    /**
     * Releases the lock for the given key.
     *
     * @throws IllegalMonitorStateException If the current thread does not hold this lock.
     */
    public void unlock(final K key) throws IllegalMonitorStateException {
        synchronized (locks) {
            final ReentrantLock lock = locks.get(key);
            if (lock == null) {
                throw new IllegalMonitorStateException("Cannot unlock prior to locking");
            }
            lock.unlock();
            if (!lock.isLocked()) {
                locks.remove(key);
            }
        }
    }

    /**
     * Returns [EMAIL PROTECTED] true} if the current thread holds the lock for the given key.
     * This is used mostly for debugging purpose.
     */
    public boolean holdsLock(final K key) {
        synchronized (locks) {
            final ReentrantLock lock = locks.get(key);
            if (lock != null) {
                return lock.isHeldByCurrentThread();
            }
        }
        return false;
    }

    /**
     * Stores a value. The current thread should holds the lock for that key.
     */
    public void put(final K key, final V value) {
        assert holdsLock(key) : key;
        cache.put(key, value);
    }
}
package org.geotools.util;

import org.opengis.referencing.FactoryException;
import org.opengis.referencing.IdentifiedObject;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

public class Example {
    private final DefaultObjectCache2<String, IdentifiedObject> cache = new DefaultObjectCache2<String,IdentifiedObject>();

    public CoordinateReferenceSystem createCoordinateReferenceSystem(String key) throws FactoryException {
        CoordinateReferenceSystem crs = (CoordinateReferenceSystem) cache.get(key);
        if (crs == null) {
            try {
                cache.lock(key);
                /*
                 * The line below way look like "Double-checked locking", which is a deprecated idiom:
                 *
                 *     http://www.ibm.com/developerworks/library/j-dcl.html
                 *
                 * However in the DefaultObjectCache2 case, we are not getting or setting a field.
                 * The 'get' method is invoked (indirectly) on a ConcurrentHashMap, which provides
                 * the needed garantees.
                 */
                crs = (CoordinateReferenceSystem) cache.get(key);
                if (crs == null) {
                    //crs = generateCoordinateReferenceSystem(key);
                    cache.put(key, crs);
                }
            } finally {
                cache.unlock(key);
            }
        }
        return crs;
    }
}
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Geotools-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geotools-devel

Reply via email to