All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.openhft.chronicle.map.MapEntryOperations Maven / Gradle / Ivy

There is a newer version: 3.26ea4
Show newest version
/*
 * Copyright 2012-2018 Chronicle Map Contributors
 *
 * 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.Data;
import net.openhft.chronicle.map.replication.MapRemoteOperations;
import org.jetbrains.annotations.NotNull;

/**
 * SPI interface for customizing "low-level" modification operations on {@link ChronicleMap}
 * entries. All {@code ChronicleMap} modifications operate via an instance of this interface:
 * 
    *
  • Ordinary query operations: {@code map.put()}, {@code map.compute()}, {@code map.remove()} *
  • *
  • Operations with entry during iterations on the map, or the key/value/entry views, * like {@code iterator.remove()}.
  • *
  • Remote map operation calls and Replicated {@code ChronicleMap} reconciliation operations: * see {@link MapRemoteOperations}.
  • *
*

*

By default {@link #remove}, {@link #insert} and {@link #replaceValue} return {@code null}, * but subclasses could return something more sensible, to be used in higher-level SPI interfaces, * namely {@link MapMethods} and {@link MapRemoteOperations}. For example, in bidirectional map * implementation (i. e. a map that preserves the uniqueness of its values as well as that of * its keys), that includes two {@code ChronicleMaps}, the {@code MapEntryOperations}' methods return * type could be used to indicate if we were successful to lock both maps before performing * the update:


 * enum DualLockSuccess {SUCCESS, FAIL}
 * 

* class{@code BiMapEntryOperations} * implements{@code MapEntryOperations} { * {@code ChronicleMap} reverse; *

* public void{@code setReverse(ChronicleMap} reverse) { * this.reverse = reverse; * } *

* {@literal @}Override * public DualLockSuccess{@literal remove(@}NotNull{@code MapEntry} entry) { * try{@code (ExternalMapQueryContext} rq = reverse.queryContext(entry.value())) { * if (!rq.updateLock().tryLock()) { * if (entry.context() instanceof MapQueryContext) * return FAIL; * throw new IllegalStateException("Concurrent modifications to reverse map " + * "during remove during iteration"); * } * {@code MapEntry} reverseEntry = rq.entry(); * if (reverseEntry != null) { * entry.doRemove(); * reverseEntry.doRemove(); * return SUCCESS; * } else { * throw new IllegalStateException(entry.key() + " maps to " + entry.value() + * ", but in the reverse map this value is absent"); * } * } * } *

* // ... other methods * } *

* class{@code BiMapMethods} implements{@code MapMethods} { * {@literal @}Override * public void{@code remove(MapQueryContext} q, * {@code ReturnValue} returnValue) { * while (true) { * q.updateLock().lock(); * try { * {@code MapEntry} entry = q.entry(); * if (entry != null) { * returnValue.returnValue(entry.value()); * if (q.remove(entry) == SUCCESS) * return; * } * } finally { * q.readLock().unlock(); * } * } * } *

* // ... other methods * }

* * @param the map key type * @param the map value type * @param methods return type, used for communication between lower- and higher-level SPI * @see ChronicleMapBuilder#entryOperations(MapEntryOperations) */ public interface MapEntryOperations { /** * Removes the given entry from the map. * * @param entry the entry to remove * @return result of operation, understandable by higher-level SPIs, e. g. custom * {@link MapMethods} implementation * @throws IllegalStateException if some locking/state conditions required to perform remove * operation are not met * @throws RuntimeException if removal was unconditionally unsuccessful due to any reason * @implNote default implementation calls {@link MapEntry#doRemove()} on the given entry * and returns {@code null}. */ default R remove(@NotNull MapEntry entry) { entry.doRemove(); return null; } /** * Replaces the given entry's value with the new one. * * @param entry the entry to replace the value in * @return result of operation, understandable by higher-level SPIs, e. g. custom * {@link MapMethods} implementation * @throws IllegalStateException if some locking/state conditions required to perform replace * operation are not met * @throws RuntimeException if value replacement was unconditionally unsuccessful due * to any reason * @implNote default implementation calls {@link MapEntry#doReplaceValue(Data) * entry.doReplaceValue(newValue)} and returns {@code null}. */ default R replaceValue(@NotNull MapEntry entry, Data newValue) { entry.doReplaceValue(newValue); return null; } /** * Inserts the new entry into the map, of {@link MapAbsentEntry#absentKey() the key} from * the given insertion context (absentEntry) and the given {@code value}. * * @return result of operation, understandable by higher-level SPIs, e. g. custom * {@link MapMethods} implementation * @throws IllegalStateException if some locking/state conditions required to perform insertion * operation are not met * @throws RuntimeException if insertion was unconditionally unsuccessful due to any reason * @implNote default implementation calls {@link MapAbsentEntry#doInsert(Data) * absentEntry.doInsert(value)} and returns {@code null}. */ default R insert(@NotNull MapAbsentEntry absentEntry, Data value) { absentEntry.doInsert(value); return null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy