Java tutorial
/* * CoarseHashSet.java * * Created on December 29, 2005, 11:50 PM * * From "The Art of Multiprocessor Programming", * by Maurice Herlihy and Nir Shavit. * * This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License. * http://i.creativecommons.org/l/by-sa/3.0/us/88x31.png */ //package xbird.util.concurrent.set; import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * Coarse-grained hash set. * @param <T> type * @author Maurice Herlihy */ public class CoarseHashSet<T> extends BaseHashSet<T> { final Lock lock; CoarseHashSet(int capacity) { super(capacity); lock = new ReentrantLock(); } /** * double the set size */ @Override public void resize() { int oldCapacity = table.length; lock.lock(); try { if (oldCapacity != table.length) { return; // someone beat us to it } int newCapacity = 2 * oldCapacity; List<T>[] oldTable = table; table = (List<T>[]) new List[newCapacity]; for (int i = 0; i < newCapacity; i++) table[i] = new ArrayList<T>(); for (List<T> bucket : oldTable) { for (T x : bucket) { int myBucket = Math.abs(x.hashCode() % table.length); table[myBucket].add(x); } } } finally { lock.unlock(); } } /** * Synchronize before adding, removing, or testing for item * @param x item involved */ @Override public final void acquire(T x) { lock.lock(); } /** * synchronize after adding, removing, or testing for item * @param x item involved */ @Override public void release(T x) { lock.unlock(); } @Override public boolean policy() { return size / table.length > 4; } } /** * Simple fine-grained hash map. * @param <T> type * @author Maurice Herlihy */ abstract class BaseHashSet<T> { protected List<T>[] table; protected int size; public BaseHashSet(int capacity) { size = 0; table = (List<T>[]) new List[capacity]; for (int i = 0; i < capacity; i++) { table[i] = new ArrayList<T>(); } } /** * Is item in set? * @param x item to test * @return <code>true</code> iff item present */ public boolean contains(T x) { acquire(x); try { int myBucket = Math.abs(x.hashCode() % table.length); return table[myBucket].contains(x); } finally { release(x); } } /** * Add item to set * @param x item to add * @return <code>true</code> iff set changed */ public boolean add(T x) { boolean result = false; acquire(x); try { int myBucket = Math.abs(x.hashCode() % table.length); result = table[myBucket].add(x); size = result ? size + 1 : size; } finally { release(x); // always unlock } if (policy()) resize(); return result; } /** * Remove item from set * @param x item to remove * @return <code>true</code> iff set changed */ public boolean remove(T x) { acquire(x); try { int myBucket = Math.abs(x.hashCode() % table.length); boolean result = table[myBucket].remove(x); size = result ? size - 1 : size; return result; } finally { release(x); // always unlock } } /** * Synchronize before adding, removing, or testing for item * @param x item involved */ public abstract void acquire(T x); /** * synchronize after adding, removing, or testing for item * @param x item involved */ public abstract void release(T x); /** * double the set size */ public abstract void resize(); /** * decide whether to resize * @return whether to resize */ public abstract boolean policy(); }