Package xbird.util.concurrent.collections.set

Source Code of xbird.util.concurrent.collections.set.TCuckooHashSet$Intent

/*
* TCuckooHashSet.java
*
* Created on May 12, 2006, 11:01 AM
*
* 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.collections.set;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.TreeSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* Concurrent Cuckoo hashing.
* @param <T> type
* @author Maurice Herlihy
*/
public class TCuckooHashSet<T> {
    volatile T[][] table;
    volatile int size;
    static final int LIMIT = 32;
    static final int LOCKS = 8;
    Lock[][] locks;
    // used for resizeing
    Random random = new Random();

    /**
     * Constructor
     * @param capacity Initial array size.
     */
    public TCuckooHashSet(int capacity) {
        locks = new Lock[2][LOCKS];
        table = (T[][]) new Object[2][capacity];
        size = capacity;
        for(int i = 0; i < 2; i++) {
            for(int j = 0; j < LOCKS; j++) {
                locks[i][j] = new ReentrantLock();
            }
        }
    }

    private final int hash0(Object x) {
        return Math.abs(x.hashCode() % size);
    }

    private final int hash1(Object x) {
        random.setSeed(x.hashCode());
        return random.nextInt(size);
    }

    /**
     * Is item in set?
     * @param x Item to test.
     * @return <code>true</code> iff item is present.
     */
    public boolean contains(T x) {
        if(x == null) {
            throw new IllegalArgumentException();
        }
        int h0 = hash0(x);
        Lock lock0 = locks[0][h0 % LOCKS];
        try {
            lock0.lock();
            if(x.equals(table[0][h0])) {
                return true;
            } else {
                int h1 = hash1(x);
                Lock lock1 = locks[1][h1 % LOCKS];
                try {
                    lock1.lock();
                    if(x.equals(table[1][h1])) {
                        return true;
                    }
                    return false;
                } finally {
                    lock1.unlock();
                }
            }
        } finally {
            lock0.unlock();
        }
    }

    /**
     * Remove item from set.
     * @param x Item to remove.
     * @return <code>true</code> iff set was changed.
     */
    public boolean remove(T x) {
        if(x == null) {
            throw new IllegalArgumentException();
        }
        int h0 = hash0(x);
        Lock lock0 = locks[0][h0 % LOCKS];
        try {
            lock0.lock();
            if(x.equals(table[0][h0])) {
                table[0][h0] = null;
                return true;
            } else {
                int h1 = hash1(x);
                Lock lock1 = locks[1][h1 % LOCKS];
                try {
                    lock1.lock();
                    if(x.equals(table[1][h1])) {
                        table[1][h1] = null;
                        return true;
                    }
                    return false;
                } finally {
                    lock1.unlock();
                }
            }
        } finally {
            lock0.unlock();
        }
    }

    /**
     * Add item to set.
     * @param x Item to add.
     * @return <code>true</code> iff set was changed.
     */
    public boolean add(T x) {
        if(x == null) {
            throw new IllegalArgumentException();
        }
        TreeSet<Intent>[] intentions = (TreeSet<Intent>[]) new TreeSet[2];
        for(int i = 0; i < intentions.length; i++) {
            intentions[i] = new TreeSet<Intent>();
        }
        List<Lock> acquired = new ArrayList<Lock>(locks.length);
        while(true) { // forever true
            try {
                // already present?
                if(optContains(intentions, x)) {
                    if(validate(intentions, acquired)) {
                        return false;
                    } else {
                        continue;
                    }
                }
                // not already present?
                if(optAdd(intentions, x)) {
                    if(validate(intentions, acquired)) {
                        doAdd(x);
                        return true;
                    } else {
                        continue;
                    }
                }
            } finally {
                release(acquired);
                intentions[0].clear();
                intentions[1].clear();
            }
        }
    }

    private void release(List<Lock> acquired) {
        for(Lock lock : acquired) {
            lock.unlock();
        }
        acquired.clear();
    }

    private T swap(int i, int j, T value) {
        T result = table[i][j];
        table[i][j] = value;
        return result;
    }

    protected boolean optContains(TreeSet<Intent>[] intentions, T x) {
        int h0 = hash0(x);
        T y = table[0][h0];
        intentions[0].add(new Intent(h0, y));
        if(x.equals(y)) {
            return true;
        } else {
            int h1 = hash1(x);
            y = table[1][h1];
            intentions[1].add(new Intent(h1, y));
            if(x.equals(y)) {
                return true;
            }
            return false;
        }
    }

    boolean validate(TreeSet<Intent>[] intentions, List<Lock> acquired) {
        for(int phase = 0; phase < 2; phase++) {
            for(Intent intent : intentions[phase]) {
                // lock and prepare to unlock
                Lock lock = locks[phase][intent.index % LOCKS];
                lock.lock();
                acquired.add(lock);
                // beware that expected could be null
                T expected = intent.item;
                T found = table[phase][intent.index];
                if(expected == null) {
                    if(found != null) {
                        return false;
                    }
                } else if(!expected.equals(found)) {
                    return false;
                }
            }
        }
        return true;
    }

    void unlock(TreeSet<Intent>[] intentions) {
        for(int phase = 0; phase < 2; phase++) {
            for(Intent intent : intentions[phase]) {
                locks[phase][intent.index % LOCKS].unlock();
            }
        }
    }

    boolean optAdd(TreeSet<Intent>[] intentions, T x) {
        for(int i = 0; i < LIMIT; i++) {
            int h0 = hash0(x);
            x = table[0][h0];
            intentions[0].add(new Intent(h0, x));
            if(x == null) {
                return true;
            } else {
                int h1 = hash1(x);
                x = table[1][h1];
                intentions[1].add(new Intent(h1, x));
                if(x == null) {
                    return true;
                }
            }
        }
        resize(size);
        return false;
    }

    void doAdd(T x) {
        for(int i = 0; i < LIMIT; i++) {
            if((x = swap(0, hash0(x), x)) == null) {
                return;
            } else if((x = swap(1, hash1(x), x)) == null) {
                return;
            }
        }
    }

    void resize(int oldSize) {
        if(size > oldSize) { // someone beat us to it
            return;
        }
        for(int i = 0; i < 2; i++) {
            for(int j = 0; j < LOCKS; j++) {
                locks[i][j].lock();
            }
        }
        T[][] oldtable = table;
        size = 2 * size;
        table = (T[][]) new Object[2][size];
        for(int i = 0; i < 2; i++) {
            for(T x : oldtable[i]) {
                if(x != null) {
                    add(x);
                }
            }
        }
        for(int i = 0; i < 2; i++) {
            for(int j = 0; j < LOCKS; j++) {
                locks[i][j].unlock();
            }
        }
    }

    class Intent implements Comparable<Intent> {
        public int index;
        public T item;

        Intent(int index, T item) {
            this.index = index;
            this.item = item;
        }

        public int compareTo(TCuckooHashSet.Intent o) {
            // equal items never compared
            if((this.index % LOCKS) < (o.index % LOCKS)) {
                return -1;
            } else if((this.index % LOCKS) > (o.index % LOCKS)) {
                return 1;
            } else {
                return 0;
            }
        }

    }
}
TOP

Related Classes of xbird.util.concurrent.collections.set.TCuckooHashSet$Intent

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.