Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceDeque.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceDeque.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceDeque.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceDeque.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,150 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.util.Deque; +import java.util.Iterator; + +/** + * + * @author Peter Firmstone + */ +class ReferenceDeque<T> extends ReferencedQueue<T> implements Deque<T>{ + private static final long serialVersionUID = 1L; + private final Deque<Referrer<T>> deque; + ReferenceDeque(Deque<Referrer<T>> deque, Ref type, boolean gcThreads, long gcCycle){ + super(deque, type, gcThreads, gcCycle); + this.deque = deque; + } + + private void readObject(ObjectInputStream stream) + throws InvalidObjectException{ + throw new InvalidObjectException("Builder required"); + } + + public void addFirst(T e) { + processQueue(); + Referrer<T> r = wrapObj(e, true, false); + deque.addFirst(r); + } + + public void addLast(T e) { + processQueue(); + Referrer<T> r = wrapObj(e, true, false); + deque.addLast(r); + } + + public boolean offerFirst(T e) { + processQueue(); + Referrer<T> r = wrapObj(e, true, false); + return deque.offerFirst(r); + } + + public boolean offerLast(T e) { + processQueue(); + Referrer<T> r = wrapObj(e, true, false); + return deque.offerLast(r); + } + + public T removeFirst() { + processQueue(); + Referrer<T> t = deque.removeFirst(); + if ( t != null ) return t.get(); + return null; + } + + public T removeLast() { + processQueue(); + Referrer<T> t = deque.removeLast(); + if ( t != null ) return t.get(); + return null; + } + + public T pollFirst() { + processQueue(); + Referrer<T> t = deque.pollFirst(); + if ( t != null ) return t.get(); + return null; + } + + public T pollLast() { + processQueue(); + Referrer<T> t = deque.pollLast(); + if ( t != null ) return t.get(); + return null; + } + + public T getFirst() { + processQueue(); + Referrer<T> t = deque.getFirst(); + if ( t != null ) return t.get(); + return null; + } + + public T getLast() { + processQueue(); + Referrer<T> t = deque.getLast(); + if ( t != null ) return t.get(); + return null; + } + + public T peekFirst() { + processQueue(); + Referrer<T> t = deque.peekFirst(); + if ( t != null ) return t.get(); + return null; + } + + public T peekLast() { + processQueue(); + Referrer<T> t = deque.peekLast(); + if ( t != null ) return t.get(); + return null; + } + + public boolean removeFirstOccurrence(Object o) { + processQueue(); + @SuppressWarnings("unchecked") + Referrer<T> r = wrapObj((T) o, false, true); + return deque.removeFirstOccurrence(r); + } + + public boolean removeLastOccurrence(Object o) { + processQueue(); + @SuppressWarnings("unchecked") + Referrer<T> r = wrapObj((T) o, false, true); + return deque.removeLastOccurrence(r); + } + + public void push(T e) { + processQueue(); + Referrer<T> r = wrapObj(e, true, false); + deque.push(r); + } + + public T pop() { + processQueue(); + Referrer<T> t = deque.pop(); + if ( t != null ) return t.get(); + return null; + } + + public Iterator<T> descendingIterator() { + return new ReferenceIterator<T>(deque.descendingIterator()); + } +}
Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceEntryFacade.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceEntryFacade.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceEntryFacade.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceEntryFacade.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,83 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.lang.ref.Reference; +import java.util.Map; +import java.util.Map.Entry; + +/** + * + * @author Peter Firmstone. + */ +class ReferenceEntryFacade<K, V> implements Map.Entry<K, V> { + private final Entry<Referrer<K>, Referrer<V>> entry; + private final ReferenceQueuingFactory<V, Referrer<V>> rqf; + + ReferenceEntryFacade(Entry<Referrer<K>, Referrer<V>> entry, ReferenceQueuingFactory<V, Referrer<V>> rqf){ + this.entry = entry; + this.rqf = rqf; + } + + public K getKey() { + Referrer<K> k = entry.getKey(); + if ( k != null ) return k.get(); + return null; + } + + public V getValue() { + Referrer<V> v = entry.getValue(); + if ( v != null ) return v.get(); + return null; + } + + public V setValue(V value) { + Referrer<V> v = entry.setValue(wrapVal(value, true)); + if ( v != null ) return v.get(); + return null; + } + + /** + * Implementation copied directly from Entry javadoc. + * @see Entry#hashCode() + * @return + */ + @Override + public int hashCode() { + return (getKey()==null ? 0 : getKey().hashCode()) ^ + (getValue()==null ? 0 : getValue().hashCode()); + } + + /** + * Implementation copied directly from Entry javadoc. + * @see Entry#equals(java.lang.Object) + */ + public boolean equals(Object o){ + if ( o == this ) return true; + if ( !(o instanceof Entry) ) return false; + Entry e1 = this; + Entry e2 = (Entry) o; + return ( (e1.getKey()==null ? e2.getKey()==null : + e1.getKey().equals(e2.getKey())) && + (e1.getValue()==null ? e2.getValue()==null : + e1.getValue().equals(e2.getValue()))); + } + + private Referrer<V> wrapVal(V val, boolean enque) { + return rqf.referenced(val, enque, false); +} + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceFactory.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceFactory.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceFactory.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceFactory.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,105 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; + +/** + * ReferenceFactory creates References, representing the various subclasses + * of Reference, such as WEAK, SOFT and STRONG for + * use in collections. + * + * These subtypes override equals and hashcode, so that References may be used + * in Collections, Maps, Sets and Lists to represent their referent. + * + * @see Reference + * @see Ref + * @author Peter Firmstone. + */ +class ReferenceFactory<T> { + + // Non instantiable. + private ReferenceFactory(){} + + static <T> Referrer<T> create(T t, RefQueue<? super T> queue, Ref type ){ + if (t == null) throw new NullPointerException("Reference collections cannot contain null"); + RefReferenceQueue<? super T> refQueue = null; + TimedRefQueue timedRefQue = null; + if (queue instanceof RefReferenceQueue) refQueue = (RefReferenceQueue<? super T>) queue; + if (queue instanceof TimedRefQueue) timedRefQue = (TimedRefQueue) queue; + switch (type){ + case WEAK_IDENTITY: + return new ReferrerDecorator<T>(new WeakIdentityReference<T>(t, refQueue)); + case SOFT_IDENTITY: + return new ReferrerDecorator<T>(new SoftIdentityReference<T>(t, refQueue)); + case WEAK: + if (t instanceof Comparable) + return new ComparableReferrerDecorator<T>(new WeakEqualityReference<T>(t, refQueue)); + return new ReferrerDecorator<T>(new WeakEqualityReference<T>(t, refQueue)); + case SOFT: + if (t instanceof Comparable) + return new ComparableReferrerDecorator<T>(new SoftEqualityReference<T>(t, refQueue)); + return new ReferrerDecorator<T>(new SoftEqualityReference<T>(t, refQueue)); + case TIME: + if (t instanceof Comparable) + return new TimedComparableReferrerDecorator<T>(new TimedReferrer<T>(t, timedRefQue)); + return new TimedReferrerDecorator<T>(new TimedReferrer<T>(t, timedRefQue)); + default: + if (t instanceof Comparable) + return new ComparableReferrerDecorator<T>(new StrongReference<T>(t, refQueue)); + return new ReferrerDecorator<T>(new StrongReference<T>(t, refQueue)); + } + } + + /** + * This doesn't create a genuine reference, only a simple wrapper object + * that will be used once then discarded. The Referrer will be allocated + * to the stack by the jvm and not the heap. There is no queue, no + * reference, this is simply a wrapper class that provides the correct + * equals, hashcode and comparator semantics. + * + * This object must not be added to any collection classes, it is not + * serialisable, it's sole intended purpose is to improve read performance + * by being allocated to the stack, not the heap space and avoiding a + * cache miss. To achieve this goal, it must not be shared with other + * Threads either. + * + * @param <T> + * @param t + * @param type + * @return + */ + static <T> Referrer<T> singleUseForLookup(T t, Ref type){ + if (t == null) throw new NullPointerException("Reference collections cannot contain null"); + switch (type){ + case WEAK_IDENTITY: + return new TempIdentityReferrer<T>(t); + case SOFT_IDENTITY: + return new TempIdentityReferrer<T>(t); + case WEAK: + if (t instanceof Comparable) return new TempComparableReferrer<T>(t); + return new TempEqualReferrer<T>(t); + case SOFT: + if (t instanceof Comparable) return new TempComparableReferrer<T>(t); + return new TempEqualReferrer<T>(t); + default: + if (t instanceof Comparable) return new TempComparableReferrer<T>(t); + return new TempEqualReferrer<T>(t); + } + } + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceIterator.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceIterator.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceIterator.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceIterator.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,58 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.lang.ref.Reference; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * + * @author Peter Firmstone. + */ +class ReferenceIterator<T> implements Iterator<T> { + private final Iterator<Referrer<T>> iterator; + private T next; + + ReferenceIterator(Iterator<Referrer<T>> iterator) { + if ( iterator == null ) throw new IllegalArgumentException("iterator cannot be null"); + this.iterator = iterator; + next = null; + } + + public boolean hasNext() { + while ( iterator.hasNext()){ + Referrer<T> t = iterator.next(); + if ( t != null ) { + next = t.get(); + if (next != null) return true; + else iterator.remove(); // garbage collected. + } + } + next = null; + return false; + } + + public T next() { + if (next == null) throw new NoSuchElementException(); + return next; + } + + public void remove() { + iterator.remove(); + } + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceList.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceList.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceList.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceList.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,215 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +/** + * A List implementation that uses References. + * + * This enables a Collection or List to contain, softly, weakly or strongly referenced + * objects. Objects that are no longer reachable will simply vanish from + * the Collection. + * + * For example, this could be used as an Object cache containing softly reachable + * objects which are only collected when the jvm is experiencing low memory + * conditions. + * + * Synchronisation must be performed by the underlying List, it cannot be + * performed externally, since every read is also potentially a mutable + * change, caused by removal of garbage collected Objects. + * + * Removal of garbage collected objects is performed before iteration, but not + * during, instead some Object's returned during iteration may be null. + * + * @author Peter Firmstone. + */ +class ReferenceList<T> extends ReferenceCollection<T> implements List<T> { + private static final long serialVersionUID = 1L; + private final List<Referrer<T>> list; + ReferenceList(List<Referrer<T>> list, Ref type, boolean gcThreads, long gcCycle){ + super(list, type, gcThreads, gcCycle); + this.list = list; + } + + ReferenceList(List<Referrer<T>> list, ReferenceQueuingFactory<T, Referrer<T>> rqf, Ref type){ + super(list, rqf, type); + this.list = list; + } + + private void readObject(ObjectInputStream stream) + throws InvalidObjectException{ + throw new InvalidObjectException("Builder required"); + } + + /** + * Implemented as per the List interface definition of equals. + * @see List#equals(java.lang.Object) + * @param o + * @return + */ + public boolean equals(Object o){ + if ( o == null ) return false; + if (!( o instanceof List)) return false; + List l = (List) o; + if ( l.size() != size()) return false; + Iterator<T> li = iterator(); + int i = 0; + while(li.hasNext()){ + T t = li.next(); + if ( t != null ){ + if ( !(t.equals(l.get(i))) ) return false; + } else { + if ( l.get(i) != null ) return false; // both must be null + } + i++; + } + return true; + } + + /** + * Implemented as per List interface definition. + * + * @see List#hashCode() + * @return + */ + public int hashCode() { + // hash code calculation copied directly from List interface contract. + int hashCode = 1; + Iterator<T> i = iterator(); + while (i.hasNext()) { + T obj = i.next(); + hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode()); + } + return hashCode; + } + + @SuppressWarnings("unchecked") + public boolean addAll(int index, Collection<? extends T> c) { + processQueue(); + return list.addAll(index, new CollectionDecorator<T>((Collection<T>) c, getRQF(), true, false)); + } + + public T get(int index) { + processQueue(); + Referrer<T> r = list.get(index); + if (r != null) return r.get(); + return null; + } + + public T set(int index, T element) { + processQueue(); + Referrer<T> r = list.set(index, wrapObj(element, true, false)); + if (r != null) return r.get(); + return null; + } + + public void add(int index, T element) { + processQueue(); + list.add(index, wrapObj(element, true, false)); + } + + public T remove(int index) { + processQueue(); + Referrer<T> r = list.remove(index); + if (r != null) return r.get(); + return null; + } + + @SuppressWarnings("unchecked") + public int indexOf(Object o) { + processQueue(); + return list.indexOf(wrapObj((T) o, false, true)); + } + + @SuppressWarnings("unchecked") + public int lastIndexOf(Object o) { + processQueue(); + return list.lastIndexOf(wrapObj((T)o, false, true)); + } + + public ListIterator<T> listIterator() { + processQueue(); + return new ReferenceListIterator<T>(list.listIterator(), getRQF()); + } + + public ListIterator<T> listIterator(int index) { + processQueue(); + return new ReferenceListIterator<T>(list.listIterator(index), getRQF()); + } + + public List<T> subList(int fromIndex, int toIndex) { + processQueue(); + List<T> sub = new ReferenceList<T>(list.subList(fromIndex, toIndex), getRQF(), null); + return sub; + } + + private class ReferenceListIterator<T> implements ListIterator<T>{ + ListIterator<Referrer<T>> iterator; + ReferenceQueuingFactory<T, Referrer<T>> rqf; + private ReferenceListIterator(ListIterator<Referrer<T>> iterator, ReferenceQueuingFactory<T, Referrer<T>> rqf ){ + if ( iterator == null || rqf == null ) throw + new NullPointerException("Null iterator or reference queuing factory not allowed"); + this.iterator = iterator; + this.rqf = rqf; + } + + public boolean hasNext() { + return iterator.hasNext(); + } + + public T next() { + Referrer<T> t = iterator.next(); + if ( t != null ) return t.get(); + return null; + } + + public boolean hasPrevious() { + return iterator.hasPrevious(); + } + + public T previous() { + Referrer<T> t = iterator.previous(); + if ( t != null ) return t.get(); + return null; + } + + public int nextIndex() { + return iterator.nextIndex(); + } + + public int previousIndex() { + return iterator.previousIndex(); + } + + public void remove() { + iterator.remove(); + } + + public void set(T e) { + iterator.set(rqf.referenced(e, true, false)); + } + + public void add(T e) { + iterator.add(rqf.referenced( e, true, false)); + } + } +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceMap.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceMap.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceMap.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceMap.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,251 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.lang.ref.ReferenceQueue; +import java.util.AbstractMap; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +/** + * ReferenceMap is a wrapper object that encapsulates another Map implementation + * which it uses to store references. + * + * Synchronisation must be performed by the underlying map, using external + * synchronisation will fail, since each read is also potentially a + * mutation to remove a garbage collected reference. + * + * Implementation note: + * + * ReferenceQueue's must be allowed to be used by any views when creating + * new References using the wrapper, so the Reference is passed to the + * correct ReferenceQueue when it becomes unreachable. + * + * There is only one ReferenceQueue for each Collection, whether that is a + * Collection of Key's or Values. Defensive copies cannot be made by the + * underlying encapsulated collections. + * + * Abstract map is extended to take advantage of it's equals, hashCode and + * toString methods, which rely on calling entrySet() which this class + * overrides. + * + * @param <K> + * @param <V> + * @author Peter Firmstone. + */ +class ReferenceMap<K, V> extends AbstractMap<K, V> implements Map<K, V> { + + private final Map<Referrer<K>, Referrer<V>> map; + // ReferenceQueuingFactory's handle ReferenceQueue locking policy. + private final ReferenceQueuingFactory<K, Referrer<K>> krqf; + private final ReferenceQueuingFactory<V, Referrer<V>> vrqf; + private final Ref key; + private final Ref val; + + // Views of values and keys, reduces object creation. + private final Collection<V> values; + private final Set<K> keys; + private final Set<Entry<K,V>> entrys; + + @SuppressWarnings("unchecked") + ReferenceMap(Map<Referrer<K>,Referrer<V>> map, Ref key, Ref val, boolean gcThreads, long gcKeyCycle, long gcValCycle){ + // Note the ReferenceProcessor must synchronize on map, not the keySet or values for iteration. + // This no effect on ConcurrentMap implementations, it's just in case of + // Synchronized maps. + RefQueue<K> keyQue = null; + if (key.equals(Ref.TIME)) keyQue = new TimedRefQueue(); + else if (!key.equals(Ref.STRONG)) keyQue = new RefReferenceQueue<K>(); + RefQueue<V> valQue = null; + if (val.equals(Ref.TIME)) valQue = new TimedRefQueue(); + else if (!val.equals(Ref.STRONG)) valQue = new RefReferenceQueue<V>(); + ReferenceProcessor<K> krp = new ReferenceProcessor<K>(map.keySet(), key, keyQue, gcThreads, map); + ReferenceProcessor<V> vrp = new ReferenceProcessor<V>(map.values(), val, valQue, gcThreads, map); + this.krqf = krp; + this.vrqf = vrp; + this.map = map; + this.key = key; + this.val = val; + values = new ReferenceCollection<V>(this.map.values(), vrqf, val); + keys = new ReferenceSet<K>(this.map.keySet(), krqf, key); + // We let this escape during construction, but it's package private only + // and doesn't escape the package. + entrys = new EntrySetFacade<Entry<K,V>, Entry<Referrer<K>,Referrer<V>>>( + map.entrySet(), + new EntryFacadeConverter<K,V>(krqf, vrqf) + ); + krp.start(gcKeyCycle); + vrp.start(gcValCycle); + } + + ReferenceMap(Map<Referrer<K>, Referrer<V>> map, ReferenceQueuingFactory<K, Referrer<K>> krqf, ReferenceQueuingFactory<V, Referrer<V>> vrqf, Ref key, Ref val){ + this.map = map; + this.krqf = krqf; + this.vrqf = vrqf; + this.key = key; + this.val = val; + values = new ReferenceCollection<V>(this.map.values(), vrqf, val); + keys = new ReferenceSet<K>(this.map.keySet(), krqf, key); + // We let this escape during construction, but it's package private only + // and doesn't escape the package. + entrys = new EntrySetFacade<Entry<K,V>, Entry<Referrer<K>,Referrer<V>>>( + map.entrySet(), + new EntryFacadeConverter<K,V>(krqf, vrqf) + ); + } + + + + ReferenceQueuingFactory<K, Referrer<K>> getKeyRQF(){ + return krqf; + } + + ReferenceQueuingFactory<V, Referrer<V>> getValRQF(){ + return vrqf; + } + + Ref keyRef() { + return key; + } + + Ref valRef() { + return val; + } + + /** + * Removes all associations from this map. + */ + public void clear() { + processQueue(); + map.clear(); + } + + @SuppressWarnings(value = "unchecked") + public boolean containsKey(Object key) { + processQueue(); + return map.containsKey(wrapKey((K)key, false, true)); + } + + @SuppressWarnings("unchecked") + public boolean containsValue(Object value) { + processQueue(); + return map.containsValue(wrapVal((V) value, false, true)); + } + + /** + * Returns a Set view of the mappings contained in the underlying map. + * + * The behaviour of this Set depends on the underlying Map passed in + * at construction time. + * + * The set supports element removal, which removes the corresponding + * mapping from the map, via the Iterator.remove, Set.remove, removeAll, + * retainAll and clear operations. + * + * @return + */ + public Set<Entry<K,V>> entrySet() { + return entrys; + } + + /** + * Returns value associated with given key, or null if none. + */ + public V get(Object key) { + processQueue(); + @SuppressWarnings(value = "unchecked") + Referrer<V> refVal = map.get(wrapKey((K) key, false, true)); + if (refVal != null) return refVal.get(); + return null; + } + + public boolean isEmpty() { + processQueue(); + return map.isEmpty(); + } + + /** + * The key Set returned, is encapsulated by ReferenceSet, which encapsulates + * it's objects using the same Ref type as ReferenceMap + * + * @see Ref + * @see ReferenceSet + * @return + */ + public Set<K> keySet() { + processQueue(); + return keys; + } + + public void processQueue() { + // If someone else is cleaning out the trash, don't bother waiting, + // the underlying Map is responsible for it's own synchronization. + // Null values or keys may be returned as a result. + // Or a ConcurrentMap that contains a value may no longer contain + // it after checking. +// krqf.processQueue(); +// vrqf.processQueue(); + } + + /** + * Associates value with given key, returning value previously associated + * with key, or null if none. + * @param key - Key + * @param value - Value + * @return previous value or null + */ + public V put(K key, V value) { + processQueue(); + Referrer<V> val = map.put(wrapKey(key, true, false),wrapVal(value, true, false)); + if (val != null) return val.get(); + return null; + } + + /** + * Removes association for given key, returning value previously associated + * with key, or null if none. + */ + public V remove(Object key) { + processQueue(); + @SuppressWarnings(value = "unchecked") + Referrer<V> val = map.remove(wrapKey((K) key, false, true)); + if (val != null) return val.get(); + return null; + } + + public int size() { + processQueue(); + return map.size(); + } + + /** + * Returns collection containing all values currently held in this map. + */ + public Collection<V> values() { + processQueue(); + return values; + } + + Referrer<V> wrapVal(V val, boolean enque, boolean temporary) { + return vrqf.referenced(val, enque, temporary); + } + + Referrer<K> wrapKey(K key, boolean enque, boolean temporary) { + return krqf.referenced(key, enque, temporary); + } + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceMapSerialData.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceMapSerialData.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceMapSerialData.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceMapSerialData.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,24 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +/** + * + * @author peter + */ +class ReferenceMapSerialData<K,V> { + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceNavigableMap.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceNavigableMap.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceNavigableMap.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceNavigableMap.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,184 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.util.Map.Entry; +import java.util.NavigableMap; +import java.util.NavigableSet; + +/** + * + * @author Peter Firmstone. + */ +class ReferenceNavigableMap<K,V> extends ReferenceSortedMap<K,V> implements NavigableMap<K,V> { + private final NavigableMap<Referrer<K>, Referrer<V>> map; + + ReferenceNavigableMap(NavigableMap<Referrer<K>, Referrer<V>> map, Ref keyRef, Ref valRef, boolean gcThreads, long gcKeyCycle, long gcValCycle){ + super(map, keyRef, valRef, gcThreads, gcKeyCycle, gcValCycle); + this.map = map; + } + + ReferenceNavigableMap(NavigableMap<Referrer<K>, Referrer<V>> map, + ReferenceQueuingFactory<K, Referrer<K>> krqf, + ReferenceQueuingFactory<V, Referrer<V>> vrqf, Ref key, Ref val){ + super(map, krqf, vrqf, key, val); + this.map = map; + } + + public Entry<K, V> lowerEntry(K key) { + processQueue(); + return new ReferenceEntryFacade<K,V>( + map.lowerEntry(wrapKey(key, false, true)), + getValRQF() + ); + } + + public K lowerKey(K key) { + processQueue(); + Referrer<K> k = map.lowerKey(wrapKey(key, false, true)); + if (k != null) return k.get(); + return null; + } + + public Entry<K, V> floorEntry(K key) { + processQueue(); + return new ReferenceEntryFacade<K,V>( + map.floorEntry(wrapKey(key, false, true)), + getValRQF() + ); + } + + public K floorKey(K key) { + processQueue(); + Referrer<K> k = map.floorKey(wrapKey(key, false, true)); + if (k != null) return k.get(); + return null; + } + + public Entry<K, V> ceilingEntry(K key) { + processQueue(); + return new ReferenceEntryFacade<K,V>( + map.ceilingEntry(wrapKey(key, false, true)), + getValRQF() + ); + } + + public K ceilingKey(K key) { + processQueue(); + Referrer<K> k = map.ceilingKey(wrapKey(key, false, true)); + if (k != null) return k.get(); + return null; + } + + public Entry<K, V> higherEntry(K key) { + processQueue(); + return new ReferenceEntryFacade<K,V>( + map.higherEntry(wrapKey(key, false, true)), + getValRQF() + ); + } + + public K higherKey(K key) { + processQueue(); + Referrer<K> k = map.higherKey(wrapKey(key, false, true)); + if (k != null) return k.get(); + return null; + } + + public Entry<K, V> firstEntry() { + processQueue(); + return new ReferenceEntryFacade<K,V>( + map.firstEntry(), + getValRQF() + ); + } + + public Entry<K, V> lastEntry() { + processQueue(); + return new ReferenceEntryFacade<K,V>( + map.lastEntry(), + getValRQF() + ); + } + + public Entry<K, V> pollFirstEntry() { + processQueue(); + return new ReferenceEntryFacade<K,V>( + map.pollFirstEntry(), + getValRQF() + ); + } + + public Entry<K, V> pollLastEntry() { + processQueue(); + return new ReferenceEntryFacade<K,V>( + map.pollLastEntry(), + getValRQF() + ); + } + + public NavigableMap<K, V> descendingMap() { + processQueue(); + return new ReferenceNavigableMap<K,V>( + map.descendingMap(), + getKeyRQF(), + getValRQF(), keyRef(), valRef() + ); + } + + public NavigableSet<K> navigableKeySet() { + processQueue(); + return new ReferenceNavigableSet<K>(map.navigableKeySet(), getKeyRQF(), keyRef()); + } + + public NavigableSet<K> descendingKeySet() { + processQueue(); + return new ReferenceNavigableSet<K>(map.descendingKeySet(), getKeyRQF(), keyRef()); + } + + public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { + processQueue(); + return new ReferenceNavigableMap<K,V>( + map.subMap( + wrapKey(fromKey, false, true), + fromInclusive, + wrapKey(toKey, false, true), + toInclusive + ), + getKeyRQF(), + getValRQF(), keyRef(), valRef() + ); + + } + + public NavigableMap<K, V> headMap(K toKey, boolean inclusive) { + processQueue(); + return new ReferenceNavigableMap<K,V>( + map.headMap(wrapKey(toKey, false, true),inclusive), + getKeyRQF(), + getValRQF(), keyRef(), valRef() + ); + } + + public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) { + processQueue(); + return new ReferenceNavigableMap<K,V>( + map.tailMap(wrapKey(fromKey, false, true),inclusive), + getKeyRQF(), + getValRQF(), keyRef(), valRef() + ); + } +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceNavigableSet.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceNavigableSet.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceNavigableSet.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceNavigableSet.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,132 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.util.Iterator; +import java.util.NavigableSet; + +/** + * + * @param <T> + * @author Peter Firmstone. + */ +class ReferenceNavigableSet<T> + extends ReferenceSortedSet<T> implements NavigableSet<T> { + private static final long serialVersionUID = 1L; + private final NavigableSet<Referrer<T>> set; + + public ReferenceNavigableSet(NavigableSet<Referrer<T>> set, Ref type, boolean gcThreads, long gcCycle){ + super(set, type, gcThreads, gcCycle); + this.set = set; + } + + ReferenceNavigableSet(NavigableSet<Referrer<T>> set, ReferenceQueuingFactory<T, Referrer<T>> rqf, Ref type){ + super(set, rqf, type); + this.set = set; + } + + private void readObject(ObjectInputStream stream) + throws InvalidObjectException{ + throw new InvalidObjectException("Builder required"); + } + + public T lower(T e) { + processQueue(); + Referrer<T> t = set.lower(wrapObj(e, false, true)); + if ( t != null ) return t.get(); + return null; + } + + public T floor(T e) { + processQueue(); + Referrer<T> t = set.floor(wrapObj(e, false, true)); + if ( t != null ) return t.get(); + return null; + } + + public T ceiling(T e) { + processQueue(); + Referrer<T> t = set.ceiling(wrapObj(e, false, true)); + if ( t != null ) return t.get(); + return null; + } + + public T higher(T e) { + processQueue(); + Referrer<T> t = set.higher(wrapObj(e, false, true)); + if ( t != null ) return t.get(); + return null; + } + + public T pollFirst() { + processQueue(); + Referrer<T> t = set.pollFirst(); + if ( t != null ) return t.get(); + return null; + } + + public T pollLast() { + processQueue(); + Referrer<T> t = set.pollLast(); + if ( t != null ) return t.get(); + return null; + } + + public NavigableSet<T> descendingSet() { + processQueue(); + return new ReferenceNavigableSet<T>(set.descendingSet(), getRQF(), null); + } + + public Iterator<T> descendingIterator() { + processQueue(); + return new ReferenceIterator<T>(set.descendingIterator()); + } + + public NavigableSet<T> subSet(T fromElement, boolean fromInclusive, T toElement, boolean toInclusive) { + processQueue(); + return new ReferenceNavigableSet<T>( + set.subSet( + wrapObj(fromElement, false, true), + fromInclusive, + wrapObj(toElement, false, true), + toInclusive + ), getRQF(), getRef()); + } + + public NavigableSet<T> headSet(T toElement, boolean inclusive) { + processQueue(); + return new ReferenceNavigableSet<T>( + set.headSet( + wrapObj(toElement, false, true), inclusive), + getRQF(), + getRef() + ); + } + + public NavigableSet<T> tailSet(T fromElement, boolean inclusive) { + processQueue(); + return new ReferenceNavigableSet<T>( + set.tailSet( + wrapObj(fromElement, false, true), + inclusive), + getRQF(), + getRef() + ); + } + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceProcessor.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceProcessor.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceProcessor.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceProcessor.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,285 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.lang.ref.PhantomReference; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * ReferenceProcessor is responsible for creation and collection of References + * on behalf of Reference Collection implementations. + * + * @param <T> + * @author peter + */ +class ReferenceProcessor<T> implements ReferenceQueuingFactory<T, Referrer<T>> { + + private final static ScheduledExecutorService garbageCleaner = + Executors.newScheduledThreadPool(1, new SystemThreadFactory()); + // Map to register newly created object references. + private final static Map<Reference,ScheduledFuture> finalizerTasks = + new ConcurrentHashMap<Reference,ScheduledFuture>(); + // Finalizer queue to advise cancellation of ScheduledFuture's, + // when their ReferenceProcessor has been collected. + private final static ReferenceQueue<Reference> phantomQueue = + new ReferenceQueue<Reference>(); + static { + // Finizer Task to cancel unneeded tasks. + garbageCleaner.scheduleAtFixedRate( + new FinalizerTask(phantomQueue, finalizerTasks), + 5L, 5L, TimeUnit.MINUTES + ); + } + + private final Collection<Referrer<T>> col; + private final Object colLock; + private final RefQueue<T> queue; + private final Ref type; + private final Lock queueLock; + private final boolean gcThreads; + private volatile boolean started = false; + + ReferenceProcessor(Collection<Referrer<T>> col, Ref type, RefQueue<T> queue, boolean gcThreads, Object lock){ + if (col == null || type == null ) throw new NullPointerException("collection or reference type cannot be null"); + this.col = col; + colLock = lock; + this.type = type; + this.queue = type == Ref.STRONG ? null : queue; + this.gcThreads = gcThreads; + queueLock = new ReentrantLock(); + } + + /** + * Register with executor service and finaliser for cleanup. + * @param GcInterval time interval between scheduled cleaning runs. + */ + public void start(long GcInterval){ + if (started) return; // Start once only. + synchronized (this){ + if (started) return; + started = true; + } + if (queue == null) return; + long enqDelay = GcInterval * (9L/10L); + // Enque garbage task preceeds cleaner task slightly, so we don't + // consume too much memory with massive collections. + // It would be more efficient for the enque task to perform removal + // from the collection while iterating, however it has been left + // this way in case we want to combine time and soft or weak reference + // behaviour in some way. + ScheduledFuture task; + task = ( queue != null && (gcThreads || type.equals(Ref.TIME))) + ? garbageCleaner.scheduleAtFixedRate(new CleanerTask(col, queue), GcInterval, GcInterval, TimeUnit.MILLISECONDS) + : null; + scheduleFinaliserTask(task); + task = (type.equals(Ref.TIME)) + ? garbageCleaner.scheduleAtFixedRate(new EnqueGarbageTask(col, colLock), enqDelay, GcInterval, TimeUnit.MILLISECONDS) + : null; + scheduleFinaliserTask(task); + } + + private void scheduleFinaliserTask(ScheduledFuture task){ + if ( task != null ){ + // Register with finaliser. + @SuppressWarnings("unchecked") + Reference r = new PhantomReference(this, phantomQueue); + finalizerTasks.put(r, task); + } + } + + @Override + public T pseudoReferent(Referrer<T> u) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Referrer<T> referenced(T w, boolean enque, boolean temporary) { + if (w == null) return null; + if (temporary) return ReferenceFactory.singleUseForLookup(w, type); + return ReferenceFactory.create(w, enque == true ? queue : null, type); + } + + @Override + public void processQueue() { + if (queue == null || gcThreads) return; + Object t = null; + /* + * The reason for using an explicit lock is if another thread is + * removing the garbage, we don't want to prevent all other threads + * accessing the underlying collection, when it blocks on poll, + * this means that some client threads will receive null values + * on occassion, but this is a small price to pay. + * Might have to employ the null object pattern. + */ + if ( queueLock.tryLock()){ + try { + while ( (t = queue.poll()) != null){ + col.remove(t); + } + }finally{ + queueLock.unlock(); + } + } + } + + private static class EnqueGarbageTask implements Runnable{ + private final Collection col; + private final Object lock; // This could be the same as col, or a map. + + EnqueGarbageTask(Collection c, Object lock){ + col = c; + this.lock = lock; + } + + public void run() { + long time = System.nanoTime(); + synchronized (lock){ + Iterator it = col.iterator(); + while (it.hasNext()){ + Object r = it.next(); + if (r instanceof TimeBomb) { + ((TimeBomb)r).updateClock(time); + } + } + } + } + + } + + private static class CleanerTask implements Runnable { + + private final Collection col; + private final RefQueue queue; + + private CleanerTask(Collection c, RefQueue queue){ + col = c; + this.queue = queue; + } + + @Override + public void run() { + try { + for ( Object t = queue.poll(); t != null; t = queue.poll()){ + col.remove(t); + } + }catch(Exception e){ + e.printStackTrace(System.err); + } + } + + } + + private static class FinalizerTask implements Runnable { + + private final ReferenceQueue phantomQueue; + private final Map<Reference,ScheduledFuture> finalizerTasks ; + + private FinalizerTask(ReferenceQueue queue, + Map<Reference,ScheduledFuture> tasks){ + phantomQueue = queue; + finalizerTasks = tasks; + } + + @Override + public void run() { + Reference p; + while ( (p = phantomQueue.poll()) != null){ + ScheduledFuture sf = finalizerTasks.remove(p); + if (sf !=null) sf.cancel(true); + // phantom reference is eligible for gc we don't have to + // clear it, but might as well. + p.clear(); + } + } + + } + + private static class SystemThreadFactory implements ThreadFactory{ + private static final ThreadGroup g; + + static { + ThreadGroup tg = Thread.currentThread().getThreadGroup(); + g = AccessController.doPrivileged( new ThreadGroupAction(tg)); + } + + private SystemThreadFactory(){ + } + + @Override + public Thread newThread(Runnable r) { + return AccessController.doPrivileged( new CreateThread(g, r)); + } + + } + + private static class ThreadGroupAction implements PrivilegedAction<ThreadGroup>{ + private ThreadGroup tg; + + ThreadGroupAction(ThreadGroup g){ + tg = g; + } + public ThreadGroup run() { + try { + ThreadGroup parent = tg.getParent(); + while (parent != null){ + tg = parent; + parent = tg.getParent(); + } + }catch (SecurityException e){ + Logger.getLogger(ReferenceProcessor.class.getName()).log(Level.FINE, "Unable to get parent thread group", e); + } + return tg; + } + } + + private static class CreateThread implements PrivilegedAction<Thread>{ + private ThreadGroup g; + private Runnable r; + + CreateThread(ThreadGroup g, Runnable r){ + this.g = g; + this.r = r; + } + public Thread run() { + Thread t = new Thread(g, r); + try { + t.setContextClassLoader(null); + t.setPriority(Thread.MAX_PRIORITY); + } catch (SecurityException e){ + Logger.getLogger(ReferenceProcessor.class.getName()).log(Level.FINE, "Unable to set ContextClassLoader or Priority", e); + } + return t; + } + + } + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceQueuingFactory.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceQueuingFactory.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceQueuingFactory.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceQueuingFactory.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,40 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +/** + * An interface for processing ReferenceQueue's and encapsulating Objects + * in references and for making references appear as their referent. + * + * @author Peter Firmstone + */ +interface ReferenceQueuingFactory<O, R> { + + O pseudoReferent(R u); + + R referenced(O w, boolean enque, boolean temporary); + + /** + * This method was originally intended to process the reference queue + * prior to access, however this severely hurts scalability. Now + * reference queue's are processed with a background garbage collection + * thread. + * + * @deprecated + */ + void processQueue(); + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSerializationFactory.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSerializationFactory.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSerializationFactory.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSerializationFactory.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,31 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +/** + * + * @author Peter Firmstone. + */ +class ReferenceSerializationFactory<T> { + + // Not instantiable. + private ReferenceSerializationFactory(){} + + static <T> Referrer<T> create(T t) { + return new ReferenceSerializedForm<T>(t); + } + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSerializedForm.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSerializedForm.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSerializedForm.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSerializedForm.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,98 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +/** + * A temporary but functional replacement for ReferenceKey's. No attempt is + * made to use readResolve to replace the original, that responsibility is left + * up to the collection implementation during de-serialisation. + * + * @author peter + */ +class ReferenceSerializedForm<T> implements Referrer<T>, Serializable{ + private static final long serialVersionUID = 1L; + + private T obj; + private transient int hash; + + ReferenceSerializedForm(){ + obj = null; + hash = 0; + } + + ReferenceSerializedForm(T t){ + obj = t; + int hash = 7; + hash = 29 * hash + System.identityHashCode(t); + hash = 29 * hash + (t!= null ? t.getClass().hashCode() :0); + this.hash = hash; + } + + public T get() { + T t = obj; + obj = null; + return t; + } + + public void clear() { + obj = null; + } + + public boolean isEnqueued() { + return false; + } + + public boolean enqueue() { + return false; + } + + /* In this case we're using Identity because it has a wider scope. + */ + @Override + public boolean equals(Object o) { + if (this == o) return true; // Same reference. + if (!(o instanceof Referrer)) return false; + Object k1 = get(); + Object k2 = ((Referrer) o).get(); + if ( k1 != null && k1 == k2) return true; + return ( k1 == null && k2 == null && hashCode() == o.hashCode()); // Both objects were collected. + } + + @Override + public int hashCode() { + return hash; + } + + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException { + in.defaultReadObject(); + int hash = 7; + hash = 29 * hash + System.identityHashCode(obj); + hash = 29 * hash + (obj != null ? obj.getClass().hashCode() :0); + this.hash = hash; + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + } + + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSet.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSet.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSet.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSet.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,74 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.util.Iterator; +import java.util.Set; + +/** + * A Referenced Set. + * + * + * @see ReferenceCollection + * @author Peter Firmstone. + */ +class ReferenceSet<T> extends ReferenceCollection<T> implements Set<T>{ + private static final long serialVersionUID = 1L; + + ReferenceSet(Set<Referrer<T>> col, Ref type, boolean gcThreads, long gcCycle){ + super(col, type, gcThreads, gcCycle); + } + + ReferenceSet(Set<Referrer<T>> col, ReferenceQueuingFactory<T, Referrer<T>> rqf, Ref type){ + super(col, rqf, type); + } + + private void readObject(ObjectInputStream stream) + throws InvalidObjectException{ + throw new InvalidObjectException("Builder required"); + } + + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof Set)) return false; + @SuppressWarnings("unchecked") + Set<T> s = (Set<T>) o; + if (s.size() != size()) + return false; + try { + return containsAll(s); + } catch (ClassCastException e) { + return false; + } catch (NullPointerException e) { + return false; +} + } + + @Override + public int hashCode() { + int hash = 0; + Iterator<T> i = iterator(); + while (i.hasNext()){ + T next = i.next(); + if ( next != null) { + hash = hash + next.hashCode(); + } + } + return hash; + } +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSortedMap.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSortedMap.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSortedMap.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSortedMap.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,98 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.lang.ref.Reference; +import java.util.Comparator; +import java.util.SortedMap; + +/** + * + * @param <K> + * @param <V> + * @author peter + */ +class ReferenceSortedMap<K,V> extends ReferenceMap<K,V> implements SortedMap<K,V>{ + private SortedMap<Referrer<K>, Referrer<V>> map; + + ReferenceSortedMap(SortedMap<Referrer<K>, Referrer<V>> map, Ref keyRef, Ref valRef, boolean gcThreads, long gcKeyCycle, long gcValCycle){ + super(map, keyRef, valRef, gcThreads, gcKeyCycle, gcValCycle); + this.map = map; + } + + ReferenceSortedMap(SortedMap<Referrer<K>, Referrer<V>> map, + ReferenceQueuingFactory<K, Referrer<K>> krqf, + ReferenceQueuingFactory<V, Referrer<V>> vrqf, Ref key, Ref val){ + super(map, krqf, vrqf, key, val); + this.map = map; + } + + @SuppressWarnings("unchecked") + public Comparator<? super K> comparator() { + processQueue(); + Comparator<? super Referrer<K>> c = map.comparator(); + if ( c instanceof ReferenceComparator){ + return ((ReferenceComparator) c).get(); + } + return null; + } + + public SortedMap<K, V> subMap(K fromKey, K toKey) { + processQueue(); + return new ReferenceSortedMap<K,V>( + map.subMap(wrapKey(fromKey, false, true), wrapKey(toKey, false, true)), + getKeyRQF(), + getValRQF(), keyRef(), valRef() + ); + } + + + public SortedMap<K, V> headMap(K toKey) { + processQueue(); + return new ReferenceSortedMap<K,V>( + map.headMap(wrapKey(toKey, false, true)), + getKeyRQF(), + getValRQF(), keyRef(), valRef() + ); + } + + + public SortedMap<K, V> tailMap(K fromKey) { + processQueue(); + return new ReferenceSortedMap<K,V>( + map.tailMap(wrapKey(fromKey, false, true)), + getKeyRQF(), + getValRQF(), keyRef(), valRef() + ); + } + + + public K firstKey() { + processQueue(); + Referrer<K> k = map.firstKey(); + if (k != null) return k.get(); + return null; + } + + + public K lastKey() { + processQueue(); + Referrer<K> k = map.lastKey(); + if (k != null) return k.get(); + return null; + } + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSortedSet.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSortedSet.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSortedSet.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferenceSortedSet.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,95 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.util.Comparator; +import java.util.SortedSet; + +/** + * Referenced set supports sorting Object based on their natural ordering + * or a Comparator, which must be wrapped in a ReferenceComparator. + * + * @param <T> + * @see Comparable + * @see Comparator + * @see ReferenceComparator + * @author Peter Firmstone. + */ +class ReferenceSortedSet<T> extends ReferenceSet<T> implements SortedSet<T> { + private static final long serialVersionUID = 1L; + private final SortedSet<Referrer<T>> set; + + ReferenceSortedSet( SortedSet<Referrer<T>> set, Ref type, boolean gcThreads, long gcCycle){ + super(set, type, gcThreads, gcCycle); + this.set = set; + } + + ReferenceSortedSet(SortedSet<Referrer<T>> set, ReferenceQueuingFactory<T, Referrer<T>> rqf, Ref type){ + super(set, rqf, type); + this.set = set; + } + + private void readObject(ObjectInputStream stream) + throws InvalidObjectException{ + throw new InvalidObjectException("Builder required"); + } + + @SuppressWarnings("unchecked") + public Comparator<? super T> comparator() { + processQueue(); + Comparator<? super Referrer<T>> c = set.comparator(); + if ( c instanceof ReferenceComparator){ + return ((ReferenceComparator) c).get(); + } + return null; + } + + public SortedSet<T> subSet(T fromElement, T toElement) { + processQueue(); + Referrer<T> from = wrapObj(fromElement, false, true); + Referrer<T> to = wrapObj(toElement, false, true); + return new ReferenceSortedSet<T>( set.subSet(from, to), getRQF(), getRef()); + } + + public SortedSet<T> headSet(T toElement) { + processQueue(); + Referrer<T> to = wrapObj(toElement, false, true); + return new ReferenceSortedSet<T>(set.headSet(to), getRQF(), getRef()); + } + + public SortedSet<T> tailSet(T fromElement) { + processQueue(); + Referrer<T> from = wrapObj(fromElement, false, true); + return new ReferenceSortedSet<T>(set.tailSet(from), getRQF(), getRef()); + } + + public T first() { + processQueue(); + Referrer<T> t = set.first(); + if ( t != null ) return t.get(); + return null; + } + + public T last() { + processQueue(); + Referrer<T> t = set.last(); + if ( t != null ) return t.get(); + return null; + } + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferencedQueue.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferencedQueue.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferencedQueue.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferencedQueue.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,82 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.util.NoSuchElementException; +import java.util.Queue; + +/** + * + * @param <T> + * @author Peter Firmstone. + */ +class ReferencedQueue<T> extends ReferenceCollection<T> implements Queue<T> { + private static final long serialVersionUID = 1L; + private final Queue<Referrer<T>> queue; + + public ReferencedQueue( Queue<Referrer<T>> queue, Ref type, boolean gcThreads, long gcCycle){ + super(queue, type, gcThreads, gcCycle); + this.queue = queue; + } + + private void readObject(ObjectInputStream stream) + throws InvalidObjectException{ + throw new InvalidObjectException("Builder required"); + } + + public boolean offer(T e) { + processQueue(); + Referrer<T> r = wrapObj(e, true, false); + return queue.offer(r); + } + + public T remove() { + processQueue(); + do { + Referrer<T> r = queue.remove(); + T t = r == null? null: r.get(); + if (t != null) return t; + } while (!queue.isEmpty()); + throw new NoSuchElementException("Queue is empty"); + } + + public T poll() { + processQueue(); + do { + Referrer<T> r = queue.poll(); + T t = r == null? null: r.get(); + if (t != null) return t; + } while (!queue.isEmpty()); + return null; + } + + public T element() { + processQueue(); + Referrer<T> t = queue.element(); + if ( t != null ) return t.get(); + return null; + } + + public T peek() { + processQueue(); + Referrer<T> t = queue.peek(); + if ( t != null ) return t.get(); + return null; + } + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/Referrer.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/Referrer.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/Referrer.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/Referrer.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,110 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.lang.ref.Reference; + +/** + * <p> + * The public API of package private Reference implementations, it defines the equals + * and hashCode contracts as well as methods identical to Reference. + * </p> + * @see Reference + * @see Ref + * @param <T> Referent + * @author Peter Firmstone + */ +public interface Referrer<T> { + + /** + * @see Reference#get() + */ + public T get() ; + /** + * @see Reference#clear() + */ + public void clear(); + /** + * @see Reference#isEnqueued() + * @return true if enqueued. + */ + public boolean isEnqueued(); + /** + * @see Reference#enqueue() + * @return true if successfully enqueued. + */ + public boolean enqueue(); + + /** + * <p> + * Equals is calculated on IDENTITY or EQUALITY. + * </p> + * IDENTITY calculation:<BR> + * <BR><CODE> + * if (this == o) return true;<BR> + * if (!(o instanceof Referrer)) return false;<BR> + * Object k1 = get();<BR> + * Object k2 = ((Referrer) o).get();<BR> + * if ( k1 != null && k1 == k2 ) return true;<BR> + * return ( k1 == null && k2 == null && hashCode() == o.hashCode());<BR> + * </CODE> + * <BR> + * EQUALITY calculation:<BR> + * <BR><CODE> + * if (this == o) return true; // Same reference.<BR> + * if (!(o instanceof Referrer)) return false;<BR> + * Object k1 = get();<BR> + * Object k2 = ((Referrer) o).get();<BR> + * if ( k1 != null && k1.equals(k2)) return true;<BR> + * return ( k1 == null && k2 == null && hashCode() == o.hashCode());<BR> + * <BR> + * + * @see Ref + * @param o + * @return true if equal + */ + public boolean equals(Object o); + + /** + * <p> + * Standard hashCode calculation for IDENTITY based references, where k + * is the referent. This may be stored in a final field: + * </p> + * <BR><CODE> + * int hash = 7;<BR> + * hash = 29 * hash + System.identityHashCode(k);<BR> + * hash = 29 * hash + k.getClass().hashCode();<BR> + * </CODE> + * <BR> + * <p> + * Standard hashCode calculation for EQUALITY based references, where k + * is the referent: + * </p> + * <BR><CODE> + * int hash = 7;<BR> + * hash = 29 * hash + k.hashCode();<BR> + * hash = 29 * hash + k.getClass().hashCode();<BR> + * </CODE> + * <BR> + * <p> + * The hash must be calculated during construction and if the reference is + * cleared, the recorded hashCode returned. While the referent remains + * reachable the hashCode must be calculated each time. + * </p> + * @return hash + */ + public int hashCode(); +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferrerDecorator.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferrerDecorator.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferrerDecorator.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/ReferrerDecorator.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,70 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +/** + * I've thought about refactoring so the equals and comparator behaviour is + * implemented by the wrapper classes and only accepting References in + * constructors as this would allow the use of standard java Reference classes + * without extension, reducing the number of classes created, + * however that would create serial form lock in. The current arrangement + * allows for + * + * + * + * @author peter + */ +class ReferrerDecorator<T> extends AbstractReferrerDecorator<T> implements Serializable{ + private static final long serialVersionUID = 1L; + + /** + * @serialField + */ + private volatile Referrer<T> reference; + + ReferrerDecorator(Referrer<T> ref){ + if (ref == null) throw new NullPointerException("Referrer cannot be null"); + reference = ref; + } + + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException { + in.defaultReadObject(); + if (getReference() == null) throw new IOException("Attempt to write null Referrer"); + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + } + + @Override + public void refresh(Referrer<T> r) { + reference = r; + } + + /** + * @return the reference + */ + public Referrer<T> getReference() { + return reference; + } + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/SerializationOfReferenceCollection.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/SerializationOfReferenceCollection.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/SerializationOfReferenceCollection.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/SerializationOfReferenceCollection.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,38 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.io.ObjectStreamException; +import java.util.AbstractCollection; +import java.util.Collection; + +/** + * + * @author peter + */ +abstract class SerializationOfReferenceCollection<T> extends AbstractCollection<T> { + + static <T> SerializationOfReferenceCollection<T> create( + Class clazz, + Collection<Referrer<T>> refCol, + Ref type) throws InstantiationException, IllegalAccessException{ + return new ReferenceCollectionSerialData<T>(clazz, refCol, type); + } + + abstract Collection<T> build() throws InstantiationException, + IllegalAccessException, ObjectStreamException; + +} Added: river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/SerializationOfReferenceMap.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/SerializationOfReferenceMap.java?rev=1702174&view=auto ============================================================================== --- river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/SerializationOfReferenceMap.java (added) +++ river/jtsk/skunk/qa-refactor-namespace/trunk/src/org/apache/river/concurrent/SerializationOfReferenceMap.java Thu Sep 10 06:59:28 2015 @@ -0,0 +1,38 @@ +/* Copyright (c) 2010-2012 Zeus Project Services Pty Ltd. + * + * 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.apache.river.concurrent; + +import java.io.ObjectStreamException; +import java.util.AbstractMap; +import java.util.Map; + +/** + * + * @author peter + */ +abstract class SerializationOfReferenceMap<K,V> extends AbstractMap<K,V>{ + + static <K,V> SerializationOfReferenceMap<K,V> create( + Class clazz, + Map<Referrer<K>, Referrer<V>> refmap, + Ref type) throws InstantiationException, IllegalAccessException{ + return null; + // return new ReferenceMapSerialData<K,V>(clazz, refmap, type); + } + + abstract Map<K,V> build() throws InstantiationException, + IllegalAccessException, ObjectStreamException; +}
