/******************************************************************************* | |
* 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 arrayType) { | |
super(ordered, capacity, arrayType); | |
} | |
public SnapshotArray (boolean ordered, int capacity) { | |
super(ordered, capacity); | |
} | |
public SnapshotArray (boolean ordered, T[] array, int startIndex, int count) { | |
super(ordered, array, startIndex, count); | |
} | |
public SnapshotArray (Class 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 () { | |
modified(); | |
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 void removeRange (int start, int end) { | |
modified(); | |
super.removeRange(start, end); | |
} | |
public boolean removeAll (Array<? extends T> array, boolean identity) { | |
modified(); | |
return super.removeAll(array, identity); | |
} | |
public T pop () { | |
modified(); | |
return super.pop(); | |
} | |
public void clear () { | |
modified(); | |
super.clear(); | |
} | |
public void sort () { | |
modified(); | |
super.sort(); | |
} | |
public void sort (Comparator<? super 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); | |
} | |
public T[] setSize (int newSize) { | |
modified(); | |
return super.setSize(newSize); | |
} | |
/** @see #SnapshotArray(Object[]) */ | |
static public <T> SnapshotArray<T> with (T... array) { | |
return new SnapshotArray(array); | |
} | |
} |