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

com.oracle.coherence.concurrent.atomic.AsyncRemoteAtomicReference Maven / Gradle / Ivy

Go to download

Utility classes commonly useful in concurrent programming within a Coherence Cluster.

There is a newer version: 24.03.1
Show newest version
/*
 * Copyright (c) 2020, 2021, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */
package com.oracle.coherence.concurrent.atomic;

import com.tangosol.net.AsyncNamedMap;

import com.tangosol.util.function.Remote;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;

import java.util.function.BinaryOperator;
import java.util.function.UnaryOperator;

/**
 * The remote implementation of {@link AsyncAtomicReference}, backed by a
 * Coherence {@code NamedMap} entry.
 * 

* Every method in this class is guaranteed to execute effectively-once, and provides * cluster-wide atomicity guarantees for the backing atomic value. However, * keep in mind that this comes at a significant cost -- each method invocation * results in a network call to a remote owner of the backing atomic value, * which means that each operation has significantly higher latency than a * corresponding {@link AsyncLocalAtomicReference local} implementation. * * @param the type of object referred to by this reference * * @author Aleks Seovic 2020.12.08 * @since 21.12 */ public class AsyncRemoteAtomicReference implements AsyncAtomicReference { // ----- constructors --------------------------------------------------- /** * Constructs a new {@code AsyncRemoteAtomicReference}. * * @param mapAtomic the map that holds this atomic value * @param sName the name of this atomic value */ protected AsyncRemoteAtomicReference(AsyncNamedMap> mapAtomic, String sName) { f_mapAtomic = mapAtomic; f_sName = sName; } // ----- AsyncAtomicReference interface ------------------------------ @Override public CompletableFuture get() { return invoke(AtomicReference::get, false); } @Override public CompletableFuture set(V newValue) { return invoke(value -> { value.set(newValue); return null; }); } @Override public CompletableFuture getAndSet(V newValue) { return invoke(value -> value.getAndSet(newValue)); } @Override @SuppressWarnings("DuplicatedCode") public CompletableFuture compareAndSet(V expectedValue, V newValue) { return invoke(value -> { V v = value.get(); if (Objects.equals(v, expectedValue)) { value.set(newValue); return true; } return false; }); } @Override public CompletableFuture getAndUpdate(Remote.UnaryOperator updateFunction) { return getAndUpdate((UnaryOperator) updateFunction); } @Override public CompletableFuture getAndUpdate(UnaryOperator updateFunction) { return invoke(value -> value.getAndUpdate(updateFunction)); } @Override public CompletableFuture updateAndGet(Remote.UnaryOperator updateFunction) { return updateAndGet((UnaryOperator) updateFunction); } @Override public CompletableFuture updateAndGet(UnaryOperator updateFunction) { return invoke(value -> value.updateAndGet(updateFunction)); } @Override public CompletableFuture getAndAccumulate(V x, Remote.BinaryOperator accumulatorFunction) { return getAndAccumulate(x, (BinaryOperator) accumulatorFunction); } @Override public CompletableFuture getAndAccumulate(V x, BinaryOperator accumulatorFunction) { return invoke(value -> value.getAndAccumulate(x, accumulatorFunction)); } @Override public CompletableFuture accumulateAndGet(V x, Remote.BinaryOperator accumulatorFunction) { return accumulateAndGet(x, (BinaryOperator) accumulatorFunction); } @Override public CompletableFuture accumulateAndGet(V x, BinaryOperator accumulatorFunction) { return invoke(value -> value.accumulateAndGet(x, accumulatorFunction)); } @Override @SuppressWarnings("DuplicatedCode") public CompletableFuture compareAndExchange(V expectedValue, V newValue) { return invoke(value -> { V v = value.get(); if (v == null) { if (expectedValue == null) { value.set(newValue); } } else { if (v.equals(expectedValue)) { value.set(newValue); } } return v; }); } // ----- Object methods ------------------------------------------------- /** * Returns the String representation of the current value. * * @return the String representation of the current value */ @Override public String toString() { return String.valueOf(get().join()); } // ----- helpers methods ------------------------------------------------ /** * Apply specified function against the remote object and return the result. * *

Any changes the function makes to the remote object will be preserved. * * @param function the function to apply * @param the type of the result * * @return the result of the function applied to a remote object */ protected CompletableFuture invoke(Remote.Function, R> function) { return invoke(function, true); } /** * Apply specified function against the remote object and return the result. * *

If the {@code fMutate} argument is {@code true}, any changes to the * remote object will be preserved. * * @param function the function to apply * @param fMutate flag specifying whether the function mutates the object * @param the type of the result * * @return the result of the function applied to a remote object */ protected CompletableFuture invoke(Remote.Function, R> function, boolean fMutate) { return f_mapAtomic.invoke(f_sName, entry -> { AtomicReference value = entry.getValue(); R result = function.apply(value); if (fMutate) { entry.setValue(value); } return result; }); } // ----- data members --------------------------------------------------- /** * The map that holds this atomic value. */ private final AsyncNamedMap> f_mapAtomic; /** * The name of this atomic value. */ private final String f_sName; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy