package org.stianloader.mrjmania; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * Polyfills related to classes like {@link AtomicInteger}, {@link AtomicReference}, * etc. However, the polyfill themselves are probably the exact opposite of what * these classes usually provide. */ public class MRJAtomics { private MRJAtomics() { throw new UnsupportedOperationException(); } /** * Get the value of an {@link AtomicInteger}, with plain access if possible (J9+), otherwise be stricter from a * thread-safety standpoint. * * @param atomic The atomic object to pull the value from. * @return The value stored in the {@link AtomicInteger}, as per plain access (or volatile read, if plain access is not available). */ @Contract(pure = true) public static int getPlain(@NotNull AtomicInteger atomic) { return atomic.get(); } /** * Get the value of an {@link AtomicReference}, with plain access * if possible (J9+), otherwise be stricter. * * @param atomic The atomic object to pull the value from. * @param The type of the reference value stored by the {@link AtomicReference}. * @return The value stored in the {@link AtomicReference}, as per plain access (or volatile read, if plain access is not available). */ @Contract(pure = true) public static <@Nullable V> V getPlain(@NotNull AtomicReference atomic) { return atomic.get(); } /** * Sets the value of an {@link AtomicInteger} using a plain write if possible (J9+), otherwise be stricter from a * thread-safety standpoint. * *

A plain write might never get updated to threads, making this method highly unwise to use * in multi-threaded environments, unless stale reads are not a concern. * However, it is possible that other threads might see the updated value, so it should not * be expected that plain writes are thread-local. Generally, given enough time, * changes will be visible to other threads. * * @param atomic The {@link AtomicInteger} to set the value of. * @param value The value. */ @Contract(pure = false, mutates = "param1") public static void setPlain(@NotNull AtomicInteger atomic, int value) { atomic.lazySet(value); } /** * Sets the value of an {@link AtomicReference} using a plain write if possible (J9+), otherwise be stricter from a * thread-safety standpoint. * *

A plain write might never get updated to threads, making this method highly unwise to use * in multi-threaded environments, unless stale reads are not a concern. * However, it is possible that other threads might see the updated value, so it should not * be expected that plain writes are thread-local. Generally, given enough time, * changes will be visible to other threads. * * @param atomic The {@link AtomicReference} to set the value of. * @param value The value, may be null. * @param The type of the reference value stored by the {@link AtomicReference}. */ @Contract(pure = false, mutates = "param1") public static <@Nullable V> void setPlain(@NotNull AtomicReference atomic, V value) { atomic.lazySet(value); } }