34 messages in org.codehaus.groovy.devRe: [groovy-dev] Re: [groovy-user] Me...
FromSent OnAttachments
Alex TkachmanOct 16, 2008 2:30 pm 
Alex TkachmanOct 16, 2008 3:17 pm 
Jochen TheodorouOct 16, 2008 3:49 pm 
Tim QuinnOct 16, 2008 4:15 pm 
Alexander VeitOct 16, 2008 4:34 pm 
Jochen TheodorouOct 16, 2008 4:43 pm 
Tim QuinnOct 16, 2008 5:28 pm 
Jochen TheodorouOct 17, 2008 6:35 am 
Alex TkachmanOct 17, 2008 6:44 am 
Graeme RocherOct 17, 2008 6:54 am 
Jochen TheodorouOct 17, 2008 7:05 am 
Graeme RocherOct 17, 2008 7:14 am 
alex...@gmail.comOct 17, 2008 7:30 am 
Jochen TheodorouOct 17, 2008 7:36 am 
Alex TkachmanOct 17, 2008 9:51 am 
Jochen TheodorouOct 22, 2008 5:27 am 
Alex TkachmanOct 22, 2008 5:37 am 
Jochen TheodorouOct 22, 2008 6:05 am 
Alex TkachmanOct 22, 2008 6:08 am 
Jochen TheodorouOct 22, 2008 6:18 am.zip
Alex TkachmanOct 22, 2008 6:32 am 
Jochen TheodorouOct 22, 2008 7:06 am 
Guillaume LaforgeOct 22, 2008 7:08 am 
Alex TkachmanOct 22, 2008 7:11 am 
Guillaume LaforgeOct 22, 2008 7:21 am 
Jochen TheodorouOct 22, 2008 7:22 am 
Jochen TheodorouOct 22, 2008 7:39 am 
Jochen TheodorouOct 22, 2008 7:41 am 
Alex TkachmanOct 22, 2008 9:16 am 
Jochen TheodorouOct 22, 2008 10:11 am 
Jochen TheodorouOct 22, 2008 11:24 am 
Alex TkachmanOct 22, 2008 11:48 am 
Jochen TheodorouOct 22, 2008 2:07 pm 
Jochen TheodorouDec 22, 2008 12:52 pm 
Actions with this message:
Paste this link in email or IM:
Paste this link in email or IM:
Atom feed for this thread
Paste this URL into your reader:
Subject:Re: [groovy-dev] Re: [groovy-user] Memory leaks in GroovyActions...
From:Alex Tkachman (alex@gmail.com)
Date:Oct 22, 2008 6:08:13 am
List:org.codehaus.groovy.dev

Could you please attached patch file? And I will be able to have a look only at night

On Wed, Oct 22, 2008 at 5:05 PM, Jochen Theodorou <blac@gmx.org> wrote:

Alex Tkachman schrieb:

If you would like (think it will help) I can review the code before you commit.

well, sure, but it is of course a big patch. I attached the svn diff output in src to this post. the strong meta class tracking is atm commented out

hope this works for you

bye blackdrag

-- Jochen "blackdrag" Theodorou The Groovy Project Tech Lead (http://groovy.codehaus.org) http://blackdragsview.blogspot.com/ http://www.g2one.com/

Index: test/org/codehaus/groovy/reflection/WeakMapTest.groovy =================================================================== --- test/org/codehaus/groovy/reflection/WeakMapTest.groovy (Revision 13791) +++ test/org/codehaus/groovy/reflection/WeakMapTest.groovy (Arbeitskopie) @@ -27,8 +27,7 @@ if (i % 50 == 0) shell = null System.gc () - println "${i} ${ReflectionCache.assignableMap.size()} ${ReflectionCache.assignableMap.fullSize()} ${ClassInfo.size()} ${ClassInfo.fullSize()}" - } + }

if (shell != null) shell.classLoader.clearCache() Index: main/groovy/ui/Console.groovy =================================================================== --- main/groovy/ui/Console.groovy (Revision 13791) +++ main/groovy/ui/Console.groovy (Arbeitskopie) @@ -216,7 +216,7 @@

bindResults()

- // stitch some actions togeather + // stitch some actions together swing.bind(source:swing.inputEditor.undoAction, sourceProperty:'enabled', target:swing.undoAction, targetProperty:'enabled') swing.bind(source:swing.inputEditor.redoAction, sourceProperty:'enabled', target:swing.redoAction, targetProperty:'enabled')

Index: main/org/codehaus/groovy/runtime/metaclass/ThreadManagedMetaBeanProperty.java ===================================================================

--- main/org/codehaus/groovy/runtime/metaclass/ThreadManagedMetaBeanProperty.java (Revision 13791) +++ main/org/codehaus/groovy/runtime/metaclass/ThreadManagedMetaBeanProperty.java (Arbeitskopie) @@ -21,8 +21,12 @@ import groovy.lang.MetaMethod; import org.codehaus.groovy.reflection.CachedClass; import org.codehaus.groovy.reflection.ReflectionCache; -import org.codehaus.groovy.util.ConcurrentWeakMap; +import org.codehaus.groovy.util.ManagedConcurrentMap; +import org.codehaus.groovy.util.ReferenceManager; +import org.codehaus.groovy.util.ReferenceType; +import org.codehaus.groovy.util.ManagedReference.ReferenceBundle;

+import java.lang.ref.ReferenceQueue; import java.lang.reflect.Modifier; import java.util.concurrent.ConcurrentHashMap;

@@ -40,15 +44,23 @@ */ public class ThreadManagedMetaBeanProperty extends MetaBeanProperty { private static final CachedClass[] ZERO_ARGUMENT_LIST = new CachedClass[0]; - private static final ConcurrentHashMap<String,ConcurrentWeakMap> propName2Map = new ConcurrentHashMap<String, ConcurrentWeakMap>(); + private static final ConcurrentHashMap<String,ManagedConcurrentMap> propName2Map = new ConcurrentHashMap<String, ManagedConcurrentMap>();

- private final ConcurrentWeakMap instance2Prop; + private final ManagedConcurrentMap instance2Prop;

private Class declaringClass; private ThreadBoundGetter getter; private ThreadBoundSetter setter; private Object initialValue; private Closure initialValueCreator; + + private final static ReferenceBundle softBundle; + static { + ReferenceQueue queue = new ReferenceQueue(); + ReferenceManager callBack = ReferenceManager.createCallBackedManager(queue); + ReferenceManager manager = ReferenceManager.createThresholdedIdlingManager(queue, callBack, 200); + softBundle = new ReferenceBundle(manager, ReferenceType.SOFT); + }

/** * Retrieves the initial value of the ThreadBound property @@ -116,11 +128,11 @@ instance2Prop = getInstance2PropName(name); }

- private static ConcurrentWeakMap getInstance2PropName(String name) { - ConcurrentWeakMap res = propName2Map.get(name); + private static ManagedConcurrentMap getInstance2PropName(String name) { + ManagedConcurrentMap res = propName2Map.get(name); if (res == null) { - res = new ConcurrentWeakMap(); - ConcurrentWeakMap ores = propName2Map.putIfAbsent(name, res); + res = new ManagedConcurrentMap(softBundle); + ManagedConcurrentMap ores = propName2Map.putIfAbsent(name, res); if (ores != null) return ores; } @@ -177,7 +189,7 @@ * @see groovy.lang.MetaMethod#invoke(java.lang.Object, java.lang.Object[]) */ public Object invoke(Object object, Object[] arguments) { - return ((ConcurrentWeakMap.EntryWithValue)instance2Prop.getOrPut(object, getInitialValue())).getValue(); + return ((ManagedConcurrentMap.EntryWithValue)instance2Prop.getOrPut(object, getInitialValue())).getValue(); } }

Index: main/org/codehaus/groovy/runtime/metaclass/MetaClassRegistryImpl.java =================================================================== --- main/org/codehaus/groovy/runtime/metaclass/MetaClassRegistryImpl.java (Revision 13791) +++ main/org/codehaus/groovy/runtime/metaclass/MetaClassRegistryImpl.java (Arbeitskopie) @@ -23,8 +23,6 @@ import org.codehaus.groovy.vmplugin.VMPluginFactory; import org.codehaus.groovy.util.FastArray;

-import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -32,7 +30,6 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger;

/** * A registry of MetaClass instances which caches introspection & @@ -55,7 +52,7 @@

private LinkedList changeListenerList = new LinkedList(); private LinkedList metaClassInfo = new LinkedList(); - private ReferenceQueue queue = new ReferenceQueue(); + //TODO: private ReferenceQueue queue = new ReferenceQueue();

public static final int LOAD_DEFAULT = 0; public static final int DONT_LOAD_DEFAULT = 1; @@ -109,9 +106,9 @@

addMetaClassRegistryChangeEventListener(new MetaClassRegistryChangeEventListener(){ public void updateConstantMetaClass(MetaClassRegistryChangeEvent cmcu) { - synchronized (metaClassInfo) { - metaClassInfo.add(new WeakReference(cmcu.getNewMetaClass(),queue)); - } +//TODO: synchronized (metaClassInfo) { +// metaClassInfo.add(new WeakReference(cmcu.getNewMetaClass(),queue)); +// } } }); } @@ -138,7 +135,7 @@ CachedMethod[] methods = ReflectionCache.getCachedClass(theClass).getMethods();

if (useMethodrapper) { - // Here we instanciate objects representing MetaMethods for DGM methods. + // Here we instantiate objects representing MetaMethods for DGM methods. // Calls for such meta methods done without reflection, so more effectively. // It gives 7-8% improvement for benchmarks involving just several ariphmetic operations for (int i = 0; ; ++i) { @@ -225,7 +222,7 @@ info.unlock(); }

- if (oldMc==mc) fireConstantMetaClassUpdate(theClass,newMc); + if (oldMc!=mc) fireConstantMetaClassUpdate(theClass,newMc); }

public void removeMetaClass(Class theClass) { @@ -314,21 +311,21 @@

private void cleanMetaClassList() { - boolean hasCollectedEntries=false; - java.lang.ref.Reference r=null; - while ((r=queue.poll())!=null) { - r.clear(); - hasCollectedEntries=true; - } - - if (!hasCollectedEntries) return; - - for (Iterator it = metaClassInfo.iterator(); it.hasNext();) { - WeakReference ref = (WeakReference) it.next(); - if (ref.get()!=null) continue; - it.remove(); - ref.clear(); - } +//TODO: boolean hasCollectedEntries=false; +// java.lang.ref.Reference r=null; +// while ((r=queue.poll())!=null) { +// r.clear(); +// hasCollectedEntries=true; +// } +// +// if (!hasCollectedEntries) return; +// +// for (Iterator it = metaClassInfo.iterator(); it.hasNext();) { +// WeakReference ref = (WeakReference) it.next(); +// if (ref.get()!=null) continue; +// it.remove(); +// ref.clear(); +// } }

/** @@ -395,55 +392,56 @@ * @return the iterator. */ public Iterator iterator() { - final WeakReference[] refs; - synchronized (metaClassInfo) { - cleanMetaClassList(); - refs = (WeakReference[]) metaClassInfo.toArray(new WeakReference[0]); - } - - return new Iterator() { - // index inn the ref array - private int index=0; - // the current meta class - private MetaClass currentMeta; - // used to ensure that hasNext has been called - private boolean hasNextCalled=false; - // the cached hasNext call value - private boolean hasNext=false; - - public boolean hasNext() { - if (hasNextCalled) return hasNext; - hasNextCalled = true; - hasNext=true; - - // currentMeta==null means the entry might have been - // collected already, we skip these. - currentMeta=null; - while (currentMeta==null && index<refs.length) { - currentMeta = (MetaClass) refs[index].get(); - index++; - } - hasNext=currentMeta!=null; - return hasNext; - } - - private void ensureNext() { - // we ensure that hasNext has been called before - // next is called - hasNext(); - hasNextCalled=false; - } - - public Object next() { - ensureNext(); - return currentMeta; - } - - public void remove() { - ensureNext(); - setMetaClass(currentMeta.getTheClass(),currentMeta,null); - currentMeta=null; - } - }; + return null; +//TODO: final WeakReference[] refs; +// synchronized (metaClassInfo) { +// cleanMetaClassList(); +// refs = (WeakReference[]) metaClassInfo.toArray(new WeakReference[0]); +// } +// +// return new Iterator() { +// // index inn the ref array +// private int index=0; +// // the current meta class +// private MetaClass currentMeta; +// // used to ensure that hasNext has been called +// private boolean hasNextCalled=false; +// // the cached hasNext call value +// private boolean hasNext=false; +// +// public boolean hasNext() { +// if (hasNextCalled) return hasNext; +// hasNextCalled = true; +// hasNext=true; +// +// // currentMeta==null means the entry might have been +// // collected already, we skip these. +// currentMeta=null; +// while (currentMeta==null && index<refs.length) { +// currentMeta = (MetaClass) refs[index].get(); +// index++; +// } +// hasNext=currentMeta!=null; +// return hasNext; +// } +// +// private void ensureNext() { +// // we ensure that hasNext has been called before +// // next is called +// hasNext(); +// hasNextCalled=false; +// } +// +// public Object next() { +// ensureNext(); +// return currentMeta; +// } +// +// public void remove() { +// ensureNext(); +// setMetaClass(currentMeta.getTheClass(),currentMeta,null); +// currentMeta=null; +// } +// }; } } Index: main/org/codehaus/groovy/reflection/MixinInMetaClass.java =================================================================== --- main/org/codehaus/groovy/reflection/MixinInMetaClass.java (Revision 13791) +++ main/org/codehaus/groovy/reflection/MixinInMetaClass.java (Arbeitskopie) @@ -3,6 +3,7 @@ import groovy.lang.*;

import java.lang.reflect.Modifier; +import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.WeakHashMap; import java.util.List; @@ -17,14 +18,26 @@ import org.codehaus.groovy.runtime.metaclass.MixedInMetaClass; import org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod; import org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaProperty; -import org.codehaus.groovy.util.ConcurrentWeakMap; +import org.codehaus.groovy.util.ManagedConcurrentMap; +import org.codehaus.groovy.util.ReferenceManager; +import org.codehaus.groovy.util.ReferenceType; +import org.codehaus.groovy.util.ManagedReference.ReferenceBundle;

-public class MixinInMetaClass extends ConcurrentWeakMap { +public class MixinInMetaClass extends ManagedConcurrentMap { final ExpandoMetaClass emc; final CachedClass mixinClass; final CachedConstructor constructor;

+ private static ReferenceBundle softBundle; + static { + ReferenceQueue queue = new ReferenceQueue(); + ReferenceManager callBack = ReferenceManager.createCallBackedManager(queue); + ReferenceManager manager = ReferenceManager.createThresholdedIdlingManager(queue, callBack, 200); + softBundle = new ReferenceBundle(manager, ReferenceType.SOFT); + } + public MixinInMetaClass(ExpandoMetaClass emc, CachedClass mixinClass) { + super(softBundle); this.emc = emc; this.mixinClass = mixinClass;

Index: main/org/codehaus/groovy/reflection/ReflectionCache.java =================================================================== --- main/org/codehaus/groovy/reflection/ReflectionCache.java (Revision 13791) +++ main/org/codehaus/groovy/reflection/ReflectionCache.java (Arbeitskopie) @@ -16,7 +16,6 @@ package org.codehaus.groovy.reflection;

import org.codehaus.groovy.util.TripleKeyHashMap; -import org.codehaus.groovy.util.SoftDoubleKeyMap;

import java.util.HashMap; import java.util.Map; @@ -49,9 +48,7 @@ } return (String) mopNameEntry.value; } - - static SoftDoubleKeyMap assignableMap = new SoftDoubleKeyMap(); - + static final CachedClass STRING_CLASS = getCachedClass(String.class);

public static boolean isArray(Class klazz) { Index: main/org/codehaus/groovy/reflection/ClassInfo.java =================================================================== --- main/org/codehaus/groovy/reflection/ClassInfo.java (Revision 13791) +++ main/org/codehaus/groovy/reflection/ClassInfo.java (Arbeitskopie) @@ -19,6 +19,7 @@ import org.codehaus.groovy.reflection.stdclasses.*; import org.codehaus.groovy.util.*;

+import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.math.BigDecimal; import java.math.BigInteger; @@ -30,38 +31,44 @@ * * @author Alex.Tkachman */ -public class ClassInfo extends ConcurrentSoftMap.Entry<Class,ClassInfo> { +public class ClassInfo extends ManagedConcurrentMap.Entry<Class,ClassInfo> {

+ private static final HashSet<ClassInfo> modifiedExpandos = new HashSet<ClassInfo>(); + private final LazyCachedClassRef cachedClassRef; + private final LazyClassLoaderRef artifactClassLoader; + private final LockableObject lock = new LockableObject(); + public final int hash;

+ private volatile int version; + private MetaClass strongMetaClass; - private SoftReference<MetaClass> weakMetaClass; - - private volatile int version; - - private final LazyClassLoaderRef artifactClassLoader; - - private static final HashSet<ClassInfo> modifiedExpandos = new HashSet<ClassInfo>(); - - private final LockableObject lock = new LockableObject(); - MetaMethod[] dgmMetaMethods = CachedClass.EMPTY; - MetaMethod[] newMetaMethods = CachedClass.EMPTY; + private ManagedConcurrentMap perInstanceMetaClassMap; + + private final static ReferenceBundle softBundle; + private final static ReferenceBundle perInstanceBundle; + static { + ReferenceQueue queue = new ReferenceQueue(); + ReferenceManager callBack = ReferenceManager.createCallBackedManager(queue); + ReferenceManager manager = ReferenceManager.createThresholdedIdlingManager(queue, callBack, 500); + softBundle = new ReferenceBundle(manager, ReferenceType.SOFT); + perInstanceBundle = new ReferenceBundle(manager, ReferenceType.WEAK); + } + private static final ClassInfoSet globalClassSet = new ClassInfoSet(softBundle); +

- public final int hash; - private ConcurrentWeakMap perInstanceMetaClassMap; + ClassInfo(ManagedConcurrentMap.Segment segment, Class klazz, int hash) { + super (softBundle, segment, klazz, hash);

- ClassInfo(ConcurrentSoftMap.Segment segment, Class klazz, int hash) { - super (segment, klazz, hash); - if (ClassInfo.DebugRef.debug) new DebugRef(klazz);

this.hash = hash; - cachedClassRef = new LazyCachedClassRef(this); - artifactClassLoader = new LazyClassLoaderRef(this); + cachedClassRef = new LazyCachedClassRef(softBundle, this); + artifactClassLoader = new LazyClassLoaderRef(softBundle, this); }

public int getVersion() { @@ -88,8 +95,6 @@ return artifactClassLoader.get(); }

- private static final ClassInfoSet globalClassSet = new ClassInfoSet(); - public static ClassInfo getClassInfo (Class cls) { return localMap.get().get(cls); } @@ -188,8 +193,8 @@

public void finalizeRef() { setStrongMetaClass(null); - cachedClassRef.set(null); - artifactClassLoader.set(null); + cachedClassRef.clear(); + artifactClassLoader.clear();

super.finalizeRef(); } @@ -264,7 +269,7 @@

if (metaClass != null) { if (perInstanceMetaClassMap == null) - perInstanceMetaClassMap = new ConcurrentWeakMap (); + perInstanceMetaClassMap = new ManagedConcurrentMap(perInstanceBundle);

perInstanceMetaClassMap.put(obj, metaClass); } @@ -279,18 +284,21 @@ return perInstanceMetaClassMap != null; }

- public static class ClassInfoSet extends ConcurrentSoftMap<Class,ClassInfo> { - - public ClassInfoSet() { + public static class ClassInfoSet extends ManagedConcurrentMap<Class,ClassInfo> { + public ClassInfoSet(ReferenceBundle bundle) { + super(bundle); }

- protected Segment createSegment(int cap) { - return new Segment(cap); + protected Segment createSegment(Object segmentInfo, int cap) { + ReferenceBundle bundle = (ReferenceBundle) segmentInfo; + if (bundle==null) throw new IllegalArgumentException("bundle must not be null "); + + return new Segment(bundle, cap); }

- static final class Segment extends ConcurrentSoftMap.Segment<Class,ClassInfo> { - Segment(int initialCapacity) { - super(initialCapacity); + static final class Segment extends ManagedConcurrentMap.Segment<Class,ClassInfo> { + Segment(ReferenceBundle bundle, int initialCapacity) { + super(bundle, initialCapacity); }

protected ClassInfo createEntry(Class key, int hash, ClassInfo unused) { @@ -371,10 +379,11 @@ } };

- private static class LazyCachedClassRef extends LazySoftReference<CachedClass> { + private static class LazyCachedClassRef extends LazyReference<CachedClass> { private final ClassInfo info;

- LazyCachedClassRef(ClassInfo info) { + LazyCachedClassRef(ReferenceBundle bundle, ClassInfo info) { + super(bundle); this.info = info; }

@@ -383,10 +392,11 @@ } }

- private static class LazyClassLoaderRef extends LazySoftReference<ClassLoaderForClassArtifacts> { + private static class LazyClassLoaderRef extends LazyReference<ClassLoaderForClassArtifacts> { private final ClassInfo info;

- LazyClassLoaderRef(ClassInfo info) { + LazyClassLoaderRef(ReferenceBundle bundle, ClassInfo info) { + super(bundle); this.info = info; }

@@ -395,7 +405,7 @@ } }

- private static class DebugRef extends FinalizableRef.DebugRef<Class> { + private static class DebugRef extends ManagedReference<Class> { public final static boolean debug = false;

private static final AtomicInteger count = new AtomicInteger(); @@ -403,14 +413,14 @@ final String name;

public DebugRef(Class klazz) { - super(klazz); + super(softBundle, klazz); name = klazz == null ? "<null>" : klazz.getName(); count.incrementAndGet(); }

public void finalizeRef() { System.out.println(name + " unloaded " + count.decrementAndGet() + " classes kept"); - super.finalizeRef(); + super.finalizeReference(); } } } Index: main/org/codehaus/groovy/reflection/CachedClass.java =================================================================== --- main/org/codehaus/groovy/reflection/CachedClass.java (Revision 13791) +++ main/org/codehaus/groovy/reflection/CachedClass.java (Arbeitskopie) @@ -18,10 +18,13 @@ import groovy.lang.*; import org.codehaus.groovy.classgen.BytecodeHelper; import org.codehaus.groovy.runtime.callsite.CallSiteClassLoader; -import org.codehaus.groovy.util.LazySoftReference; import org.codehaus.groovy.util.LazyReference; import org.codehaus.groovy.util.FastArray; +import org.codehaus.groovy.util.ReferenceManager; +import org.codehaus.groovy.util.ReferenceType; +import org.codehaus.groovy.util.ManagedReference.ReferenceBundle;

+import java.lang.ref.ReferenceQueue; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -36,8 +39,16 @@ public class CachedClass { private final Class cachedClass; public ClassInfo classInfo; + + private static ReferenceBundle softBundle; + static { + ReferenceQueue queue = new ReferenceQueue(); + ReferenceManager callBack = ReferenceManager.createCallBackedManager(queue); + ReferenceManager manager = ReferenceManager.createThresholdedIdlingManager(queue, callBack, 500); + softBundle = new ReferenceBundle(manager, ReferenceType.SOFT); + }

- private final LazySoftReference<CachedField[]> fields = new LazySoftReference<CachedField[]>() { + private final LazyReference<CachedField[]> fields = new LazyReference<CachedField[]>(softBundle) { public CachedField[] initValue() { final Field[] declaredFields = (Field[]) AccessController.doPrivileged(new PrivilegedAction/*<Field[]>*/() { @@ -54,7 +65,7 @@ } };

- private LazySoftReference<CachedConstructor[]> constructors = new LazySoftReference<CachedConstructor[]>() { + private LazyReference<CachedConstructor[]> constructors = new LazyReference<CachedConstructor[]>(softBundle) { public CachedConstructor[] initValue() { final Constructor[] declaredConstructors = (Constructor[]) AccessController.doPrivileged(new PrivilegedAction/*<Constructor[]>*/() { @@ -69,7 +80,7 @@ } };

- private LazySoftReference<CachedMethod[]> methods = new LazySoftReference<CachedMethod[]>() { + private LazyReference<CachedMethod[]> methods = new LazyReference<CachedMethod[]>(softBundle) { public CachedMethod[] initValue() { final Method[] declaredMethods = (Method[]) AccessController.doPrivileged(new PrivilegedAction/*<Method[]>*/() { @@ -114,7 +125,8 @@ } };

- private LazyReference<CachedClass> cachedSuperClass = new LazyReference<CachedClass>() { + /* nicht SOFT xxx */ + private LazyReference<CachedClass> cachedSuperClass = new LazyReference<CachedClass>(softBundle) { public CachedClass initValue() { if (!isArray) return ReflectionCache.getCachedClass(getTheClass().getSuperclass()); @@ -126,7 +138,7 @@ } };

- private final LazySoftReference<CallSiteClassLoader> callSiteClassLoader = new LazySoftReference<CallSiteClassLoader>() { + private final LazyReference<CallSiteClassLoader> callSiteClassLoader = new LazyReference<CallSiteClassLoader>(softBundle) { public CallSiteClassLoader initValue() { return AccessController.doPrivileged(new PrivilegedAction<CallSiteClassLoader>() { @@ -144,7 +156,8 @@ public CachedMethod [] mopMethods; public static final CachedClass[] EMPTY_ARRAY = new CachedClass[0];

- private final LazyReference<Set<CachedClass>> declaredInterfaces = new LazyReference<Set<CachedClass>> () { + /* nicht SOFT xxx */ + private final LazyReference<Set<CachedClass>> declaredInterfaces = new LazyReference<Set<CachedClass>> (softBundle) { public Set<CachedClass> initValue() { HashSet<CachedClass> res = new HashSet<CachedClass> (0);

@@ -156,7 +169,7 @@ } };

- private final LazySoftReference<Set<CachedClass>> interfaces = new LazySoftReference<Set<CachedClass>> () { + private final LazyReference<Set<CachedClass>> interfaces = new LazyReference<Set<CachedClass>> (softBundle) { public Set<CachedClass> initValue() { HashSet<CachedClass> res = new HashSet<CachedClass> (0);

Index: main/org/codehaus/groovy/util/AbstractConcurrentMapBase.java =================================================================== --- main/org/codehaus/groovy/util/AbstractConcurrentMapBase.java (Revision 13791) +++ main/org/codehaus/groovy/util/AbstractConcurrentMapBase.java (Arbeitskopie) @@ -8,7 +8,7 @@ final int segmentShift; protected final Segment[] segments;

- public AbstractConcurrentMapBase() { + public AbstractConcurrentMapBase(Object segmentInfo) { int sshift = 0; int ssize = 1; while (ssize < 16) { @@ -27,10 +27,10 @@ cap <<= 1;

for (int i = 0; i < this.segments.length; ++i) - this.segments[i] = createSegment(cap); + this.segments[i] = createSegment(segmentInfo, cap); }

- protected abstract Segment createSegment(int cap); + protected abstract Segment createSegment(Object segmentInfo, int cap);

protected static <K> int hash(K key) { int h = System.identityHashCode(key); Index: main/org/codehaus/groovy/util/ReferenceType.java =================================================================== --- main/org/codehaus/groovy/util/ReferenceType.java (Revision 0) +++ main/org/codehaus/groovy/util/ReferenceType.java (Revision 0) @@ -0,0 +1,93 @@ +package org.codehaus.groovy.util; + +import java.lang.ref.PhantomReference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; + + +public enum ReferenceType { + SOFT { + @Override + protected <T,V extends Finalizable> Reference<T,V> createReference(T value, V handler, ReferenceQueue queue) { + return new SoftRef(value, handler, queue); + } + }, + WEAK { + @Override + protected <T,V extends Finalizable> Reference<T,V> createReference(T value, V handler, ReferenceQueue queue) { + return new WeakRef(value, handler, queue); + } + }, + PHANTOM { + @Override + protected <T,V extends Finalizable> Reference<T,V> createReference(T value, V handler, ReferenceQueue queue) { + return new PhantomRef(value, handler, queue); + } + }, + HARD { + @Override + protected <T,V extends Finalizable> Reference<T,V> createReference(T value, V handler, ReferenceQueue queue) { + return new HardRef(value, handler, queue); + } + }; + protected abstract <T,V extends Finalizable> Reference<T,V> createReference(T value, V handler, ReferenceQueue queue); + + private static class SoftRef<TT,V extends Finalizable> extends SoftReference<TT> implements Reference<TT,V> { + private final V handler; + public SoftRef(TT referent, V handler, ReferenceQueue<? super TT> q) { + super(referent, q); + this.handler = handler; + } + @Override + public V getHandler() { + return handler; + } + } + + private static class WeakRef<TT,V extends Finalizable> extends WeakReference<TT> implements Reference<TT,V> { + private final V handler; + public WeakRef(TT referent, V handler, ReferenceQueue<? super TT> q) { + super(referent, q); + this.handler = handler; + } + @Override + public V getHandler() { + return handler; + } + } + + private static class PhantomRef<TT,V extends Finalizable> extends PhantomReference<TT> implements Reference<TT,V> { + private final V handler; + public PhantomRef(TT referent, V handler, ReferenceQueue<? super TT> q) { + super(referent, q); + this.handler = handler; + } + @Override + public V getHandler() { + return handler; + } + } + + private static class HardRef<TT,V extends Finalizable> implements Reference<TT,V> { + private TT ref; + private final V handler; + public HardRef(TT referent, V handler, ReferenceQueue<? super TT> q) { + this.ref = referent; + this.handler = handler; + } + @Override + public V getHandler() { + return handler; + } + @Override + public TT get() { + return ref; + } + @Override + public void clear() { + ref = null; + } + } + +} Index: main/org/codehaus/groovy/util/AbstractConcurrentMap.java =================================================================== --- main/org/codehaus/groovy/util/AbstractConcurrentMap.java (Revision 13791) +++ main/org/codehaus/groovy/util/AbstractConcurrentMap.java (Arbeitskopie) @@ -1,7 +1,9 @@ package org.codehaus.groovy.util;

public abstract class AbstractConcurrentMap<K, V> extends AbstractConcurrentMapBase { - public AbstractConcurrentMap() { + + public AbstractConcurrentMap(Object segmentInfo) { + super(segmentInfo); }

public Segment segmentFor (int hash) { Index: main/org/codehaus/groovy/util/AbstractConcurrentDoubleKeyMap.java =================================================================== --- main/org/codehaus/groovy/util/AbstractConcurrentDoubleKeyMap.java (Revision 13791) +++ main/org/codehaus/groovy/util/AbstractConcurrentDoubleKeyMap.java (Arbeitskopie) @@ -1,7 +1,8 @@ package org.codehaus.groovy.util;

public abstract class AbstractConcurrentDoubleKeyMap<K1,K2,V> extends AbstractConcurrentMapBase { - public AbstractConcurrentDoubleKeyMap() { + public AbstractConcurrentDoubleKeyMap(Object segmentInfo) { + super(segmentInfo); }

static <K1,K2> int hash(K1 key1, K2 key2) { Index: main/org/codehaus/groovy/util/ManagedReference.java =================================================================== --- main/org/codehaus/groovy/util/ManagedReference.java (Revision 13791) +++ main/org/codehaus/groovy/util/ManagedReference.java (Arbeitskopie) @@ -1,127 +1,52 @@ package org.codehaus.groovy.util;

-import java.lang.ref.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.Set; -import java.util.LinkedHashSet; - -public interface FinalizableRef { - - public void finalizeRef (); - - public static abstract class SoftRef<T> extends SoftReference<T> implements FinalizableRef { - public SoftRef(T referent) { - super(referent, MyReferenceQueue.getInstance()); +/** + * + * + * @author Alex Tkachman + * @author Jochen Theodorou + */ +public class ManagedReference<T> implements Finalizable { + public static class ReferenceBundle{ + private ReferenceManager manager; + private ReferenceType type; + public ReferenceBundle(ReferenceManager manager, ReferenceType type){ + this.manager = manager; + this.type = type; } - - public String toString() { - T res = get (); - if (res == null) - return "<null>"; - else - return res.toString(); + public ReferenceType getType() { + return type; } - - public void finalizeRef () { - } + public ReferenceManager getManager() { + return manager; + } } - - public static abstract class WeakRef<T> extends WeakReference<T> implements FinalizableRef { - public WeakRef(T referent) { - super(referent, MyReferenceQueue.getInstance()); - } - - public String toString() { - T res = get (); - if (res == null) - return "<null>"; - else - return res.toString(); - } - - public void finalizeRef () { - } + + private static ReferenceManager NULL_MANAGER = new ReferenceManager(null){}; + private Reference<T,ManagedReference<T>> ref; + private ReferenceManager manager; + + public ManagedReference(ReferenceType type, ReferenceManager rmanager, T value) { + if (rmanager==null) rmanager = NULL_MANAGER; + this.manager = rmanager; + this.ref = type.createReference(value, this, rmanager.getReferenceQueue()); + rmanager.afterReferenceCreation(ref); } - - public static abstract class PhantomRef<T> extends PhantomReference<T> implements FinalizableRef { - public PhantomRef(T referent) { - super(referent, MyReferenceQueue.getInstance()); - } - - public void finalizeRef () { - } + + public ManagedReference(ReferenceBundle bundle, T value) { + this(bundle.getType(),bundle.getManager(),value); } - - /** - * Phantom reference, which will be kept alive while not finalized. - * There is no need to store this references anywhere because they will be automatically put in to internal set. - * Subclasses should overide finalizeRef () method and call super.finalizeRef () to do any additional cleanup or dyagnostic - */ - public static abstract class DebugRef<T> extends PhantomRef<T> { - private static final ConcurrentHashMap<FinalizableRef,Object> anchor = new ConcurrentHashMap<FinalizableRef,Object> (); - private static final Object ANCHOR = new Object(); - - public DebugRef(T referent) { - super(referent); - anchor.put(this, ANCHOR); - } - - public void finalizeRef () { - super.clear(); - anchor.remove(this); - } + + public final T get() { + return ref.get(); } - - public static class MyReferenceQueue extends ReferenceQueue { - private static final MyReferenceQueue finalizableQueue = new MyReferenceQueue(); - - private AtomicInteger refCnt = new AtomicInteger(); - - private AtomicReference<Thread> thread = new AtomicReference<Thread> (); - - public MyReferenceQueue() { - } - - private ReferenceQueue getMe () { - if (thread.get() == null) { - final Thread newThread = new MyThread(); - if (thread.compareAndSet(null, newThread)) { - newThread.setContextClassLoader(null); - newThread.setDaemon(true); - newThread.setName(FinalizableRef.class.getName()); - newThread.start(); - } - } - - refCnt.incrementAndGet(); - return this; - } - - public static ReferenceQueue getInstance() { - return finalizableQueue.getMe (); - } - - private class MyThread extends Thread { - public void run() { - while (true) { - try { - FinalizableRef ref = (FinalizableRef) remove(5000); - if (ref == null) { - if (refCnt.get() == 0) { - thread.compareAndSet(this, null); - return; - } - } else { - refCnt.decrementAndGet(); - ref.finalizeRef(); - } - } - catch (Throwable t) {// - } - } - } - } + + public final void clear() { + ref.clear(); + manager.removeStallEntries(); } -} + + public void finalizeReference(){ + clear(); + } +} \ No newline at end of file

Eigenschaftsänderungen: main/org/codehaus/groovy/util/ManagedReference.java

___________________________________________________________________ Hinzugefügt: svn:mergeinfo

Index: main/org/codehaus/groovy/util/ConcurrentSoftMap.java =================================================================== --- main/org/codehaus/groovy/util/ConcurrentSoftMap.java (Revision 13791) +++ main/org/codehaus/groovy/util/ConcurrentSoftMap.java (Arbeitskopie) @@ -1,78 +0,0 @@ -package org.codehaus.groovy.util; - -public class ConcurrentSoftMap<K,V> extends AbstractConcurrentMap<K,V> { - public ConcurrentSoftMap() { - } - - protected Segment<K,V> createSegment(int cap) { - return new ConcurrentSoftMap.Segment<K,V>(cap); - } - - public static class Segment<K,V> extends AbstractConcurrentMap.Segment<K,V>{ - public Segment(int cap) { - super(cap); - } - - protected AbstractConcurrentMap.Entry<K,V> createEntry(K key, int hash, V value) { - return new EntryWithValue<K,V>(this, key, hash, value); - } - } - - public static class Entry<K,V> extends FinalizableRef.SoftRef<K> implements AbstractConcurrentMap.Entry<K,V> { - private final Segment segment; - private int hash; - - public Entry(Segment segment, K key, int hash) { - super(key); - this.segment = segment; - this.hash = hash; - } - - public boolean isValid() { - return get() != null; - } - - public boolean isEqual(K key, int hash) { - return this.hash == hash && get() == key; - } - - public V getValue() { - return (V)this; - } - - public void setValue(V value) { - } - - public int getHash() { - return hash; - } - - public void finalizeRef() { - super.finalizeRef(); - segment.removeEntry(this); - } - } - - public static class EntryWithValue<K,V> extends Entry<K,V> { - private V value; - - public EntryWithValue(Segment segment, K key, int hash, V value) { - super(segment, key, hash); - setValue(value); - } - - public V getValue() { - return value; - } - - public void setValue(V value) { - this.value = value; - } - - - public void finalizeRef() { - value = null; - super.finalizeRef(); - } - } -} \ No newline at end of file Index: main/org/codehaus/groovy/util/FinalizableRef.java =================================================================== --- main/org/codehaus/groovy/util/FinalizableRef.java (Revision 13791) +++ main/org/codehaus/groovy/util/FinalizableRef.java (Arbeitskopie) @@ -1,127 +0,0 @@ -package org.codehaus.groovy.util; - -import java.lang.ref.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.Set; -import java.util.LinkedHashSet; - -public interface FinalizableRef { - - public void finalizeRef (); - - public static abstract class SoftRef<T> extends SoftReference<T> implements FinalizableRef { - public SoftRef(T referent) { - super(referent, MyReferenceQueue.getInstance()); - } - - public String toString() { - T res = get (); - if (res == null) - return "<null>"; - else - return res.toString(); - } - - public void finalizeRef () { - } - } - - public static abstract class WeakRef<T> extends WeakReference<T> implements FinalizableRef { - public WeakRef(T referent) { - super(referent, MyReferenceQueue.getInstance()); - } - - public String toString() { - T res = get (); - if (res == null) - return "<null>"; - else - return res.toString(); - } - - public void finalizeRef () { - } - } - - public static abstract class PhantomRef<T> extends PhantomReference<T> implements FinalizableRef { - public PhantomRef(T referent) { - super(referent, MyReferenceQueue.getInstance()); - } - - public void finalizeRef () { - } - } - - /** - * Phantom reference, which will be kept alive while not finalized. - * There is no need to store this references anywhere because they will be automatically put in to internal set. - * Subclasses should overide finalizeRef () method and call super.finalizeRef () to do any additional cleanup or dyagnostic - */ - public static abstract class DebugRef<T> extends PhantomRef<T> { - private static final ConcurrentHashMap<FinalizableRef,Object> anchor = new ConcurrentHashMap<FinalizableRef,Object> (); - private static final Object ANCHOR = new Object(); - - public DebugRef(T referent) { - super(referent); - anchor.put(this, ANCHOR); - } - - public void finalizeRef () { - super.clear(); - anchor.remove(this); - } - } - - public static class MyReferenceQueue extends ReferenceQueue { - private static final MyReferenceQueue finalizableQueue = new MyReferenceQueue(); - - private AtomicInteger refCnt = new AtomicInteger(); - - private AtomicReference<Thread> thread = new AtomicReference<Thread> (); - - public MyReferenceQueue() { - } - - private ReferenceQueue getMe () { - if (thread.get() == null) { - final Thread newThread = new MyThread(); - if (thread.compareAndSet(null, newThread)) { - newThread.setContextClassLoader(null); - newThread.setDaemon(true); - newThread.setName(FinalizableRef.class.getName()); - newThread.start(); - } - } - - refCnt.incrementAndGet(); - return this; - } - - public static ReferenceQueue getInstance() { - return finalizableQueue.getMe (); - } - - private class MyThread extends Thread { - public void run() { - while (true) { - try { - FinalizableRef ref = (FinalizableRef) remove(5000); - if (ref == null) { - if (refCnt.get() == 0) { - thread.compareAndSet(this, null); - return; - } - } else { - refCnt.decrementAndGet(); - ref.finalizeRef(); - } - } - catch (Throwable t) {// - } - } - } - } - } -} Index: main/org/codehaus/groovy/util/SoftDoubleKeyMap.java =================================================================== --- main/org/codehaus/groovy/util/SoftDoubleKeyMap.java (Revision 13791) +++ main/org/codehaus/groovy/util/SoftDoubleKeyMap.java (Arbeitskopie) @@ -1,108 +0,0 @@ -/* - * Copyright 2003-2007 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.codehaus.groovy.util; - -public class SoftDoubleKeyMap<K1,K2,V> extends AbstractConcurrentDoubleKeyMap<K1,K2,V> { - protected AbstractConcurrentDoubleKeyMap.Segment<K1,K2,V> createSegment(int cap) { - return new Segment<K1,K2,V>(cap); - } - - static class Segment<K1,K2,V> extends AbstractConcurrentDoubleKeyMap.Segment<K1,K2,V>{ - public Segment(int cap) { - super(cap); - } - - protected AbstractConcurrentDoubleKeyMap.Entry<K1,K2,V> createEntry(K1 key1, K2 key2, int hash) { - return new EntryWithValue(key1, key2, hash, this); - } - } - - static class Ref<K> extends FinalizableRef.SoftRef<K> { - final Entry entry; - public Ref(K referent, Entry entry) { - super(referent); - this.entry = entry; - } - - public void finalizeRef() { - this.entry.clean(); - } - - public void clear() { - super.clear(); - } - } - - public static class Entry<K1,K2, V> implements AbstractConcurrentDoubleKeyMap.Entry<K1,K2,V> { - final private int hash; - final Ref<K1> ref1; - final Ref<K2> ref2; - final Segment segment; - - public Entry(K1 key1, K2 key2, int hash, Segment segment) { - this.hash = hash; - this.segment = segment; - ref1 = new Ref(key1, this); - ref2 = new Ref(key2, this); - } - - public boolean isValid() { - return ref1.get() != null && ref2.get () != null; - } - - public boolean isEqual(K1 key1, K2 key2, int hash) { - return this.hash == hash && ref1.get() == key1 && ref2.get() == key2; - } - - public V getValue() { - return (V)this; - } - - public void setValue(V value) { - } - - public int getHash() { - return hash; - } - - public void clean() { - segment.removeEntry(this); - ref1.clear(); - ref2.clear(); - } - } - - private static class EntryWithValue<K1,K2,V> extends Entry<K1,K2,V> { - private V value; - - public EntryWithValue(K1 key1, K2 key2, int hash, Segment segment) { - super(key1, key2, hash, segment); - } - - public V getValue() { - return value; - } - - public void setValue(V value) { - this.value = value; - } - - public void clean() { - super.clean(); - value = null; - } - } -} Index: main/org/codehaus/groovy/util/Finalizable.java =================================================================== --- main/org/codehaus/groovy/util/Finalizable.java (Revision 0) +++ main/org/codehaus/groovy/util/Finalizable.java (Revision 0) @@ -0,0 +1,5 @@ +package org.codehaus.groovy.util; + +public interface Finalizable { + public void finalizeReference(); +} Index: main/org/codehaus/groovy/util/ConcurrentWeakMap.java =================================================================== --- main/org/codehaus/groovy/util/ConcurrentWeakMap.java (Revision 13791) +++ main/org/codehaus/groovy/util/ConcurrentWeakMap.java (Arbeitskopie) @@ -1,78 +0,0 @@ -package org.codehaus.groovy.util; - -public class ConcurrentWeakMap<K,V> extends AbstractConcurrentMap<K,V> { - public ConcurrentWeakMap() { - } - - protected Segment<K,V> createSegment(int cap) { - return new ConcurrentWeakMap.Segment<K,V>(this, cap); - } - - public static class Segment<K,V> extends AbstractConcurrentMap.Segment<K,V>{ - public Segment(ConcurrentWeakMap<K,V> map, int cap) { - super(cap); - } - - protected AbstractConcurrentMap.Entry<K,V> createEntry(K key, int hash, V value) { - return new EntryWithValue<K,V>(this, key, hash, value); - } - } - - public static class Entry<K,V> extends FinalizableRef.WeakRef<K> implements AbstractConcurrentMap.Entry<K,V> { - private final Segment segment; - private int hash; - - public Entry(Segment segment, K key, int hash) { - super(key); - this.segment = segment; - this.hash = hash; - } - - public boolean isValid() { - return get() != null; - } - - public boolean isEqual(K key, int hash) { - return this.hash == hash && get() == key; - } - - public V getValue() { - return (V)this; - } - - public void setValue(V value) { - } - - public int getHash() { - return hash; - } - - public void finalizeRef() { - super.finalizeRef(); - segment.removeEntry(this); - } - } - - public static class EntryWithValue<K,V> extends Entry<K,V> { - private V value; - - public EntryWithValue(Segment segment, K key, int hash, V value) { - super(segment, key, hash); - setValue(value); - } - - public V getValue() { - return value; - } - - public void setValue(V value) { - this.value = value; - } - - - public void finalizeRef() { - value = null; - super.finalizeRef(); - } - } -} \ No newline at end of file Index: main/org/codehaus/groovy/util/ReferenceManager.java =================================================================== --- main/org/codehaus/groovy/util/ReferenceManager.java (Revision 0) +++ main/org/codehaus/groovy/util/ReferenceManager.java (Revision 0) @@ -0,0 +1,132 @@ +package org.codehaus.groovy.util; + +import java.lang.ref.ReferenceQueue; +import java.util.concurrent.atomic.AtomicInteger; + +public class ReferenceManager { + private static class ThreadedReferenceManager extends ReferenceManager { + private final Thread thread; + private volatile boolean shouldRun = true; + public ThreadedReferenceManager(ReferenceQueue queue) { + super(queue); + thread = new Thread() { + public void run() { + ReferenceQueue queue = getReferenceQueue(); + java.lang.ref.Reference r=null; + while (shouldRun) { + try { + r = queue.remove(1000); + } catch (InterruptedException e) { + break; + } + if (r==null) continue; + + if (r instanceof Reference) { + Reference ref = (Reference) r; + Finalizable holder = ref.getHandler(); + if (holder!=null) holder.finalizeReference(); + } + r.clear(); + r=null; + } + } + }; + thread.setContextClassLoader(null); + thread.setDaemon(true); + thread.setName(ThreadedReferenceManager.class.getName()); + thread.start(); + } + @Override + public void stopThread() { + shouldRun = false; + thread.interrupt(); + } + @Override + public String toString() { + return "ReferenceManager(threaded, thread="+thread+")"; + } + } + + public static ReferenceManager createThreadedManager(ReferenceQueue queue) { + return new ThreadedReferenceManager(queue); + } + public static ReferenceManager createIdlingManager(ReferenceQueue queue) { + return new ReferenceManager(queue); + } + public static ReferenceManager createCallBackedManager(ReferenceQueue queue) { + return new ReferenceManager(queue){ + @Override + public void removeStallEntries() { + ReferenceQueue queue = getReferenceQueue(); + for(;;) { + java.lang.ref.Reference r = queue.poll(); + if (r==null) break; + + if (r instanceof Reference) { + Reference ref = (Reference) r; + Finalizable holder = ref.getHandler(); + if (holder!=null) holder.finalizeReference(); + } + r.clear(); + r=null; + } + } + @Override + public void afterReferenceCreation(Reference r) { + removeStallEntries(); + } + @Override + public String toString() { + return "ReferenceManager(callback)"; + } + }; + } + public static ReferenceManager createThresholdedIdlingManager(final ReferenceQueue queue, final ReferenceManager callback, final int threshold) { + if (threshold<0) throw new IllegalArgumentException("threshold must not be below 0."); + + return new ReferenceManager(queue){ + private AtomicInteger refCnt = new AtomicInteger(); + private volatile ReferenceManager manager = createIdlingManager(queue); + @Override + public void afterReferenceCreation(Reference r) { + if (manager==callback) { + callback.afterReferenceCreation(r); + return; + } + // we use the idle manager, so let us use the reference counter + // we change the manager once the threshold is reached. There is + // a small chance that the value will go beyond Integer.MAX_VALUe + // so we check for values below 0 too. If threshold is low, then + // this is unlikely to happen. If threshold is high, then we + // have all negative values as fall back + int count = refCnt.incrementAndGet(); + if (count>threshold || count<0) { + manager = callback; + } + } + @Override + public String toString() { + return "ReferenceManager(thresholded, current manager="+manager+", threshold="+refCnt.get()+"/"+threshold+")"; + } + }; + } + + private ReferenceQueue queue; + + public ReferenceManager(ReferenceQueue queue) { + this.queue = queue; + } + + protected ReferenceQueue getReferenceQueue() { + return queue; + } + + public void afterReferenceCreation(Reference r) {} + public void removeStallEntries() {} + public void stopThread() {} + + @Override + public String toString() { + return "ReferenceManager(idling)"; + } +} Index: main/org/codehaus/groovy/util/LazySoftReference.java =================================================================== --- main/org/codehaus/groovy/util/LazySoftReference.java (Revision 13791) +++ main/org/codehaus/groovy/util/LazySoftReference.java (Arbeitskopie) @@ -1,76 +0,0 @@ -package org.codehaus.groovy.util; - -import java.lang.ref.SoftReference; - -/** - * Soft reference with lazy initialization under lock - */ -public abstract class LazySoftReference<T> extends LockableObject { - private SoftReference<T> value; - - public T get() { - SoftReference<T> resRef = value; - T res; - if (resRef != null && (res = resRef.get()) != null) - return res; - - return getLocked(); - } - - private T getLocked () { - lock (); - try { - SoftReference<T> resRef = value; - T res; - if (resRef != null && (res = resRef.get()) != null) - return res; - - res = initValue(); - value = new MySoftRef<T>(res); - return res; - } - finally { - unlock(); - } - } - - public void set (T newVal) { - if (newVal == null) - value = null; - else - value = new MySoftRef<T>(newVal); - } - - public T getNullable() { - SoftReference<T> resRef = value; - T res; - if (resRef == null || (res = resRef.get()) == null) { - return null; - } - return res; - } - - public abstract T initValue(); - - protected void finalizeRef() { - value = null; - } - - public String toString() { - T res = getNullable(); - if (res == null) - return "<null>"; - else - return res.toString(); - } - - private class MySoftRef<T> extends FinalizableRef.SoftRef<T> { - public MySoftRef(T res) { - super(res); - } - - public void finalizeRef() { - LazySoftReference.this.finalizeRef(); - } - } -} Index: main/org/codehaus/groovy/util/ManagedConcurrentMap.java =================================================================== --- main/org/codehaus/groovy/util/ManagedConcurrentMap.java (Revision 13791) +++ main/org/codehaus/groovy/util/ManagedConcurrentMap.java (Arbeitskopie) @@ -1,29 +1,42 @@ package org.codehaus.groovy.util;

-public class ConcurrentWeakMap<K,V> extends AbstractConcurrentMap<K,V> { - public ConcurrentWeakMap() { +import org.codehaus.groovy.util.ManagedReference.ReferenceBundle; + +public class ManagedConcurrentMap<K,V> extends AbstractConcurrentMap<K,V> { + protected ReferenceBundle bundle; + public ManagedConcurrentMap(ReferenceBundle bundle) { + super(bundle); + this.bundle = bundle; + if (bundle==null) throw new IllegalArgumentException("bundle must not be null"); }

- protected Segment<K,V> createSegment(int cap) { - return new ConcurrentWeakMap.Segment<K,V>(this, cap); + protected Segment<K,V> createSegment(Object segmentInfo, int cap) { + ReferenceBundle bundle = (ReferenceBundle) segmentInfo; + if (bundle==null) throw new IllegalArgumentException("bundle must not be null"); + return new ManagedConcurrentMap.Segment<K,V>(bundle, cap); }

public static class Segment<K,V> extends AbstractConcurrentMap.Segment<K,V>{ - public Segment(ConcurrentWeakMap<K,V> map, int cap) { + protected final ReferenceBundle bundle; + public Segment(ReferenceBundle bundle, int cap) { super(cap); + this.bundle = bundle; + if (bundle==null) throw new IllegalArgumentException("bundle must not be null"); + }

protected AbstractConcurrentMap.Entry<K,V> createEntry(K key, int hash, V value) { - return new EntryWithValue<K,V>(this, key, hash, value); + if (bundle==null) throw new IllegalArgumentException("bundle must not be null"); + return new EntryWithValue<K,V>(bundle, this, key, hash, value); } }

- public static class Entry<K,V> extends FinalizableRef.WeakRef<K> implements AbstractConcurrentMap.Entry<K,V> { + public static class Entry<K,V> extends ManagedReference<K> implements AbstractConcurrentMap.Entry<K,V> { private final Segment segment; private int hash;

- public Entry(Segment segment, K key, int hash) { - super(key); + public Entry(ReferenceBundle bundle, Segment segment, K key, int hash) { + super(bundle, key); this.segment = segment; this.hash = hash; } @@ -48,7 +61,7 @@ }

public void finalizeRef() { - super.finalizeRef(); + super.finalizeReference(); segment.removeEntry(this); } } @@ -56,8 +69,8 @@ public static class EntryWithValue<K,V> extends Entry<K,V> { private V value;

- public EntryWithValue(Segment segment, K key, int hash, V value) { - super(segment, key, hash); + public EntryWithValue(ReferenceBundle bundle, Segment segment, K key, int hash, V value) { + super(bundle, segment, key, hash); setValue(value); }

Eigenschaftsänderungen: main/org/codehaus/groovy/util/ManagedConcurrentMap.java

___________________________________________________________________ Hinzugefügt: svn:mergeinfo

Index: main/org/codehaus/groovy/util/ManagedDoubleKeyMap.java =================================================================== --- main/org/codehaus/groovy/util/ManagedDoubleKeyMap.java (Revision 13791) +++ main/org/codehaus/groovy/util/ManagedDoubleKeyMap.java (Arbeitskopie) @@ -15,35 +15,40 @@ */ package org.codehaus.groovy.util;

-public class SoftDoubleKeyMap<K1,K2,V> extends AbstractConcurrentDoubleKeyMap<K1,K2,V> { - protected AbstractConcurrentDoubleKeyMap.Segment<K1,K2,V> createSegment(int cap) { - return new Segment<K1,K2,V>(cap); +import org.codehaus.groovy.util.ManagedReference.ReferenceBundle; + +public class ManagedDoubleKeyMap<K1,K2,V> extends AbstractConcurrentDoubleKeyMap<K1,K2,V> { + public ManagedDoubleKeyMap(ReferenceBundle bundle) { + super(bundle); } + + protected AbstractConcurrentDoubleKeyMap.Segment<K1,K2,V> createSegment(Object segmentInfo, int cap) { + ReferenceBundle bundle = (ReferenceBundle) segmentInfo; + return new Segment<K1,K2,V>(bundle, cap); + }

static class Segment<K1,K2,V> extends AbstractConcurrentDoubleKeyMap.Segment<K1,K2,V>{ - public Segment(int cap) { + private ReferenceBundle bundle; + public Segment(ReferenceBundle bundle, int cap) { super(cap); + this.bundle = bundle; }

protected AbstractConcurrentDoubleKeyMap.Entry<K1,K2,V> createEntry(K1 key1, K2 key2, int hash) { - return new EntryWithValue(key1, key2, hash, this); + return new EntryWithValue(bundle, key1, key2, hash, this); } }

- static class Ref<K> extends FinalizableRef.SoftRef<K> { + static class Ref<K> extends ManagedReference<K> { final Entry entry; - public Ref(K referent, Entry entry) { - super(referent); + public Ref(ReferenceBundle bundle, K referent, Entry entry) { + super(bundle, referent); this.entry = entry; }

public void finalizeRef() { this.entry.clean(); } - - public void clear() { - super.clear(); - } }

public static class Entry<K1,K2, V> implements AbstractConcurrentDoubleKeyMap.Entry<K1,K2,V> { @@ -52,11 +57,11 @@ final Ref<K2> ref2; final Segment segment;

- public Entry(K1 key1, K2 key2, int hash, Segment segment) { + public Entry(ReferenceBundle bundle, K1 key1, K2 key2, int hash, Segment segment) { this.hash = hash; this.segment = segment; - ref1 = new Ref(key1, this); - ref2 = new Ref(key2, this); + ref1 = new Ref(bundle, key1, this); + ref2 = new Ref(bundle, key2, this); }

public boolean isValid() { @@ -88,8 +93,8 @@ private static class EntryWithValue<K1,K2,V> extends Entry<K1,K2,V> { private V value;

- public EntryWithValue(K1 key1, K2 key2, int hash, Segment segment) { - super(key1, key2, hash, segment); + public EntryWithValue(ReferenceBundle bundle, K1 key1, K2 key2, int hash, Segment segment) { + super(bundle, key1, key2, hash, segment); }

public V getValue() {

Eigenschaftsänderungen: main/org/codehaus/groovy/util/ManagedDoubleKeyMap.java

___________________________________________________________________ Hinzugefügt: svn:mergeinfo

Index: main/org/codehaus/groovy/util/LazyReference.java =================================================================== --- main/org/codehaus/groovy/util/LazyReference.java (Revision 13791) +++ main/org/codehaus/groovy/util/LazyReference.java (Arbeitskopie) @@ -1,76 +1,59 @@ package org.codehaus.groovy.util;

-import java.lang.ref.SoftReference; +import org.codehaus.groovy.util.ManagedReference.ReferenceBundle;

+ /** * Soft reference with lazy initialization under lock */ -public abstract class LazySoftReference<T> extends LockableObject { - private SoftReference<T> value; - +public abstract class LazyReference<T> extends LockableObject { + private final static ManagedReference INIT = new ManagedReference(ReferenceType.HARD,null,null){}; + private final static ManagedReference NULL_REFERENCE = new ManagedReference(ReferenceType.HARD,null,null){}; + private ManagedReference<T> reference = INIT; + private final ReferenceBundle bundle; + + public LazyReference(ReferenceBundle bundle) { + this.bundle = bundle; + } + public T get() { - SoftReference<T> resRef = value; - T res; - if (resRef != null && (res = resRef.get()) != null) - return res; - - return getLocked(); + ManagedReference<T> resRef = reference; + if (resRef == INIT) return getLocked(false); + if (resRef == NULL_REFERENCE) return null; + T res = resRef.get(); + // res== null means it got collected + if (res==null) return getLocked(true); + return res; }

- private T getLocked () { + private T getLocked (boolean force) { lock (); try { - SoftReference<T> resRef = value; - T res; - if (resRef != null && (res = resRef.get()) != null) - return res; - - res = initValue(); - value = new MySoftRef<T>(res); + ManagedReference<T> resRef = reference; + if (!force && resRef != INIT) return resRef.get(); + T res = initValue(); + if (res == null) { + reference = NULL_REFERENCE; + } else { + reference = new ManagedReference<T>(bundle,res); + } return res; - } - finally { + } finally { unlock(); } }

- public void set (T newVal) { - if (newVal == null) - value = null; - else - value = new MySoftRef<T>(newVal); + public void clear() { + reference = INIT; }

- public T getNullable() { - SoftReference<T> resRef = value; - T res; - if (resRef == null || (res = resRef.get()) == null) { - return null; - } - return res; - } - public abstract T initValue();

- protected void finalizeRef() { - value = null; - } - public String toString() { - T res = getNullable(); + T res = reference.get(); if (res == null) return "<null>"; else return res.toString(); } - - private class MySoftRef<T> extends FinalizableRef.SoftRef<T> { - public MySoftRef(T res) { - super(res); - } - - public void finalizeRef() { - LazySoftReference.this.finalizeRef(); - } - } }

Eigenschaftsänderungen: main/org/codehaus/groovy/util/LazyReference.java

___________________________________________________________________ Hinzugefügt: svn:mergeinfo

Index: main/org/codehaus/groovy/util/Reference.java =================================================================== --- main/org/codehaus/groovy/util/Reference.java (Revision 0) +++ main/org/codehaus/groovy/util/Reference.java (Revision 0) @@ -0,0 +1,7 @@ +package org.codehaus.groovy.util; + +public interface Reference<T,V extends Finalizable> { + T get(); + void clear(); + V getHandler(); +}