Class SingletonMap<K,V,E extends java.lang.Exception>
- java.lang.Object
-
- nonapi.io.github.classgraph.concurrency.SingletonMap<K,V,E>
-
- Type Parameters:
K
- The key type.V
- The value type.E
- the element type
public abstract class SingletonMap<K,V,E extends java.lang.Exception> extends java.lang.Object
A map from keys to singleton instances. Allows you to create object instance singletons and add them to aConcurrentMap
on demand, based on a key value. Works the same asconcurrentMap.computeIfAbsent(key, key -> newInstance(key))
, except that it also works on JDK 7.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
SingletonMap.NewInstanceException
Thrown whennewInstance(Object, LogNode)
throws an exception.static interface
SingletonMap.NewInstanceFactory<V,E extends java.lang.Exception>
Create a new instance.static class
SingletonMap.NullSingletonException
Thrown whennewInstance(Object, LogNode)
returns null.private static class
SingletonMap.SingletonHolder<V>
Wrapper to allow an object instance to be put into a ConcurrentHashMap using putIfAbsent() without requiring the instance to be initialized first, so that putIfAbsent can be performed without wrapping it with a synchronized lock, and so that initialization work is not wasted if an object is already in the map for the key.
-
Field Summary
Fields Modifier and Type Field Description private java.util.concurrent.ConcurrentMap<K,SingletonMap.SingletonHolder<V>>
map
The map.
-
Constructor Summary
Constructors Constructor Description SingletonMap()
-
Method Summary
All Methods Instance Methods Abstract Methods Concrete Methods Modifier and Type Method Description void
clear()
Clear the map.java.util.List<java.util.Map.Entry<K,V>>
entries()
Get the map entries.V
get(K key, LogNode log)
Check if the given key is in the map, and if so, return the value ofnewInstance(Object, LogNode)
for that key, or block on the result ofnewInstance(Object, LogNode)
if another thread is currently creating the new instance.V
get(K key, LogNode log, SingletonMap.NewInstanceFactory<V,E> newInstanceFactory)
Check if the given key is in the map, and if so, return the value ofnewInstance(Object, LogNode)
for that key, or block on the result ofnewInstance(Object, LogNode)
if another thread is currently creating the new instance.boolean
isEmpty()
Returns true if the map is empty.abstract V
newInstance(K key, LogNode log)
Construct a new singleton instance.V
remove(K key)
Remove the singleton for a given key.java.util.List<V>
values()
Get all valid singleton values in the map.
-
-
-
Field Detail
-
map
private final java.util.concurrent.ConcurrentMap<K,SingletonMap.SingletonHolder<V>> map
The map.
-
-
Method Detail
-
newInstance
public abstract V newInstance(K key, LogNode log) throws E extends java.lang.Exception, java.lang.InterruptedException
Construct a new singleton instance.- Parameters:
key
- The key for the singleton.log
- The log.- Returns:
- The singleton instance. This method must either return a non-null value, or throw an exception of type E.
- Throws:
E
- If something goes wrong while instantiating the new object instance.java.lang.InterruptedException
- if the thread was interrupted while instantiating the singleton.E extends java.lang.Exception
-
get
public V get(K key, LogNode log, SingletonMap.NewInstanceFactory<V,E> newInstanceFactory) throws E extends java.lang.Exception, java.lang.InterruptedException, SingletonMap.NullSingletonException, SingletonMap.NewInstanceException
Check if the given key is in the map, and if so, return the value ofnewInstance(Object, LogNode)
for that key, or block on the result ofnewInstance(Object, LogNode)
if another thread is currently creating the new instance. If the given key is not currently in the map, store a placeholder in the map for this key, then runnewInstance(Object, LogNode)
for the key, store the result in the placeholder (which unblocks any other threads waiting for the value), and then return the new instance.- Parameters:
key
- The key for the singleton.newInstanceFactory
- if non-null, a factory for creating new instances, otherwise if null, thennewInstance(Object, LogNode)
is called instead (this allows new instance creation to be overridden on a per-instance basis).log
- The log.- Returns:
- The non-null singleton instance, if
newInstance(Object, LogNode)
returned a non-null instance on this call or a previous call, otherwise throwsNullPointerException
if this call or a previous call tonewInstance(Object, LogNode)
returned null. - Throws:
E
- IfnewInstance(Object, LogNode)
threw an exception.java.lang.InterruptedException
- if the thread was interrupted while waiting for the singleton to be instantiated by another thread.SingletonMap.NullSingletonException
- ifnewInstance(Object, LogNode)
returned null.SingletonMap.NewInstanceException
- ifnewInstance(Object, LogNode)
threw an exception.E extends java.lang.Exception
-
get
public V get(K key, LogNode log) throws E extends java.lang.Exception, java.lang.InterruptedException, SingletonMap.NullSingletonException, SingletonMap.NewInstanceException
Check if the given key is in the map, and if so, return the value ofnewInstance(Object, LogNode)
for that key, or block on the result ofnewInstance(Object, LogNode)
if another thread is currently creating the new instance. If the given key is not currently in the map, store a placeholder in the map for this key, then runnewInstance(Object, LogNode)
for the key, store the result in the placeholder (which unblocks any other threads waiting for the value), and then return the new instance.- Parameters:
key
- The key for the singleton.log
- The log.- Returns:
- The non-null singleton instance, if
newInstance(Object, LogNode)
returned a non-null instance on this call or a previous call, otherwise throwsNullPointerException
if this call or a previous call tonewInstance(Object, LogNode)
returned null. - Throws:
E
- IfnewInstance(Object, LogNode)
threw an exception.java.lang.InterruptedException
- if the thread was interrupted while waiting for the singleton to be instantiated by another thread.SingletonMap.NullSingletonException
- ifnewInstance(Object, LogNode)
returned null.SingletonMap.NewInstanceException
- ifnewInstance(Object, LogNode)
threw an exception.E extends java.lang.Exception
-
values
public java.util.List<V> values() throws java.lang.InterruptedException
Get all valid singleton values in the map.- Returns:
- the singleton values in the map, skipping over any value for which newInstance() threw an exception or returned null.
- Throws:
java.lang.InterruptedException
- If getting the values was interrupted.
-
isEmpty
public boolean isEmpty()
Returns true if the map is empty.- Returns:
- true, if the map is empty
-
entries
public java.util.List<java.util.Map.Entry<K,V>> entries() throws java.lang.InterruptedException
Get the map entries.- Returns:
- the map entries.
- Throws:
java.lang.InterruptedException
- if interrupted.
-
remove
public V remove(K key) throws java.lang.InterruptedException
Remove the singleton for a given key.- Parameters:
key
- the key- Returns:
- the old singleton from the map, if one was present, otherwise null.
- Throws:
java.lang.InterruptedException
- if interrupted.
-
clear
public void clear()
Clear the map.
-
-