Class JCasHashMap
The creation of the new JCas cover object can, in turn, run arbitrary user code, which can result in updates to the JCasHashMap which occur before this original update occurs.
In a multi-threaded environment, multiple threads can do a "get" for the same Feature Structure instance. If it's not in the Map, the correct behavior is:
one of the threads adds the new element the other threads wait for the one thread to finish adding, and then return the object that the one thread added.
The implementation works as follows:
1) The JCasHashMap is split into "n" sub-maps. The number is the number of cores, but grows more slowly as the # of cores > 16. This number can be specified, but this is not currently exposed in the tuning parameters Locking occurs on the sub-maps; the outer method calls are not synchronized 2) The number of sub maps is rounded to a power of 2, to allow the low order bits of the hash of the key to be used to pick the map (via masking). 3) a put: 3a) locks 3b) does a find; if found, updates that, if not, adds new value 3c) unlocks 4) a putIfAbsent: 4a) does a find (not under lock) - if found returns that (not under lock) - note: this has a race condition if another thread is updating / changing that slot -- this only happens for unsupported conditions, so is not checked -- changing the type of an existing FS while another thread is accessing the CAS 4b) if not found, locks 4c) does find again 4d) if found, return that and release lock 4e) if not found, eval the creator form and use to set the value, and release lock Note: if eval of creator form recursively calls this, that's OK because sync locks can be recursively gotten and released in a nested way. 5) get does a find, if found, returns that. - if not, get lock, redo search -- if not resized, start find from last spot. else start from beginning. - if found, return that (release lock). if not found return null (release lock)
Supports put(pre-computed-value), putIfAbsent(value-to-be-computed, as an IntSupplier) get
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final int
private static final int
(package private) static final boolean
private final int
private final int
private final int
(package private) static int
must be a power of 2, > 0 package private for testing not final to allow test case to reset it must not be changed during multi-thread operationprivate final int
private final float
private final JCasHashMapSubMap
private static final int
private final int
private final JCasHashMapSubMap[]
(package private) static final boolean
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoid
clear()
(package private) static boolean
concurrencyLimitedByInitialCapacity
(int currentConcurrencyLevel, int curMapSize) initial capacity (other than testing), is by default (from JCasImpl) is bigger of 256 and cas heap initial size (500,000) / 16 = 31K but users may set it lower in their uima configuration We use the current capacity of the JCasHashMap to set the concurrency limitfinal TOP
get
(int key) int
get the approximate size (subject to multithreading inaccuracies)(package private) int[]
(package private) int
int
(package private) static int
private JCasHashMapSubMap
getSubMap
(int hash) (package private) int[]
static final int
hashInt
(int k1) iterator()
final TOP
final TOP
putIfAbsent
(int key, IntFunction<TOP> creator) (package private) static void
setDEFAULT_CONCURRENCY_LEVEL
(int dEFAULT_CONCURRENCY_LEVEL) void
(package private) static int
sizeAdjustedConcurrency
(int curMapSize) Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Methods inherited from interface java.lang.Iterable
forEach, spliterator
-
Field Details
-
TUNE
static final boolean TUNE- See Also:
-
check
static final boolean check- See Also:
-
DEFAULT_CONCURRENCY_LEVEL
static int DEFAULT_CONCURRENCY_LEVELmust be a power of 2, > 0 package private for testing not final to allow test case to reset it must not be changed during multi-thread operation -
loadFactor
private final float loadFactor- See Also:
-
initialCapacity
private final int initialCapacity -
concurrencyLevel
private final int concurrencyLevel -
concurrencyBitmask
private final int concurrencyBitmask -
concurrencyLevelBits
private final int concurrencyLevelBits -
subMaps
-
subMapInitialCapacity
private final int subMapInitialCapacity -
oneSubmap
-
C1
private static final int C1- See Also:
-
C2
private static final int C2- See Also:
-
seed
private static final int seed- See Also:
-
-
Constructor Details
-
JCasHashMap
public JCasHashMap(int capacity) -
JCasHashMap
JCasHashMap(int capacity, int aConcurrencyLevel)
-
-
Method Details
-
getDEFAULT_CONCURRENCY_LEVEL
static int getDEFAULT_CONCURRENCY_LEVEL() -
setDEFAULT_CONCURRENCY_LEVEL
static void setDEFAULT_CONCURRENCY_LEVEL(int dEFAULT_CONCURRENCY_LEVEL) -
concurrencyLimitedByInitialCapacity
static boolean concurrencyLimitedByInitialCapacity(int currentConcurrencyLevel, int curMapSize) initial capacity (other than testing), is by default (from JCasImpl) is bigger of 256 and cas heap initial size (500,000) / 16 = 31K but users may set it lower in their uima configuration We use the current capacity of the JCasHashMap to set the concurrency limit- Parameters:
casCapacity
- the capacity- Returns:
- true if the concurrency is limited, and could increase with reallocation
-
sizeAdjustedConcurrency
static int sizeAdjustedConcurrency(int curMapSize) -
clear
public void clear() -
getSubMap
-
putIfAbsent
-
get
- Parameters:
key
- -- Returns:
- the item or null
-
put
- Parameters:
value
- -- Returns:
- previous value or null
-
put
- Parameters:
key
- -value
- -- Returns:
- previous value or null
-
hashInt
public static final int hashInt(int k1) -
getCapacities
int[] getCapacities() -
getSubSizes
int[] getSubSizes() -
getCapacity
int getCapacity() -
getApproximateSize
public int getApproximateSize()get the approximate size (subject to multithreading inaccuracies)- Returns:
- the size
-
showHistogram
public void showHistogram() -
getConcurrencyLevel
public int getConcurrencyLevel() -
iterator
-