key();
+
+ /**
+ * Removes the entry from the {@code ChronicleHash}. Returns {@code true} if the remove was
+ * successful, {@code false} if it failed for any reason.
+ *
+ * This method if the default implementation for {@link MapEntryOperations#remove(MapEntry)},
+ * which might be customized over the default.
+ *
+ * @throws IllegalStateException if some locking/state conditions required to perform remove
+ * operation are not met
+ */
+ boolean defaultRemove();
+}
diff --git a/src/main/java/net/openhft/chronicle/hash/KeyContext.java b/src/main/java/net/openhft/chronicle/hash/KeyContext.java
index 2f5f97047..e15a10679 100644
--- a/src/main/java/net/openhft/chronicle/hash/KeyContext.java
+++ b/src/main/java/net/openhft/chronicle/hash/KeyContext.java
@@ -1,17 +1,19 @@
/*
- * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com
+ * Copyright 2015 Higher Frequency Trading
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * http://www.higherfrequencytrading.com
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
package net.openhft.chronicle.hash;
@@ -34,6 +36,7 @@ import java.util.ConcurrentModificationException;
*
* @param key type
*/
+@Deprecated
public interface KeyContext extends AutoCloseable, InterProcessReadWriteUpdateLock {
/**
diff --git a/src/main/java/net/openhft/chronicle/hash/Value.java b/src/main/java/net/openhft/chronicle/hash/Value.java
new file mode 100644
index 000000000..2653bb6b3
--- /dev/null
+++ b/src/main/java/net/openhft/chronicle/hash/Value.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2015 Higher Frequency Trading
+ *
+ * http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.hash;
+
+import net.openhft.chronicle.bytes.*;
+import net.openhft.chronicle.algo.hashing.LongHashFunction;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Dual bytes/object access to keys/values/elements.
+ *
+ * Bytes access: {@link #access()} + {@link #handle()} + {@link #size()}.
+ *
+ *
Object access: {@link #get()}.
+ *
+ * In most cases, each particular value wraps either some object or some bytes. Object is marshalled
+ * to bytes lazily on demand, and bytes are lazily deserialized to object, accordingly.
+ *
+ * @param type of the accessed objects
+ * @param type of the handle for bytes access
+ */
+public interface Value {
+
+ ReadAccess access();
+
+ T handle();
+
+ long offset();
+
+ long size();
+
+ default long hash(LongHashFunction f) {
+ return f.hash(handle(), access(), offset(), size());
+ }
+
+ default boolean equivalent(ReadAccess access, T2 handle, long offset) {
+ return Access.equivalent(access(), handle(), offset(), access, handle, offset, size());
+ }
+
+ default > boolean equivalent(
+ Accessor accessor, S source, long index) {
+ return equivalent(accessor.access(source), accessor.handle(source),
+ accessor.offset(source, index));
+ }
+
+ default void writeTo(WriteAccess access, T2 handle, long offset) {
+ Access.copy(access(), handle(), offset(), access, handle, offset, size());
+ }
+
+ default void writeTo(StreamingDataOutput, ?, T2> output) {
+ long offset = output.accessPositionOffset();
+ output.skip(size());
+ writeTo(output.access(), output.accessHandle(), offset);
+ }
+
+ default > void writeTo(
+ Accessor accessor, S source, long index) {
+ writeTo(accessor.access(source), accessor.handle(source), accessor.offset(source, index));
+ }
+
+ /**
+ * Returns "cached" object, generally not eligible for using outside some context, or a block,
+ * synchronized with locks, or lambda, etc.
+ *
+ * If the {@code Value} is object wrapper -- this method just returns this object.
+ */
+ V get();
+
+ /**
+ * Reads the object from the value's bytes, trying to reuse the given object
+ * (might be {@code null}).
+ */
+ V getUsing(@Nullable V usingInstance);
+
+ static boolean bytesEquivalent(Value, T1> v1, Value, T2> v2) {
+ if (v1.size() != v2.size())
+ return false;
+ return Access.equivalent(v1.access(), v1.handle(), v1.offset(),
+ v2.access(), v2.handle(), v2.offset(), v1.size());
+ }
+}
diff --git a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java
index 2798b6000..c5c163ba4 100755
--- a/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java
+++ b/src/main/java/net/openhft/chronicle/map/ChronicleMapBuilder.java
@@ -1481,5 +1481,40 @@ public final class ChronicleMapBuilder implements
return (int) Math.min(Math.max(2L, entries() >> 10),
Math.min(64, maxChunksPerEntry()));
}
+
+ /**
+ * Inject your SPI code around basic {@code ChronicleMap}'s operations with present entries:
+ * removing entries and replacing the entries' value.
+ *
+ * This affects behaviour of ordinary map.put(), map.remove(), etc. calls, as well as removes
+ * and replacing values during iterations, remote map calls and
+ * internal replication operations.
+ */
+ public ChronicleMapBuilder customizeEntryOperations(
+ MapEntryOperations customEntryOperations) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Inject your SPI code around basic operation of inserting a new entry into the map.
+ *
+ * This affects behaviour of ordinary map.put(), map.computeIfAbsent(), etc. calls,
+ * as well as similar remote map calls and internal replication operation.
+ */
+ public ChronicleMapBuilder customizeAbsentEntryOperations(
+ MapAbsentEntryOperations customAbsentEntryOperations) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Inject your SPI around logic of all {@code ChronicleMap}'s operations with individual keys:
+ * from {@link ChronicleMap#containsKey} to {@link ChronicleMap#acquireUsing} and
+ * {@link ChronicleMap#merge}.
+ *
+ * This affects behaviour of ordinary map calls, as well as remote calls.
+ */
+ public ChronicleMapBuilder customizeMapMethods(MapMethods customMapMethods) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/src/main/java/net/openhft/chronicle/map/MapAbsentEntry.java b/src/main/java/net/openhft/chronicle/map/MapAbsentEntry.java
new file mode 100644
index 000000000..fc9bcbe5a
--- /dev/null
+++ b/src/main/java/net/openhft/chronicle/map/MapAbsentEntry.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2015 Higher Frequency Trading
+ *
+ * http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.map;
+
+import net.openhft.chronicle.hash.Value;
+
+public interface MapAbsentEntry {
+
+ Value absentKey();
+
+ boolean defaultInsert(Value value);
+
+ Value defaultValue();
+}
diff --git a/src/main/java/net/openhft/chronicle/map/MapAbsentEntryOperations.java b/src/main/java/net/openhft/chronicle/map/MapAbsentEntryOperations.java
new file mode 100644
index 000000000..824262b4e
--- /dev/null
+++ b/src/main/java/net/openhft/chronicle/map/MapAbsentEntryOperations.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2015 Higher Frequency Trading
+ *
+ * http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.map;
+
+import net.openhft.chronicle.hash.Value;
+import org.jetbrains.annotations.NotNull;
+
+public interface MapAbsentEntryOperations {
+
+ default boolean insert(@NotNull MapAbsentEntry absentEntry, Value value) {
+ return absentEntry.defaultInsert(value);
+ }
+
+ default Value defaultValue(@NotNull MapAbsentEntry absentEntry) {
+ return absentEntry.defaultValue();
+ }
+}
diff --git a/src/main/java/net/openhft/chronicle/map/MapEntry.java b/src/main/java/net/openhft/chronicle/map/MapEntry.java
new file mode 100644
index 000000000..7a064b273
--- /dev/null
+++ b/src/main/java/net/openhft/chronicle/map/MapEntry.java
@@ -0,0 +1,52 @@
+
+
+/*
+ * Copyright 2015 Higher Frequency Trading
+ *
+ * http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.map;
+
+import net.openhft.chronicle.hash.HashEntry;
+import net.openhft.chronicle.hash.Value;
+
+/**
+ * Access to the present {@link ChronicleMap} entry.
+ *
+ * @param type of the key in {@code ChronicleMap}
+ * @param type of the value in {@code ChronicleMap}
+ *
+ * @see MapEntryOperations
+ */
+public interface MapEntry extends HashEntry {
+ /**
+ * Returns the entry value.
+ */
+ Value value();
+
+ /**
+ * Replaces the entry's value with the new one. Returns {@code true} if the replace operation
+ * was successful, {@code false} if it failed for any reason.
+ *
+ * This method if the default implementation for {@link MapEntryOperations#replaceValue},
+ * which might be customized over the default.
+ *
+ * @throws IllegalStateException if some locking/state conditions required to perform replace
+ * operation are not met
+ */
+ boolean defaultReplaceValue(Value newValue);
+}
+
diff --git a/src/main/java/net/openhft/chronicle/map/MapEntryOperations.java b/src/main/java/net/openhft/chronicle/map/MapEntryOperations.java
new file mode 100644
index 000000000..dd61abdd6
--- /dev/null
+++ b/src/main/java/net/openhft/chronicle/map/MapEntryOperations.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2015 Higher Frequency Trading
+ *
+ * http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.map;
+
+import net.openhft.chronicle.hash.Value;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * SPI interface for customizing "low-level" modification operations on the present
+ * {@link ChronicleMap} entry.
+ *
+ * @param type of the key in {@code ChronicleMap}
+ * @param type of the value in {@code ChronicleMap}
+ */
+public interface MapEntryOperations {
+ /**
+ * Removes the given entry from the {@code ChronicleHash}. Returns {@code true} if the remove
+ * was successful, {@code false} if it failed for any reason.
+ *
+ * @implNote simply delegates to {@link MapEntry#defaultRemove()}.
+ *
+ * @param entry the entry to remove
+ * @throws IllegalStateException if some locking/state conditions required to perform remove
+ * operation are not met
+ */
+ default boolean remove(@NotNull MapEntry entry) {
+ return entry.defaultRemove();
+ }
+
+
+ /**
+ * Replaces the given entry's value with the new one. Returns {@code true} if the replace
+ * operation was successful, {@code false} if it failed for any reason.
+ *
+ * @implNote simply delegates to {@link MapEntry#defaultReplaceValue(Value)
+ * entry.defaultReplace(newValue)}
+ *
+ * @param entry the entry to replace the value in
+ * @throws IllegalStateException if some locking/state conditions required to perform replace
+ * operation are not met
+ */
+ default boolean replaceValue(@NotNull MapEntry entry, Value newValue) {
+ return entry.defaultReplaceValue(newValue);
+ }
+}
diff --git a/src/main/java/net/openhft/chronicle/map/MapKeyContext.java b/src/main/java/net/openhft/chronicle/map/MapKeyContext.java
index a2da94c6a..1917124e8 100644
--- a/src/main/java/net/openhft/chronicle/map/MapKeyContext.java
+++ b/src/main/java/net/openhft/chronicle/map/MapKeyContext.java
@@ -18,6 +18,7 @@ package net.openhft.chronicle.map;
import net.openhft.chronicle.hash.KeyContext;
+@Deprecated
public interface MapKeyContext extends KeyContext {
long valueOffset();
diff --git a/src/main/java/net/openhft/chronicle/map/MapMethods.java b/src/main/java/net/openhft/chronicle/map/MapMethods.java
new file mode 100644
index 000000000..190d00896
--- /dev/null
+++ b/src/main/java/net/openhft/chronicle/map/MapMethods.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2015 Higher Frequency Trading
+ *
+ * http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.map;
+
+import net.openhft.chronicle.hash.Value;
+
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+import static net.openhft.chronicle.hash.Value.bytesEquivalent;
+
+/**
+ * SPI interface for customizing behaviour of the specific Map's methods with individual keys.
+ */
+public interface MapMethods {
+
+ default boolean containsKey(MapQueryContext q) {
+ return q.entry() != null;
+ }
+
+ /**
+ * Backing {@link ChronicleMap#get}, {@link ChronicleMap#getUsing} and
+ * {@link ChronicleMap#getOrDefault} methods.
+ */
+ default void get(MapQueryContext q, ReturnValue super V> returnValue) {
+ MapMethodsSupport.returnCurrentValueIfPresent(q, returnValue);
+ }
+
+ default boolean put(MapQueryContext q,
+ Value value, ReturnValue super V> returnValue) {
+ // We cannot read the previous value under read lock, because then we will need
+ // to release the read lock -> acquire write lock, the value might be updated in
+ // between, that will break ConcurrentMap.put() atomicity guarantee. So, we acquire
+ // update lock from the start:
+ q.updateLock().lock();
+ MapEntry entry = q.entry();
+ if (entry != null) {
+ returnValue.returnValue(entry.value());
+ return q.replaceValue(entry, value);
+ } else {
+ return q.insert(q.absentEntry(), value);
+ }
+ }
+
+ default boolean putIfAbsent(MapQueryContext q,
+ Value value, ReturnValue super V> returnValue) {
+ if (MapMethodsSupport.tryReturnCurrentValueIfPresent(q, returnValue))
+ return false;
+ // Key is absent
+ return q.insert(q.absentEntry(), value);
+ }
+
+ default boolean acquireUsing(MapQueryContext q, ReturnValue super V> returnValue) {
+ if (MapMethodsSupport.tryReturnCurrentValueIfPresent(q, returnValue))
+ return false;
+ // Key is absent
+ Value defaultValue = q.defaultValue(q.absentEntry());
+ boolean inserted = q.insert(q.absentEntry(), defaultValue);
+ returnValue.returnValue(defaultValue);
+ return inserted;
+ }
+
+ default boolean remove(MapQueryContext q, ReturnValue super V> returnValue) {
+ // We cannot read the previous value under read lock, because then we will need
+ // to release the read lock -> acquire write lock, the value might be updated in
+ // between, that will break ConcurrentMap.remove() atomicity guarantee. So, we acquire
+ // update lock from the start:
+ q.updateLock().lock();
+ MapEntry entry = q.entry();
+ if (entry != null) {
+ returnValue.returnValue(entry.value());
+ return q.remove(entry);
+ } else {
+ return false;
+ }
+ }
+
+ default boolean remove(MapQueryContext q, Value value) {
+ // remove(key, value) should find the entry & remove most of the time,
+ // so don't try to check key presence and value equivalence under read lock first,
+ // as in putIfAbsent()/acquireUsing(), start with update lock:
+ q.updateLock().lock();
+ MapEntry entry = q.entry();
+ return entry != null &&
+ bytesEquivalent(entry.value(), value) &&
+ q.remove(entry);
+ }
+
+ default boolean replace(MapQueryContext q,
+ Value value, ReturnValue super V> returnValue) {
+ // replace(key, value) should find the key & put the value most of the time,
+ // so don't try to check key presence under read lock first,
+ // as in putIfAbsent()/acquireUsing(), start with update lock:
+ q.updateLock().lock();
+ MapEntry entry = q.entry();
+ if (entry != null) {
+ returnValue.returnValue(entry.value());
+ return q.replaceValue(entry, value);
+ } else {
+ return false;
+ }
+ }
+
+ default boolean replace(MapQueryContext q,
+ Value oldValue, Value newValue) {
+ // replace(key, old, new) should find the entry & put new value most of the time,
+ // so don't try to check key presence and value equivalence under read lock first,
+ // as in putIfAbsent()/acquireUsing(), start with update lock:
+ q.updateLock().lock();
+ MapEntry entry = q.entry();
+ return entry != null &&
+ bytesEquivalent(((MapEntry) entry).value(), oldValue) &&
+ q.replaceValue(entry, newValue);
+ }
+
+ default boolean compute(MapQueryContext q,
+ BiFunction super K, ? super V, ? extends V> remappingFunction,
+ Function> newValueObjectToValue,
+ ReturnValue super V> returnValue) {
+ q.updateLock().lock();
+ MapEntry entry = q.entry();
+ V oldValue = entry != null ? entry.value().get() : null;
+ V newValue = remappingFunction.apply(q.queriedKey().get(), oldValue);
+ if (newValue != null) {
+ Value newValueValue = newValueObjectToValue.apply(newValue);
+ boolean updated;
+ if (entry != null) {
+ updated = q.replaceValue(entry, newValueValue);
+ } else {
+ updated = q.insert(q.absentEntry(), newValueValue);
+ }
+ returnValue.returnValue(newValueValue);
+ return updated;
+ } else if (entry != null) {
+ return q.remove(entry);
+ } else {
+ return false;
+ }
+ }
+
+ default boolean merge(MapQueryContext q, Value value,
+ BiFunction super V, ? super V, ? extends V> remappingFunction,
+ Function> newValueObjectToValue,
+ ReturnValue super V> returnValue) {
+ q.updateLock().lock();
+ Value newValueValue;
+ boolean updated;
+ MapEntry entry = q.entry();
+ if (entry != null) {
+ V oldValue = entry.value().get();
+ V newValue = remappingFunction.apply(oldValue, value.get());
+ if (newValue == null)
+ return q.remove(entry);
+ newValueValue = newValueObjectToValue.apply(newValue);
+ updated = q.replaceValue(entry, newValueValue);
+ } else {
+ newValueValue = value;
+ updated = q.insert(q.absentEntry(), newValueValue);
+ }
+ returnValue.returnValue(newValueValue);
+ return updated;
+ }
+}
diff --git a/src/main/java/net/openhft/chronicle/map/MapMethodsSupport.java b/src/main/java/net/openhft/chronicle/map/MapMethodsSupport.java
new file mode 100644
index 000000000..07662d599
--- /dev/null
+++ b/src/main/java/net/openhft/chronicle/map/MapMethodsSupport.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2015 Higher Frequency Trading
+ *
+ * http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.map;
+
+final class MapMethodsSupport {
+
+ static void returnCurrentValueIfPresent(
+ MapQueryContext q, ReturnValue super V> returnValue) {
+ MapEntry entry = q.entry();
+ if (entry != null)
+ returnValue.returnValue(entry.value());
+ }
+
+ static boolean tryReturnCurrentValueIfPresent(
+ MapQueryContext q, ReturnValue super V> returnValue) {
+ if (q.readLock().tryLock()) {
+ MapEntry entry = q.entry();
+ if (entry != null) {
+ returnValue.returnValue(entry.value());
+ return true;
+ }
+ // Key is absent
+ q.readLock().unlock();
+ }
+ q.updateLock().lock();
+ MapEntry entry = q.entry();
+ if (entry != null) {
+ returnValue.returnValue(entry.value());
+ return true;
+ }
+ return false;
+ }
+
+ private MapMethodsSupport() {}
+}
diff --git a/src/main/java/net/openhft/chronicle/map/MapQueryContext.java b/src/main/java/net/openhft/chronicle/map/MapQueryContext.java
new file mode 100644
index 000000000..c969e256b
--- /dev/null
+++ b/src/main/java/net/openhft/chronicle/map/MapQueryContext.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015 Higher Frequency Trading
+ *
+ * http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.map;
+
+import net.openhft.chronicle.hash.Value;
+import net.openhft.chronicle.hash.locks.InterProcessReadWriteUpdateLock;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * The context of Map operations with individual keys (most: get(), put(), etc., opposed
+ * to bulk operations).
+ *
+ * @param
+ * @param
+ */
+public interface MapQueryContext extends InterProcessReadWriteUpdateLock,
+ MapEntryOperations, MapAbsentEntryOperations {
+
+ /**
+ * Returns the queried key as a value.
+ */
+ Value queriedKey();
+
+ /**
+ * Returns the entry access object, if the entry with the queried key is present
+ * in the map, returns {@code null} is the entry is absent. Might acquire
+ * {@link #readLock} before searching for the key, if the context is not locked yet.
+ */
+ @Nullable
+ MapEntry entry();
+
+ /**
+ * Returns the special absent entry object, if the entry with the queried key
+ * is absent in the map, returns {@code null}, if the entry is present. Might
+ * acquire {@link #readLock} before searching for the key, if the context is not locked yet.
+ */
+ @Nullable
+ MapAbsentEntry absentEntry();
+}
diff --git a/src/main/java/net/openhft/chronicle/map/ReturnValue.java b/src/main/java/net/openhft/chronicle/map/ReturnValue.java
new file mode 100644
index 000000000..913570cad
--- /dev/null
+++ b/src/main/java/net/openhft/chronicle/map/ReturnValue.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Higher Frequency Trading
+ *
+ * http://www.higherfrequencytrading.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.openhft.chronicle.map;
+
+import net.openhft.chronicle.hash.Value;
+import org.jetbrains.annotations.NotNull;
+
+public interface ReturnValue {
+ void returnValue(@NotNull Value extends V, ?> value);
+}