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

Commit 3bb222aa authored by Neil Fuller's avatar Neil Fuller Committed by Android (Google) Code Review
Browse files

Merge "Switch ReferenceWithHistory to use ArrayDeque"

parents 5e2addf2 1ab9b864
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;
    }
}