public class ALDConcReadWeakHashMap extends Object
Note:
This file in its original version was taken from:
http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html
According to the webpage there are no license restrictions on using the file:
"Do I need a license to use it? Can I get one? No!"
You can find the original header of the file, which originally was named 'ConcurrentReaderHashMap.java', below. For using it with Alida the class was significantly modified and also simplified as Alida requires only all very small amount of the original functionality.
Details (non-modified comment of original version):
This version of Hashtable supports mostly-concurrent reading, but
exclusive writing. Because reads are not limited to periods
without writes, a concurrent reader policy is weaker than a classic
reader/writer policy, but is generally faster and allows more
concurrency. This class is a good choice especially for tables that
are mainly created by one thread during the start-up phase of a
program, and from then on, are mainly read (with perhaps occasional
additions or removals) in many threads. If you also need concurrency
among writes, consider instead using ConcurrentHashMap.
Successful retrievals using get(key) and containsKey(key) usually run without locking. Unsuccessful ones (i.e., when the key is not present) do involve brief synchronization (locking). Also, the size and isEmpty methods are always synchronized.
Because retrieval operations can ordinarily overlap with writing operations (i.e., put, remove, and their derivatives), retrievals can only be guaranteed to return the results of the most recently completed operations holding upon their onset. Retrieval operations may or may not return results reflecting in-progress writing operations. However, the retrieval operations do always return consistent results -- either those holding before any single modification or after it, but never a nonsense result. For aggregate operations such as putAll and clear, concurrent reads may reflect insertion or removal of only some entries. In those rare contexts in which you use a hash table to synchronize operations across threads (for example, to prevent reads until after clears), you should either encase operations in synchronized blocks, or instead use java.util.Hashtable.
This class also supports optional guaranteed exclusive reads, simply by
surrounding a call within a synchronized block, as in
ConcurrentReaderHashMap t; ... Object v;
synchronized(t) { v = t.get(k); }
But this is not usually necessary in practice.
For example, it is generally inefficient to write:
ConcurrentReaderHashMap t; ... // Inefficient version Object key; ... Object value; ... synchronized(t) { if (!t.containsKey(key)) t.put(key, value); // other code if not previously present } else { // other code if it was previously present } }Instead, if the values are intended to be the same in each case, just take advantage of the fact that put returns null if the key was not previously present:
ConcurrentReaderHashMap t; ... // Use this instead Object key; ... Object value; ... Object oldValue = t.put(key, value); if (oldValue == null) { // other code if not previously present } else { // other code if it was previously present }
Iterators and Enumerations (i.e., those returned by keySet().iterator(), entrySet().iterator(), values().iterator(), keys(), and elements()) return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration. They will return at most one instance of each element (via next()/nextElement()), but might or might not reflect puts and removes that have been processed since they were created. They do not throw ConcurrentModificationException. However, these iterators are designed to be used by only one thread at a time. Sharing an iterator across multiple threads may lead to unpredictable results if the table is being concurrently modified. Again, you can ensure interference-free iteration by enclosing the iteration in a synchronized block.
This class may be used as a direct replacement for any use of java.util.Hashtable that does not depend on readers being blocked during updates. Like Hashtable but unlike java.util.HashMap, this class does NOT allow null to be used as a key or value. This class is also typically faster than ConcurrentHashMap when there is usually only one thread updating the table, but possibly many retrieving values from it.
Implementation note: A slightly faster implementation of this class will be possible once planned Java Memory Model revisions are in place.
Modifier and Type | Class and Description |
---|---|
protected static class |
ALDConcReadWeakHashMap.BarrierLock
A Serializable class for barrier lock.
|
Modifier and Type | Field and Description |
---|---|
protected ALDConcReadWeakHashMap.BarrierLock |
barrierLock
Lock used only for its memory effects.
|
protected int |
count
The total number of mappings in the hash table.
|
static int |
DEFAULT_INITIAL_CAPACITY
The default initial number of table slots for this table (32).
|
static float |
DEFAULT_LOAD_FACTOR
The default load factor for this table (1.0).
|
protected Object |
lastWrite
field written to only to guarantee lock ordering.
|
protected float |
loadFactor
The load factor for the hash table.
|
private static int |
MAXIMUM_CAPACITY
The maximum capacity, used if a higher value is implicitly specified
by either of the constructors with arguments.
|
private static int |
MINIMUM_CAPACITY
The minimum capacity, used if a lower value is implicitly specified
by either of the constructors with arguments.
|
protected static ReferenceQueue<Object> |
refQueue
Queue for managing references to deleted objects.
|
protected ALDWeakHashMapEntry[] |
table
The hash table data.
|
protected int |
threshold
The table is rehashed when its size exceeds this threshold.
|
Modifier | Constructor and Description |
---|---|
|
ALDConcReadWeakHashMap()
Constructs a new, empty map with a default initial capacity
and load factor.
|
|
ALDConcReadWeakHashMap(int initialCapacity)
Constructs a new, empty map with the specified initial
capacity and default load factor.
|
private |
ALDConcReadWeakHashMap(int initialCapacity,
float loadFac)
Constructs a new, empty map with the specified initial
capacity and the specified load factor.
|
Modifier and Type | Method and Description |
---|---|
int |
capacity()
Returns the number of slots in this table.
|
void |
clear()
Removes all mappings from the map.
|
Object |
clone()
Returns a shallow copy of this ConcurrentReaderHashMap instance.
|
boolean |
containsKey(Object key)
Tests if the specified object is a key in this table.
|
protected boolean |
eq(Object x,
Object y)
Check for equality of non-null references x and y.
|
Object |
get(Object key)
Returns the value to which the specified key is mapped in this table.
|
protected ALDWeakHashMapEntry[] |
getTableForReading()
Get ref to table; the reference and the cells it
accesses will be at least as fresh as from last
use of barrierLock
|
private static int |
hash(Object x)
Return hash code for Object x.
|
boolean |
isEmpty()
Returns true if this map contains no key-value mappings.
|
float |
loadFactor()
Returns the load factor.
|
private int |
p2capacity(int initialCapacity)
Returns appropriate capacity for argument.
|
Object |
put(Object key,
Object value)
Maps the specified
key to the specified
value in this table. |
protected void |
recordModification(Object x)
Force a memory synchronization that will cause
all readers to see table.
|
protected void |
rehash()
Rehashes the contents of this map into a new table
with a larger capacity.
|
Object |
remove(Object key)
Removes the key (and its corresponding value) from the table.
|
private void |
removeWeakKeys()
Cleans-up the hashmap when called.
|
int |
size()
Returns the number of key-value mappings in this map.
|
protected Object |
sput(Object key,
Object value,
int hash)
Continuation of put(), called only when synch lock is
held and interference has been detected.
|
protected Object |
sremove(Object key,
int hash)
Continuation of remove(), called only when synch lock is
held and interference has been detected.
|
protected final ALDConcReadWeakHashMap.BarrierLock barrierLock
protected transient Object lastWrite
public static int DEFAULT_INITIAL_CAPACITY
private static final int MINIMUM_CAPACITY
private static final int MAXIMUM_CAPACITY
public static final float DEFAULT_LOAD_FACTOR
protected transient ALDWeakHashMapEntry[] table
protected transient int count
protected int threshold
protected float loadFactor
protected static ReferenceQueue<Object> refQueue
private ALDConcReadWeakHashMap(int initialCapacity, float loadFac)
initialCapacity
- the initial capacity
The actual initial capacity is rounded to the nearest power of two.loadFac
- the load factor of the ConcurrentReaderHashMapIllegalArgumentException
- if the initial maximum number
of elements is less
than zero, or if the load factor is nonpositive.public ALDConcReadWeakHashMap(int initialCapacity)
initialCapacity
- the initial capacity of the
ConcurrentReaderHashMap.IllegalArgumentException
- if the initial maximum number
of elements is less
than zero.public ALDConcReadWeakHashMap()
protected final void recordModification(Object x)
protected final ALDWeakHashMapEntry[] getTableForReading()
private int p2capacity(int initialCapacity)
The appropriate capacity is calculated as the power of two of the specified initial capacity argument.
private static int hash(Object x)
protected boolean eq(Object x, Object y)
We are going to check for object references, not equality!
public int size()
public boolean isEmpty()
public Object get(Object key)
key
- Key in the table.null
if the key is not mapped to any value.NullPointerException
- if the key is null
.put(Object, Object)
public boolean containsKey(Object key)
the method returns true
if and only if the specified
object is a key in this table, as determined by the equals
method; false
otherwise.
key
- Questionable key.true
if and only if object is a key.NullPointerException
- if the key is null
.public Object put(Object key, Object value)
key
to the specified
value
in this table.
Neither the key nor the value can be null
.
The value can be retrieved by calling the get
method
with a key that is equal to the original key.
key
- The table key.value
- The value.null
if it did not have one.NullPointerException
- if the key or value is null
.Object.equals(Object)
,
get(Object)
protected Object sput(Object key, Object value, int hash)
protected void rehash()
public Object remove(Object key)
This method does nothing if the key is not in the table.
key
- Key that needs to be removed.null
if the key did not have a mapping.NullPointerException
- if the key is null
.protected Object sremove(Object key, int hash)
public void clear()
public Object clone()
Note that the keys and values themselves are not cloned.
private void removeWeakKeys()
This function is called from time to time on the hashmap to remove keys of objects that have been deleted.
public int capacity()
public float loadFactor()
Copyright © 2010–2021 Martin Luther University Halle-Wittenberg, Institute of Computer Science, Pattern Recognition and Bioinformatics. All rights reserved.