Clover coverage report - PLT Utilities Test Coverage (plt-20120304-r5436)
Coverage timestamp: Sat Mar 3 2012 22:01:56 CST
file stats: LOC: 122   Methods: 18
NCLOC: 51   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
SnapshotSynchronizedSet.java 50% 47.8% 33.3% 41.9%
coverage coverage
 1    /*BEGIN_COPYRIGHT_BLOCK*
 2   
 3    PLT Utilities BSD License
 4   
 5    Copyright (c) 2007-2010 JavaPLT group at Rice University
 6    All rights reserved.
 7   
 8    Developed by: Java Programming Languages Team
 9    Rice University
 10    http://www.cs.rice.edu/~javaplt/
 11   
 12    Redistribution and use in source and binary forms, with or without modification, are permitted
 13    provided that the following conditions are met:
 14   
 15    - Redistributions of source code must retain the above copyright notice, this list of conditions
 16    and the following disclaimer.
 17    - Redistributions in binary form must reproduce the above copyright notice, this list of
 18    conditions and the following disclaimer in the documentation and/or other materials provided
 19    with the distribution.
 20    - Neither the name of the JavaPLT group, Rice University, nor the names of the library's
 21    contributors may be used to endorse or promote products derived from this software without
 22    specific prior written permission.
 23   
 24    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 25    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 26    FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND
 27    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 28    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 29    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 30    IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 31    OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 32   
 33    *END_COPYRIGHT_BLOCK*/
 34   
 35    package edu.rice.cs.plt.collect;
 36   
 37    import java.io.Serializable;
 38    import java.util.*;
 39   
 40    import edu.rice.cs.plt.iter.IterUtil;
 41    import edu.rice.cs.plt.lambda.CachedThunk;
 42    import edu.rice.cs.plt.lambda.Thunk;
 43   
 44    /**
 45    * A synchronized set like {@link Collections#synchronizedSet}, but one that returns a snapshot of
 46    * the set contents on invocations of {@code iterator()}. In contrast to
 47    * {@link java.util.concurrent.CopyOnWriteArraySet}, copies are only made when needed for iteration; other
 48    * operations use locking to support concurrency. The snapshot strategy has the following advantages over
 49    * {@link Collections#synchronizedSet}: 1) Thread safety during iteration is guaranteed; 2) the set is
 50    * interchangeable with other types of sets, even in contexts that perform iteration; 3) concurrent access to
 51    * the set is not blocked during iteration; and 4) the set can be directly mutated by the iteration loop
 52    * (on the other hand, removing elements via the iterator is not supported). Note, also, that operations on
 53    * this set cannot be blocked by synchronizing on the set itself. To support these differences, the
 54    * implementation must make a copy whenever {@code iterator()} is invoked after the set has been mutated;
 55    * that copy is cached with the set (optimizing the performance of subsequent calls, but doubling the
 56    * set's memory footprint).
 57    */
 58    public class SnapshotSynchronizedSet<E> extends DelegatingSet<E> {
 59    private final CachedThunk<Iterable<E>> _copy;
 60   
 61  12 public SnapshotSynchronizedSet(Set<E> delegate) {
 62  12 super(Collections.synchronizedSet(delegate));
 63  12 _copy = CachedThunk.make(new Thunk<Iterable<E>>() {
 64  9 public Iterable<E> value() {
 65  9 synchronized(_delegate) {
 66  9 return IterUtil.snapshot(_delegate.iterator());
 67    }
 68    }
 69    });
 70    }
 71   
 72    /**
 73    * Discard the cached copy of the set, if it exists. This minimizes this set's memory footprint, but
 74    * forces the copy to be recalculated when {@link #iterator} is next invoked. Has no effect if
 75    * {@code iterator()} has not been invoked since the last mutating operation.
 76    */
 77  0 public void discardSnapshot() { _copy.reset(); }
 78   
 79    /** Reset the copy thunk if {@code changed} is {@code true}; return {@code changed}. */
 80  9 private boolean reset(boolean changed) {
 81  9 if (changed) { _copy.reset(); }
 82  9 return changed;
 83    }
 84   
 85  9 @Override public Iterator<E> iterator() { return _copy.value().iterator(); }
 86   
 87  0 @Override public boolean add(E o) { return reset(_delegate.add(o)); }
 88  0 @Override public boolean addAll(Collection<? extends E> c) { return reset(_delegate.addAll(c)); }
 89  9 @Override public void clear() { _delegate.clear(); reset(true); }
 90  0 @Override public boolean remove(Object o) { return reset(_delegate.remove(o)); }
 91  0 @Override public boolean removeAll(Collection<?> c) { return reset(_delegate.removeAll(c)); }
 92  0 @Override public boolean retainAll(Collection<?> c) { return reset(_delegate.retainAll(c)); }
 93   
 94    /** Get a thunk that invokes the constructor with sets produced by the given factory. */
 95  0 public static <T> Thunk<Set<T>> factory(Thunk<? extends Set<T>> delegateFactory) {
 96  0 return new Factory<T>(delegateFactory);
 97    }
 98   
 99    private static final class Factory<T> implements Thunk<Set<T>>, Serializable {
 100    private final Thunk<? extends Set<T>> _delegateFactory;
 101  0 private Factory(Thunk<? extends Set<T>> delegateFactory) { _delegateFactory = delegateFactory; }
 102  0 public Set<T> value() { return new SnapshotSynchronizedSet<T>(_delegateFactory.value()); }
 103    }
 104   
 105    /** Call the constructor (allows {@code T} to be inferred). */
 106  0 public static <T> SnapshotSynchronizedSet<T> make(Set<T> delegate) {
 107  0 return new SnapshotSynchronizedSet<T>(delegate);
 108    }
 109    /** Call the constructor with an empty HashSet. */
 110  0 public static <T> SnapshotSynchronizedSet<T> makeHash() {
 111  0 return new SnapshotSynchronizedSet<T>(new HashSet<T>());
 112    }
 113    /** Call the constructor with an empty LinkedHashSet. */
 114  12 public static <T> SnapshotSynchronizedSet<T> makeLinkedHash() {
 115  12 return new SnapshotSynchronizedSet<T>(new LinkedHashSet<T>());
 116    }
 117    /** Call the constructor with an empty TreeSet. */
 118  0 public static <T> SnapshotSynchronizedSet<T> makeTree() {
 119  0 return new SnapshotSynchronizedSet<T>(new TreeSet<T>());
 120    }
 121   
 122    }