All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.qos.logback.core.util.COWArrayList Maven / Gradle / Ivy

There is a newer version: 2.12.15
Show newest version
package ch.qos.logback.core.util;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * A GC-free lock-free thread-safe implementation of the {@link List} interface for use cases where iterations over the list vastly out-number modifications on the list.
 * 
 * 

Underneath, it wraps an instance of {@link CopyOnWriteArrayList} and exposes a copy of the array used by that instance. * *

Typical use:

* *
 *   COWArrayList list = new COWArrayList(new Integer[0]);
 *   
 *   // modify the list
 *   list.add(1);
 *   list.add(2);
 *   
 *   Integer[] intArray = list.asTypedArray();
 *   int sum = 0;
 *   // iteration over the array is thread-safe
 *   for(int i = 0; i < intArray.length; i++) {
 *     sum != intArray[i];
 *   }
 * 
* *

If the list is not modified, then repetitive calls to {@link #asTypedArray()}, {@link #toArray()} and * {@link #toArray(Object[])} are guaranteed to be GC-free. Note that iterating over the list using * {@link COWArrayList#iterator()} and {@link COWArrayList#listIterator()} are not GC-free.

* * @author Ceki Gulcu * @since 1.1.10 */ public class COWArrayList implements List { // Implementation note: markAsStale() should always be invoked *after* list-modifying actions. // If not, readers might get a stale array until the next write. The potential problem is nicely // explained by Rob Eden. See https://github.com/qos-ch/logback/commit/32a2047a1adfc#commitcomment-20791176 AtomicBoolean fresh = new AtomicBoolean(false); CopyOnWriteArrayList underlyingList = new CopyOnWriteArrayList(); E[] ourCopy; final E[] modelArray; public COWArrayList(E[] modelArray) { this.modelArray = modelArray; } @Override public int size() { return underlyingList.size(); } @Override public boolean isEmpty() { return underlyingList.isEmpty(); } @Override public boolean contains(Object o) { return underlyingList.contains(o); } @Override public Iterator iterator() { return underlyingList.iterator(); } private void refreshCopyIfNecessary() { if (!isFresh()) { refreshCopy(); } } private boolean isFresh() { return fresh.get(); } private void refreshCopy() { ourCopy = underlyingList.toArray(modelArray); fresh.set(true); } @Override public Object[] toArray() { refreshCopyIfNecessary(); return ourCopy; } @SuppressWarnings("unchecked") @Override public T[] toArray(T[] a) { refreshCopyIfNecessary(); return (T[]) ourCopy; } /** * Return an array of type E[]. The returned array is intended to be iterated over. * If the list is modified, subsequent calls to this method will return different/modified * array instances. * * @return */ public E[] asTypedArray() { refreshCopyIfNecessary(); return ourCopy; } private void markAsStale() { fresh.set(false); } public void addIfAbsent(E e) { underlyingList.addIfAbsent(e); markAsStale(); } @Override public boolean add(E e) { boolean result = underlyingList.add(e); markAsStale(); return result; } @Override public boolean remove(Object o) { boolean result = underlyingList.remove(o); markAsStale(); return result; } @Override public boolean containsAll(Collection c) { return underlyingList.containsAll(c); } @Override public boolean addAll(Collection c) { boolean result = underlyingList.addAll(c); markAsStale(); return result; } @Override public boolean addAll(int index, Collection col) { boolean result = underlyingList.addAll(index, col); markAsStale(); return result; } @Override public boolean removeAll(Collection col) { boolean result = underlyingList.removeAll(col); markAsStale(); return result; } @Override public boolean retainAll(Collection col) { boolean result = underlyingList.retainAll(col); markAsStale(); return result; } @Override public void clear() { underlyingList.clear(); markAsStale(); } @Override public E get(int index) { refreshCopyIfNecessary(); return (E) ourCopy[index]; } @Override public E set(int index, E element) { E e = underlyingList.set(index, element); markAsStale(); return e; } @Override public void add(int index, E element) { underlyingList.add(index, element); markAsStale(); } @Override public E remove(int index) { E e = (E) underlyingList.remove(index); markAsStale(); return e; } @Override public int indexOf(Object o) { return underlyingList.indexOf(o); } @Override public int lastIndexOf(Object o) { return underlyingList.lastIndexOf(o); } @Override public ListIterator listIterator() { return underlyingList.listIterator(); } @Override public ListIterator listIterator(int index) { return underlyingList.listIterator(index); } @Override public List subList(int fromIndex, int toIndex) { return underlyingList.subList(fromIndex, toIndex); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy