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