org.eclipse.sisu.inject.MildElements Maven / Gradle / Ivy
/*
* Copyright (c) 2010-2024 Sonatype, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Stuart McCulloch (Sonatype, Inc.) - initial API and implementation
*/
package org.eclipse.sisu.inject;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
/**
* NON-thread-safe {@link Collection} of elements kept alive by soft/weak {@link Reference}s.
*/
final class MildElements
extends AbstractCollection
{
// ----------------------------------------------------------------------
// Implementation fields
// ----------------------------------------------------------------------
private final ReferenceQueue queue = new ReferenceQueue();
final List> list;
private final boolean soft;
// ----------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------
MildElements( final List> list, final boolean soft )
{
this.list = list;
this.soft = soft;
}
// ----------------------------------------------------------------------
// Public methods
// ----------------------------------------------------------------------
@Override
public boolean add( final T element )
{
compact();
return list.add( soft ? new Soft( element, queue, list.size() )
: new Weak( element, queue, list.size() ) );
}
@Override
public int size()
{
compact();
return list.size();
}
@Override
public Iterator iterator()
{
compact();
return new Itr();
}
// ----------------------------------------------------------------------
// Implementation methods
// ----------------------------------------------------------------------
/**
* Compacts the list by replacing unreachable {@link Reference}s with ones from the end.
*/
private void compact()
{
for ( Reference extends T> ref; ( ref = queue.poll() ) != null; )
{
evict( ref );
}
}
/**
* Evicts a single {@link Reference} from the list; replacing it with one from the end.
*
* @param ref The reference to evict
*/
void evict( final Reference extends T> ref )
{
final int index = ( (Indexable) ref ).index( -1 );
if ( index >= 0 )
{
final Reference last = list.remove( list.size() - 1 );
if ( ref != last )
{
( (Indexable) last ).index( index );
list.set( index, last );
}
}
}
// ----------------------------------------------------------------------
// Implementation types
// ----------------------------------------------------------------------
/**
* Represents an element that can be indexed.
*/
private interface Indexable
{
int index( int index );
}
/**
* {@link Iterator} that iterates over reachable {@link Reference}s in the list.
*/
final class Itr
implements Iterator
{
// ----------------------------------------------------------------------
// Implementation fields
// ----------------------------------------------------------------------
private int index;
private T nextElement;
private boolean haveElement;
// ----------------------------------------------------------------------
// Public methods
// ----------------------------------------------------------------------
public boolean hasNext()
{
// find next element that is still reachable
while ( null == nextElement && index < list.size() )
{
nextElement = list.get( index++ ).get();
}
return null != nextElement;
}
public T next()
{
haveElement = hasNext();
if ( haveElement )
{
// populated by hasNext()
final T element = nextElement;
nextElement = null;
return element;
}
throw new NoSuchElementException();
}
public void remove()
{
if ( haveElement )
{
evict( list.get( --index ) );
haveElement = false;
}
else
{
throw new IllegalStateException();
}
}
}
/**
* Soft {@link Indexable} element.
*/
private static final class Soft
extends SoftReference
implements Indexable
{
// ----------------------------------------------------------------------
// Implementation fields
// ----------------------------------------------------------------------
private int index;
// ----------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------
Soft( final T value, final ReferenceQueue queue, final int index )
{
super( value, queue );
this.index = index;
}
// ----------------------------------------------------------------------
// Public methods
// ----------------------------------------------------------------------
public int index( final int newIndex )
{
final int oldIndex = index;
index = newIndex;
return oldIndex;
}
}
/**
* Weak {@link Indexable} element.
*/
private static final class Weak
extends WeakReference
implements Indexable
{
// ----------------------------------------------------------------------
// Implementation fields
// ----------------------------------------------------------------------
private int index;
// ----------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------
Weak( final T value, final ReferenceQueue queue, final int index )
{
super( value, queue );
this.index = index;
}
// ----------------------------------------------------------------------
// Public methods
// ----------------------------------------------------------------------
public int index( final int newIndex )
{
final int oldIndex = index;
index = newIndex;
return oldIndex;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy