Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 99ee3fe2 authored by Neil Fuller's avatar Neil Fuller Committed by Automerger Merge Worker
Browse files

Merge "Switch ReferenceWithHistory to use ArrayDeque" into rvc-dev am: c6eea102

Change-Id: I715e8bf1afc71f237247ed9d7e7678960bab7c03
parents 741d1045 c6eea102
Loading
Loading
Loading
Loading
+47 −12
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ import android.annotation.Nullable;

import com.android.internal.util.IndentingPrintWriter;

import java.util.LinkedList;
import java.util.ArrayDeque;

/**
 * A class that behaves like the following definition, except it stores the history of values set
@@ -50,11 +50,18 @@ import java.util.LinkedList;
 */
public final class ReferenceWithHistory<V> {

    /** The size the history linked list is allowed to grow to. */
    private static final Object NULL_MARKER = "{null marker}";

    /** The maximum number of references to store. */
    private final int mMaxHistorySize;

    /**
     * The history storage. Note that ArrayDeque doesn't support {@code null} so this stores Object
     * and not V. Use {@link #packNullIfRequired(Object)} and {@link #unpackNullIfRequired(Object)}
     * to convert to / from the storage object.
     */
    @Nullable
    private LinkedList<V> mValues;
    private ArrayDeque<Object> mValues;

    /**
     * Creates an instance that records, at most, the specified number of values.
@@ -69,22 +76,31 @@ public final class ReferenceWithHistory<V> {
    /** Returns the current value, or {@code null} if it has never been set. */
    @Nullable
    public V get() {
        return (mValues == null || mValues.isEmpty()) ? null : mValues.getFirst();
        if (mValues == null || mValues.isEmpty()) {
            return null;
        }
        Object value = mValues.getFirst();
        return unpackNullIfRequired(value);
    }

    /** Sets the current value. Returns the previous value, or {@code null}. */
    /**
     * Sets the current value. Returns the previous value, which can be {@code null} if the
     * reference has never been set, or if the reference has been set to {@code null}.
     */
    @Nullable
    public V set(@Nullable V newValue) {
        if (mValues == null) {
            mValues = new LinkedList<>();
            mValues = new ArrayDeque<>(mMaxHistorySize);
        }

        V previous = get();

        mValues.addFirst(newValue);
        if (mValues.size() > mMaxHistorySize) {
        if (mValues.size() >= mMaxHistorySize) {
            mValues.removeLast();
        }

        V previous = get();

        Object nullSafeValue = packNullIfRequired(newValue);
        mValues.addFirst(nullSafeValue);
        return previous;
    }

@@ -96,8 +112,8 @@ public final class ReferenceWithHistory<V> {
            ipw.println("{Empty}");
        } else {
            int i = 0;
            for (V value : mValues) {
                ipw.println(i + ": " + value);
            for (Object value : mValues) {
                ipw.println(i + ": " + unpackNullIfRequired(value));
                i++;
            }
        }
@@ -115,4 +131,23 @@ public final class ReferenceWithHistory<V> {
    public String toString() {
        return String.valueOf(get());
    }

    /**
     * Turns a non-nullable Object into a nullable value. See also
     * {@link #packNullIfRequired(Object)}.
     */
    @SuppressWarnings("unchecked")
    @Nullable
    private V unpackNullIfRequired(@NonNull Object value) {
        return value == NULL_MARKER ? null : (V) value;
    }

    /**
     * Turns a nullable value into a non-nullable Object. See also
     * {@link #unpackNullIfRequired(Object)}.
     */
    @NonNull
    private Object packNullIfRequired(@Nullable V value) {
        return value == null ? NULL_MARKER : value;
    }
}