001: /*
002: * Written by Doug Lea with assistance from members of JCP JSR-166
003: * Expert Group and released to the public domain. Use, modify, and
004: * redistribute this code in any way without acknowledgement.
005: */
006:
007: package java.util.concurrent;
008:
009: import java.util.*;
010:
011: /**
012: * A {@link java.util.Set} that uses {@link
013: * java.util.concurrent.CopyOnWriteArrayList} for all of its
014: * operations. Thus, it shares the same basic properties:
015: * <ul>
016: * <li>It is best suited for applications in which set sizes generally
017: * stay small, read-only operations
018: * vastly outnumber mutative operations, and you need
019: * to prevent interference among threads during traversal.
020: * <li>Mutative operations(add, set, remove, etc) are expensive
021: * since they usually entail copying the entire underlying array.
022: * <li>Iterators do not support the mutative remove operation
023: * <li>Traversal via iterators is very fast and cannot ever encounter
024: * interference from other threads. Iterators rely on
025: * unchanging snapshots of the array at the time the iterators were
026: * constructed.
027: * </ul>
028: * <p>
029: * <b>Sample Usage.</b> Probably the main application
030: * of copy-on-write sets are classes that maintain
031: * sets of Handler objects
032: * that must be multicasted to upon an update command. This
033: * is a classic case where you do not want to be holding a
034: * lock while sending a message, and where traversals normally
035: * vastly overwhelm additions.
036: * <pre>
037: * class Handler { void handle(); ... }
038: *
039: * class X {
040: * private final CopyOnWriteArraySet<Handler> handlers = new CopyOnWriteArraySet<Handler>();
041: * public void addHandler(Handler h) { handlers.add(h); }
042: *
043: * private long internalState;
044: * private synchronized void changeState() { internalState = ...; }
045: *
046: * public void update() {
047: * changeState();
048: * Iterator it = handlers.iterator();
049: * while (it.hasNext())
050: * it.next().handle();
051: * }
052: * }
053: * </pre>
054: * @see CopyOnWriteArrayList
055: *
056: * <p>This class is a member of the
057: * <a href="{@docRoot}/../guide/collections/index.html">
058: * Java Collections Framework</a>.
059: *
060: * @since 1.5
061: * @author Doug Lea
062: * @param <E> the type of elements held in this collection
063: */
064: public class CopyOnWriteArraySet<E> extends AbstractSet<E> implements
065: Cloneable, java.io.Serializable {
066: private static final long serialVersionUID = 5457747651344034263L;
067:
068: private final CopyOnWriteArrayList<E> al;
069:
070: /**
071: * Creates an empty set.
072: */
073: public CopyOnWriteArraySet() {
074: al = new CopyOnWriteArrayList<E>();
075: }
076:
077: /**
078: * Creates a set containing all of the elements of the specified
079: * Collection.
080: * @param c the collection
081: */
082: public CopyOnWriteArraySet(Collection<? extends E> c) {
083: al = new CopyOnWriteArrayList<E>();
084: al.addAllAbsent(c);
085: }
086:
087: public int size() {
088: return al.size();
089: }
090:
091: public boolean isEmpty() {
092: return al.isEmpty();
093: }
094:
095: public boolean contains(Object o) {
096: return al.contains(o);
097: }
098:
099: public Object[] toArray() {
100: return al.toArray();
101: }
102:
103: public <T> T[] toArray(T[] a) {
104: return al.toArray(a);
105: }
106:
107: public void clear() {
108: al.clear();
109: }
110:
111: public Iterator<E> iterator() {
112: return al.iterator();
113: }
114:
115: public boolean remove(Object o) {
116: return al.remove(o);
117: }
118:
119: public boolean add(E o) {
120: return al.addIfAbsent(o);
121: }
122:
123: public boolean containsAll(Collection<?> c) {
124: return al.containsAll(c);
125: }
126:
127: public boolean addAll(Collection<? extends E> c) {
128: return al.addAllAbsent(c) > 0;
129: }
130:
131: public boolean removeAll(Collection<?> c) {
132: return al.removeAll(c);
133: }
134:
135: public boolean retainAll(Collection<?> c) {
136: return al.retainAll(c);
137: }
138:
139: }
|