-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
new LookupCache interface #2455
Changes from 5 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.fasterxml.jackson.databind.util; | ||
|
||
import com.fasterxml.jackson.core.util.Snapshottable; | ||
|
||
import java.util.function.BiConsumer; | ||
|
||
/** | ||
* An interface describing the required API for the Jackson-Databind Type cache. | ||
* | ||
* @see com.fasterxml.jackson.databind.type.TypeFactory#withCache(LookupCache<java.lang.Object,com.fasterxml.jackson.databind.JavaType>) | ||
* @see SimpleLookupCache | ||
*/ | ||
public interface LookupCache <K,V> | ||
extends Snapshottable<LookupCache<K,V>>, | ||
java.io.Serializable { | ||
void contents(BiConsumer<K,V> consumer); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be good to add Javadocs in general. But especially here, as to if and why iteration over entries is desired for all implementations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ReadOnlyClassToSerializerMap relies on this being implemented (only usage I found) - https://github.com/FasterXML/jackson-databind/blob/master/src/main/java/com/fasterxml/jackson/databind/ser/impl/ReadOnlyClassToSerializerMap.java#L36 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah. Hmmh. Yes, that makes sense then... if that specific case is to be made pluggable. Actually: let's drop that from interface, and not make this particular cache pluggable. |
||
int size(); | ||
|
||
/** | ||
* NOTE: key is of type Object only to retain binary backwards-compatibility | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is that needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I kept this from existing SimpleLookupCache documentation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. We wouldn't have to retain that (binary compatibility not preserved across 2.x -> 3.0 boundary) but... I don't feel strongly either way. I know that casting to type variable here won't be of much use as it's truly generic type. But it might help catch some type mismatches. So I am fine either way at this point. |
||
* @param key | ||
* @return value associated with key (can return null) | ||
*/ | ||
V get(Object key); | ||
|
||
V put(K key, V value); | ||
V putIfAbsent(K key, V value); | ||
void clear(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package com.fasterxml.jackson.databind.util; | ||
|
||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.function.BiConsumer; | ||
|
||
/** | ||
* A LookupCache implementation that has no synchronization (like SimpleLookupCache does) | ||
* but that has the downside of not limiting the size of the cache. | ||
*/ | ||
public class UnlimitedLookupCache<K,V> implements LookupCache<K,V> { | ||
|
||
private final int _initialEntries, _maxEntries; | ||
private final transient ConcurrentHashMap<K,V> _map; | ||
|
||
public UnlimitedLookupCache(int initialEntries, int maxEntries) | ||
{ | ||
_initialEntries = initialEntries; | ||
_maxEntries = maxEntries; | ||
// We'll use concurrency level of 4, seems reasonable | ||
_map = new ConcurrentHashMap<K,V>(initialEntries, 0.8f, 4); | ||
} | ||
|
||
@Override | ||
public void contents(BiConsumer<K, V> consumer) { | ||
for (Map.Entry<K,V> entry : _map.entrySet()) { | ||
consumer.accept(entry.getKey(), entry.getValue()); | ||
} | ||
} | ||
|
||
@Override | ||
public int size() { | ||
return _map.size(); | ||
} | ||
|
||
@Override | ||
public V get(Object key) { | ||
return _map.get(key); | ||
} | ||
|
||
@Override | ||
public V put(K key, V value) { | ||
return _map.put(key, value); | ||
} | ||
|
||
@Override | ||
public V putIfAbsent(K key, V value) { | ||
return _map.putIfAbsent(key, value); | ||
} | ||
|
||
@Override | ||
public void clear() { | ||
_map.clear(); | ||
} | ||
|
||
@Override | ||
public LookupCache<K, V> snapshot() { | ||
return new UnlimitedLookupCache<K,V>(_initialEntries, _maxEntries); | ||
} | ||
|
||
protected Object readResolve() { | ||
return snapshot(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure
java.io.Serializable
is actually needed for interface itself.Serializability in 3.0 is by serializing Builders. Although it may be true that for some types, implementations would need to be serializable. Snapshottable does make sense, I think.