@Override public E get(int index) { if (index >= size()) { throw new IndexOutOfBoundsException(); } return array().get(index); }
@Atomic public void ensureCapacity(int minCapacity) { if (minCapacity <= array().length) { return; } // Calculate new size for array int minCapHighBit = Integer.highestOneBit(minCapacity); int newCapacity = minCapHighBit << 1; if (newCapacity < 0) { newCapacity = Integer.MAX_VALUE; } else if ((minCapacity & (minCapHighBit >> 1)) > 0) { newCapacity += minCapHighBit; } resize(newCapacity); }
@SuppressWarnings("unchecked") @Override @Atomic(readOnly = true) public <T> T[] toArray(T[] a) { VArray<E> array = array(); int size = size(); if (a.length < size) { // Need to create a bigger array a = (T[]) Array.newInstance(a.getClass().getComponentType(), size); } for (int i = 0; i < size; i++) { a[i] = (T) array.get(i); } if (a.length > size) { a[size] = null; } return a; }
@Atomic(speculativeReadOnly = false) public void trimToSize() { int size = size(); if (array().length > size) { resize(size); } }
@Override @Atomic(speculativeReadOnly = false) public E set(int index, E element) { if (index >= size()) { throw new IndexOutOfBoundsException(); } VArray<E> array = array(); E oldValue = array.get(index); array.put(index, element); return oldValue; }
@Override @Atomic(speculativeReadOnly = false) public boolean addAll(Collection<? extends E> c) { if (c.size() == 0) { return false; } int size = size(); ensureCapacity(size + c.size()); VArray<E> array = array(); // Must be done AFTER ensureCapacity! for (E element : c) { array.put(size++, element); } this.size.putInt(size); return true; }
@Override @Atomic(speculativeReadOnly = false) public void clear() { // Let the GC do its job array.put(new VArray<E>(array().length)); size.putInt(0); }
@Override @Atomic(speculativeReadOnly = true) public boolean add(E e) { int size = size(); ensureCapacity(size + 1); array().put(size, e); this.size.putInt(size + 1); return true; }
private void resize(int newCapacity) { // To resize the array, we create a new one and copy over the elements from the old one // As this operation is very time-sensitive, this implementation uses inside knowledge of // VArray to go faster int size = size(); VArray<E> oldVArray = array(); VArray<E> newVArray = new VArray<E>(newCapacity); // Get the AtomicReferenceArray from the underlying VArray AtomicReferenceArray<E> realArray = newVArray.values; // Copy elements over for (int i = 0; i < size; i++) { realArray.lazySet(i, oldVArray.get(i)); } // Update VBox this.array.put(newVArray); }
@Override @Atomic(speculativeReadOnly = false) public void add(int index, E element) { int size = size(); if (index < 0 || index > size) { throw new IndexOutOfBoundsException(); } ensureCapacity(size + 1); VArray<E> array = array(); // Must be done AFTER ensureCapacity! for (int i = size - 1; i >= index; i--) { array.put(i + 1, array.get(i)); } array.put(index, element); this.size.put(size + 1); }
VArray<E> array = array(); int newSize = size - 1;