HCOLL-136 HCOLL-137 HCOLL-153 HCOLL-160

1. Separated ChronicleMapBuilder (for non-Byteable values) and
OffHeapUpdatableChronicleMapBuilder (for Byteable values) with common base
AbstractChronicleMapBuilder (public just to inherit common javadocs)

2. Added ChronicleHashBuilder.keyDeserializationFactory() and
AbstractChronicleMapBuilder.valueDeserializationFactory() (former
ChronicleMapBuilder.valueFactory() method)

3. Changed ChronicleMap.get(), getUsing() API and impl to what was
initially intended - now they ALWAYS returns null, if key is absent

4. acquireUsing() API, common for the cases with Byteable and non-Byteable
values: puts defaultValue or defaultValueProvider.get(key), if the key is
absent, then acquireUsing() behaves just like getUsing()

5. For off0heap updatable ChronicleMaps (Byteable values), added
prepareValueBytes() configuration which formalizes zeroing out value bytes

6. Javadoc fixes and improvements
This commit is contained in:
leventov
2014-10-27 20:15:26 +03:00
parent b374a9bd50
commit 0c45ee8aff
30 changed files with 1529 additions and 1084 deletions
@@ -22,7 +22,6 @@ import net.openhft.chronicle.common.ChronicleHash;
import net.openhft.chronicle.common.serialization.BytesReader;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.serialization.BytesMarshaller;
import net.openhft.lang.io.serialization.ObjectFactory;
import net.openhft.lang.model.Byteable;
import java.io.Closeable;
@@ -38,11 +37,15 @@ import java.util.concurrent.ConcurrentMap;
* <li>{@code ChronicleMap} flavors and properties</li>
* <li>available configurations</li>
* </ul>
* see {@link ChronicleMapBuilder} documentation.
* see {@link AbstractChronicleMapBuilder} documentation.
*
* <p>Functionally this interface defines some methods supporting garbage-free off-heap programming:
* {@link #getUsing(Object, Object)}, {@link #acquireUsing(Object, Object)}.
*
* <p>Roughly speaking, {@code ChronicleMap} compares keys and values by their binary serialized
* form, that shouldn't necessary be the same equality relation as defined by built-in {@link
* Object#equals(Object)} method, which is prescribed by general {@link Map} contract.
*
* <p>Note that {@code ChronicleMap} extends {@link Closeable}, don't forget
* to {@linkplain #close() close} map when it is no longer needed.
*
@@ -62,15 +65,6 @@ public interface ChronicleMap<K, V> extends ConcurrentMap<K, V>, ChronicleHash {
* Returns the value to which the specified key is mapped, or {@code null} if this map contains
* no mapping for the key.
*
* <p>If the specified key if absent in the map, {@linkplain
* ChronicleMapBuilder#defaultValue(Object) default value} is taken or {@linkplain
* ChronicleMapBuilder#defaultValueProvider(DefaultValueProvider) default value provider}
* is called (depending on what was configured last in {@code ChronicleMapBuilder}).
* If it results to something different from {@code null}, this object is put to this map for
* the specified key, and then returned from this {@code get()} call. Otherwise, if default
* value is {@code null} and default value provider returns {@code null}, the map remains
* unchanged and {@code null} is returned.
*
* <p>If the value class allows reusing, particularly if it is a {@link Byteable} subclass,
* consider {@link #getUsing(Object, Object)} method instead of this to reduce garbage creation.
*
@@ -90,40 +84,59 @@ public interface ChronicleMap<K, V> extends ConcurrentMap<K, V>, ChronicleHash {
* {@code value} object via value marshaller's {@link BytesMarshaller#read(Bytes, Object)
* read(Bytes, value)} or value reader's {@link BytesReader#read(Bytes, long, Object)
* read(Bytes, size, value)} method, depending on what deserialization strategy is configured
* on this map builder. If the value deserializer is able to reuse the given {@code value}
* object, calling this method instead of {@link #get(Object)} could help to reduce garbage
* creation.
* on the builder, using which this map was constructed. If the value deserializer is able
* to reuse the given {@code value} object, calling this method instead of {@link #get(Object)}
* could help to reduce garbage creation.
*
* <p>The provided {@code value} object is allowed to be {@code null}, in this case
* {@code map.getUsing(key, null)} call is semantically equivalent to simple
* {@code map.get(key)} call.
*
* <p>If the specified key if absent in the map, {@linkplain
* ChronicleMapBuilder#defaultValue(Object) default value} is taken or {@linkplain
* ChronicleMapBuilder#defaultValueProvider(DefaultValueProvider) default value provider}
* is called. If it results to something different from {@code null}, this object is put
* to this map for the specified key, and then a new value is returned from this
* {@code getUsing()} call. Otherwise, if default value is {@code null} and default value
* provider, if specified, returns {@code null}, the map remains unchanged and {@code null}
* is returned. The provided {@code value} is untouched anyway in this case.
*
* @param key the key whose associated value is to be returned
* @param value the object to read value data in, if possible
* @return the value mapped to the specified key after this method call, or {@code null} if no
* value is mapped
* @param key the key whose associated value is to be returned
* @param usingValue the object to read value data in, if possible
* @return the value to which the specified key is mapped, or {@code null} if this map contains
* no mapping for the key
* @see #get(Object)
* @see ChronicleMapBuilder#valueMarshallerAndFactory(BytesMarshaller, ObjectFactory)
* @see #acquireUsing(Object, Object)
* @see ChronicleMapBuilder#valueMarshaller(BytesMarshaller)
*/
V getUsing(K key, V value);
V getUsing(K key, V usingValue);
/**
* Acquire a value for a key, creating if absent. If the value is Byteable, it will be assigned
* to reference the value, instead of copying the data.
* Acquire a value for a key, creating if absent.
*
* @param key the key whose associated value is to be returned
* @param value to reuse if possible. If null, a new object will be created.
* @return value created or found.
* <p>If the specified key if absent in the map, {@linkplain
* AbstractChronicleMapBuilder#defaultValue(Object) default value} is taken or {@linkplain
* AbstractChronicleMapBuilder#defaultValueProvider(DefaultValueProvider) default value
* provider} is called. Then this object is put to this map for the specified key.
*
* <p>Then, either if the key was initially absent in the map or already present,
* the value is deserialized just as during {@link #getUsing(Object, Object)
* getUsing(key, usingValue)} call, passed the same {@code key} and {@code usingValue} as into
* this method call. This means, as in {@link #getUsing}, {@code usingValue} could safely be
* {@code null}, in this case a new value instance is created to deserialize the data.
*
* <p>In code, {@code acquireUsing} is specified as <pre>{@code
* V acquireUsing(K key, V usingValue) {
* if (!containsKey(key))
* put(key, defaultValue(key));
* return getUsing(key, usingValue);
* }}</pre> Where {@code defaultValue(key)} returns either {@linkplain
* AbstractChronicleMapBuilder#defaultValue(Object) default value} or {@link
* AbstractChronicleMapBuilder#defaultValueProvider(DefaultValueProvider) defaultValueProvider.}
*
* <p>If the {@code ChronicleMap} is off-heap updatable, i. e. created via {@link
* OffHeapUpdatableChronicleMapBuilder} builder (values are {@link Byteable}), there is one more
* option of what to do if the key is absent in the map, see {@link
* OffHeapUpdatableChronicleMapBuilder#prepareValueBytesOnAcquire(PrepareValueBytes)}.
* By default, value bytes are just zeroed out, no default value, either provided for key
* or constant, is put for the absent key.
*
* @param key the key whose associated value is to be returned
* @param usingValue the object to read value data in, if possible
* @return value to which the given key is mapping after this call, either found or created
* @see #getUsing(Object, Object)
*/
V acquireUsing(K key, V value);
V acquireUsing(K key, V usingValue);
}