Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.remoting3;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReferenceArray;
final class UnlockedReadHashMap extends AbstractMap implements ConcurrentMap {
private static final int DEFAULT_INITIAL_CAPACITY = 512;
private static final int MAXIMUM_CAPACITY = 1 << 30;
private static final float DEFAULT_LOAD_FACTOR = 0.60f;
// Final fields (thread-safe)
private final Object writeLock = new Object();
private final Set> entrySet = new EntrySet();
private final float loadFactor;
// Volatile fields (writes protected by {@link #writeLock})
private volatile int size;
private volatile AtomicReferenceArray[]> table;
// Raw fields (reads and writes protected by {@link #writeLock}
private int threshold;
UnlockedReadHashMap(int initialCapacity, final float loadFactor) {
if (initialCapacity < 0) {
throw new IllegalArgumentException("Initial capacity must be > 0");
}
if (initialCapacity > MAXIMUM_CAPACITY) {
initialCapacity = MAXIMUM_CAPACITY;
}
if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
throw new IllegalArgumentException("Load factor must be > 0.0f");
}
int capacity = 1;
while (capacity < initialCapacity) {
capacity <<= 1;
}
this.loadFactor = loadFactor;
synchronized (writeLock) {
threshold = (int)(capacity * loadFactor);
table = new AtomicReferenceArray[]>(capacity);
}
}
UnlockedReadHashMap(final float loadFactor) {
this(DEFAULT_INITIAL_CAPACITY, loadFactor);
}
UnlockedReadHashMap(final int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
UnlockedReadHashMap() {
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
}
@SuppressWarnings( { "unchecked" })
private void resize() {
assert Thread.holdsLock(writeLock);
final AtomicReferenceArray[]> oldTable = table;
final int oldCapacity = oldTable.length();
if (oldCapacity == MAXIMUM_CAPACITY) {
return;
}
final int newCapacity = oldCapacity << 1;
final AtomicReferenceArray[]> newTable = new AtomicReferenceArray[]>(newCapacity);
final int newThreshold = (int)(newCapacity * loadFactor);
for (int i = 0; i < oldCapacity; i ++) {
final Item[] items = oldTable.get(i);
if (items != null) {
final int length = items.length;
for (int j = 0; j < length; j++) {
Item item = items[j];
final int hc = item.hashCode() & (newCapacity - 1);
final Item[] old = newTable.get(hc);
if (old == null) {
newTable.lazySet(hc, new Item[] { item });
} else {
final int oldLen = old.length;
final Item[] copy = Arrays.copyOf(old, oldLen + 1);
copy[oldLen] = item;
newTable.lazySet(hc, copy);
}
}
}
}
table = newTable;
threshold = newThreshold;
}
private static Item doGet(final AtomicReferenceArray[]> table, final Object key) {
Item[] row = doGetRow(table, key);
return row == null ? null : doGet(row, key);
}
private static Item[] doGetRow(final AtomicReferenceArray[]> table, final Object key) {
final int hc = getIndex(table, key);
return doGetRow(table, hc);
}
private static int getIndex(final AtomicReferenceArray[]> table, final Object key) {
return key.hashCode() & (table.length() - 1);
}
private static Item[] doGetRow(final AtomicReferenceArray[]> table, final int hc) {
return table.get(hc);
}
private static Item doGet(Item[] row, Object key) {
for (Item item : row) {
if (item.key.equals(key)) {
return item;
}
}
return null;
}
private V doPut(AtomicReferenceArray[]> table, K key, V value, boolean ifAbsent) {
final int hc = getIndex(table, key);
final Item[] old = doGetRow(table, hc);
if (old == null) {
@SuppressWarnings( { "unchecked" })
final Item[] newRow = new Item[] { new Item(key, value) };
table.set(hc, newRow);
if (size++ == threshold) {
resize();
}
return null;
} else {
final Item item = doGet(old, key);
if (item != null) {
try {
return item.value;
} finally {
if (! ifAbsent) item.value = value;
}
}
final int oldLen = old.length;
final Item[] newRow = Arrays.copyOf(old, oldLen + 1);
newRow[oldLen] = new Item(key, value);
table.set(hc, newRow);
if (size++ == threshold) {
resize();
}
return null;
}
}
private static Item[] remove(Item[] row, int idx) {
final int len = row.length;
assert idx < len;
if (len == 1) {
return null;
}
@SuppressWarnings("unchecked")
Item[] newRow = new Item[len - 1];
if (idx > 0) {
System.arraycopy(row, 0, newRow, 0, idx);
}
if (idx < len - 1) {
System.arraycopy(row, idx + 1, newRow, idx, len - 1 - idx);
}
return newRow;
}
public Set> entrySet() {
return entrySet;
}
public int size() {
return size;
}
public boolean containsKey(final Object key) {
if (key == null) {
return false;
}
final Item item = doGet(table, key);
return item != null;
}
public V get(final Object key) {
if (key == null) {
return null;
}
final Item item = doGet(table, key);
return item == null ? null : item.value;
}
public V put(final K key, final V value) {
if (key == null) {
throw new IllegalArgumentException("key is null");
}
synchronized (writeLock) {
return doPut(table, key, value, false);
}
}
public V remove(final Object key) {
if (key == null) {
return null;
}
synchronized (writeLock) {
final int hc = getIndex(table, key);
final Item[] row = doGetRow(table, hc);
if (row == null) {
return null;
}
final int rowLen = row.length;
for (int i = 0; i < rowLen; i++) {
final Item item = row[i];
if (item.key.equals(key)) {
table.set(hc, remove(row, i));
size --;
return item.value;
}
}
return null;
}
}
public void clear() {
synchronized (writeLock) {
table = new AtomicReferenceArray[]>(table.length());
size = 0;
}
}
public V putIfAbsent(final K key, final V value) {
if (key == null) {
throw new IllegalArgumentException("key is null");
}
synchronized (writeLock) {
return doPut(table, key, value, true);
}
}
public boolean remove(final Object key, final Object value) {
if (key == null) {
return false;
}
synchronized (writeLock) {
final int hc = getIndex(table, key);
final Item[] row = doGetRow(table, hc);
if (row == null) {
return false;
}
final int rowLen = row.length;
for (int i = 0; i < rowLen; i++) {
final Item item = row[i];
if (item.key.equals(key) && (value == null ? item.value == null : value.equals(item.value))) {
table.set(hc, remove(row, i));
size --;
return true;
}
}
return false;
}
}
public boolean replace(final K key, final V oldValue, final V newValue) {
if (key == null) {
return false;
}
synchronized (writeLock) {
final Item item = doGet(table, key);
if (item != null) {
if (oldValue == null ? item.value == null : oldValue.equals(item.value)) {
item.value = newValue;
return true;
}
}
return false;
}
}
public V replace(final K key, final V value) {
if (key == null) {
return null;
}
synchronized (writeLock) {
final Item item = doGet(table, key);
if (item != null) try {
return item.value;
} finally {
item.value = value;
}
return null;
}
}
private final class EntrySet extends AbstractSet> implements Set> {
public Iterator> iterator() {
return new EntryIterator();
}
public int size() {
return UnlockedReadHashMap.this.size();
}
}
private final class EntryIterator implements Iterator> {
private final AtomicReferenceArray[]> table = UnlockedReadHashMap.this.table;
private int tableIdx;
private int itemIdx;
private Item next;
public boolean hasNext() {
while (next == null) {
if (table.length() == tableIdx) {
return false;
}
final Item[] items = table.get(tableIdx);
if (items != null) {
final int len = items.length;
if (itemIdx < len) {
next = items[itemIdx++];
return true;
}
}
itemIdx = 0;
tableIdx++;
}
return true;
}
public Entry next() {
if (hasNext()) try {
return next;
} finally {
next = null;
}
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
private static final class Item implements Entry {
private final K key;
private volatile V value;
private Item(final K key, final V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public V setValue(final V value) {
try {
return this.value;
} finally {
this.value = value;
}
}
public int hashCode() {
return key.hashCode();
}
public boolean equals(final Object obj) {
return obj instanceof Item && equals((Item,?>) obj);
}
public boolean equals(final Item, ?> obj) {
return obj != null && obj.key.equals(key);
}
}
}