/******************************************************************************* * Copyright 2011 See AUTHORS file. * * 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 com.badlogic.gdx.utils; import java.util.Comparator; /** * Guarantees that array entries provided by {@link #begin()} between indexes 0 and {@link #size} at the time begin was * called will not be modified until {@link #end()} is called. If modification of the SnapshotArray occurs between * begin/end, the backing array is copied prior to the modification, ensuring that the backing array that was returned * by {@link #begin()} is unaffected. To avoid allocation, an attempt is made to reuse any extra array created as a * result of this copy on subsequent copies. * <p> * It is suggested iteration be done in this specific way: * * <pre> * SnapshotArray array = new SnapshotArray(); * // ... * Object[] items = array.begin(); * for (int i = 0, n = array.size; i < n; i++) { * Object item = items[i]; * // ... * } * array.end(); * </pre> * * @author Nathan Sweet */ public class SnapshotArray<T> extends Array<T> { private T[] snapshot, recycled; private int snapshots; public SnapshotArray() { super(); } public SnapshotArray(Array array) { super(array); } public SnapshotArray(boolean ordered, int capacity, Class<T> arrayType) { super(ordered, capacity, arrayType); } public SnapshotArray(boolean ordered, int capacity) { super(ordered, capacity); } public SnapshotArray(boolean ordered, T[] array) { super(ordered, array); } public SnapshotArray(Class<T> arrayType) { super(arrayType); } public SnapshotArray(int capacity) { super(capacity); } public SnapshotArray(T[] array) { super(array); } /** Returns the backing array, which is guaranteed to not be modified before {@link #end()}. */ public T[] begin() { snapshot = items; snapshots++; return items; } /** Releases the guarantee that the array returned by {@link #begin()} won't be modified. */ public void end() { snapshots = Math.max(0, snapshots - 1); if (snapshot == null) return; if (snapshot != items && snapshots == 0) { // The backing array was copied, keep around the old array. recycled = snapshot; for (int i = 0, n = recycled.length; i < n; i++) recycled[i] = null; } snapshot = null; } private void modified() { if (snapshot == null || snapshot != items) return; // Snapshot is in use, copy backing array to recycled array or create new backing array. if (recycled != null && recycled.length >= size) { System.arraycopy(items, 0, recycled, 0, size); items = recycled; recycled = null; } else resize(items.length); } public void set(int index, T value) { modified(); super.set(index, value); } public void insert(int index, T value) { modified(); super.insert(index, value); } public void swap(int first, int second) { modified(); super.swap(first, second); } public boolean removeValue(T value, boolean identity) { modified(); return super.removeValue(value, identity); } public T removeIndex(int index) { modified(); return super.removeIndex(index); } public T pop() { modified(); return super.pop(); } public void clear() { modified(); super.clear(); } public void sort() { modified(); super.sort(); } public void sort(Comparator<T> comparator) { modified(); super.sort(comparator); } public void reverse() { modified(); super.reverse(); } public void shuffle() { modified(); super.shuffle(); } public void truncate(int newSize) { modified(); super.truncate(newSize); } }