Package xbird.util.concurrent.collections.set

Source Code of xbird.util.concurrent.collections.set.RefinableCuckooHashSet

/*
* RefinableCuckooHashSet.java
*
* Created on November 1, 2006, 4:49 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.collections.set;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicMarkableReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* Version of concurrent Cuckoo hashing that allows the lock array to be resized.
  * @param <T> type
* @author Maurice Herlihy
*/
public class RefinableCuckooHashSet<T> extends PhasedCuckooHashSet<T> {
    AtomicMarkableReference<Thread> owner;
    volatile ReentrantLock[][] locks;

    /**
     * Concurrent Cuckoo hash set. Resizes lock array.
     * @param capacity Initial bucket size.
     */
    public RefinableCuckooHashSet(int capacity) {
        super(capacity);
        locks = new ReentrantLock[2][capacity];
        for(int i = 0; i < 2; i++) {
            for(int j = 0; j < capacity; j++) {
                locks[i][j] = new ReentrantLock();
            }
        }
        owner = new AtomicMarkableReference<Thread>(null, false);
    }

    /**
     * Synchronize before adding, removing, or testing for item
     * @param x item involved
     */
    @Override
    public void acquire(T x) {
        boolean[] mark = { true };
        Thread me = Thread.currentThread();
        Thread who;
        while(true) {
            do { // wait until not resizing
                who = owner.get(mark);
            } while(mark[0] && who != me);
            ReentrantLock[][] oldLocks = this.locks;
            ReentrantLock oldLock0 = oldLocks[0][hash0(x) % oldLocks[0].length];
            ReentrantLock oldLock1 = oldLocks[1][hash1(x) % oldLocks[1].length];
            oldLock0.lock(); // acquire locks
            oldLock1.lock();
            who = owner.get(mark);
            if((!mark[0] || who == me) && this.locks == oldLocks) { // recheck
                return;
            } else { //  unlock & try again
                oldLock0.unlock();
                oldLock1.unlock();
            }
        }
    }

    /**
     * synchronize after adding, removing, or testing for item
     * @param x item involved
     */
    @Override
    public final void release(T x) {
        Lock lock0 = locks[0][hash0(x) % locks[0].length];
        Lock lock1 = locks[1][hash1(x) % locks[1].length];
        lock0.unlock();
        lock1.unlock();
    }

    /**
     * Ensure that no thread is currently locking the set.
     */
    protected void quiesce() {
        for(ReentrantLock lock : locks[0]) {
            while(lock.isLocked()) {
            } // spin
        }
    }

    /**
     * double the set size
     */
    @Override
    public void resize() {
        int oldCapacity = capacity;
        Thread me = Thread.currentThread();
        if(owner.compareAndSet(null, me, false, true)) {
            try {
                if(capacity != oldCapacity) { // someone else resized first
                    return;
                }
                quiesce();
                capacity = 2 * capacity;
                List<T>[][] oldTable = table;
                table = (List<T>[][]) new List[2][capacity];
                locks = new ReentrantLock[2][capacity];
                for(int i = 0; i < 2; i++) {
                    for(int j = 0; j < capacity; j++) {
                        locks[i][j] = new ReentrantLock();
                    }
                }
                for(List<T>[] row : table) {
                    for(int i = 0; i < row.length; i++) {
                        row[i] = new ArrayList<T>(PROBE_SIZE);
                    }
                }
                for(List<T>[] row : oldTable) {
                    for(List<T> set : row) {
                        for(T z : set) {
                            add(z);
                        }
                    }
                }
            } finally {
                owner.set(null, false); // restore prior state
            }
        }
    }
}
TOP

Related Classes of xbird.util.concurrent.collections.set.RefinableCuckooHashSet

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.