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

org.eclipse.sisu.inject.RankedBindings Maven / Gradle / Ivy

There is a newer version: 3.0.0-alpha-3
Show newest version
/*******************************************************************************
 * Copyright (c) 2010-present Sonatype, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Stuart McCulloch (Sonatype, Inc.) - initial API and implementation
 *******************************************************************************/
package org.eclipse.sisu.inject;

import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Iterator;

import com.google.inject.Binding;
import com.google.inject.TypeLiteral;

/**
 * Ordered sequence of {@link Binding}s of a given type; subscribes to {@link BindingPublisher}s on demand.
 */
final class RankedBindings
    implements Iterable>, BindingSubscriber
{
    // ----------------------------------------------------------------------
    // Implementation fields
    // ----------------------------------------------------------------------

    final transient RankedSequence> bindings = new RankedSequence>();

    final transient TypeLiteral type;

    final transient RankedSequence pendingPublishers;

    final Collection> cachedBeans = Weak.elements();

    // ----------------------------------------------------------------------
    // Constructors
    // ----------------------------------------------------------------------

    RankedBindings( final TypeLiteral type, final RankedSequence publishers )
    {
        this.type = type;
        this.pendingPublishers = new RankedSequence( publishers );
    }

    // ----------------------------------------------------------------------
    // Public methods
    // ----------------------------------------------------------------------

    public TypeLiteral type()
    {
        return type;
    }

    public void add( final Binding binding, final int rank )
    {
        bindings.insert( binding, rank );
    }

    public void remove( final Binding binding )
    {
        if ( bindings.removeThis( binding ) )
        {
            synchronized ( cachedBeans )
            {
                for ( final BeanCache beans : cachedBeans )
                {
                    beans.remove( binding );
                }
            }
        }
    }

    public Iterable> bindings()
    {
        return bindings.snapshot();
    }

    public Itr iterator()
    {
        return new Itr();
    }

    // ----------------------------------------------------------------------
    // Local methods
    // ----------------------------------------------------------------------

     BeanCache newBeanCache()
    {
        final BeanCache beans = new BeanCache();
        synchronized ( cachedBeans )
        {
            cachedBeans.add( beans );
        }
        return beans;
    }

    void add( final BindingPublisher publisher, final int rank )
    {
        /*
         * No need to lock; ranked sequence is thread-safe.
         */
        pendingPublishers.insert( publisher, rank );
    }

    void remove( final BindingPublisher publisher )
    {
        /*
         * Lock just to prevent subscription race condition.
         */
        synchronized ( publisher ) // NOSONAR
        {
            if ( !pendingPublishers.removeThis( publisher ) )
            {
                publisher.unsubscribe( this );
            }
        }
    }

    // ----------------------------------------------------------------------
    // Implementation types
    // ----------------------------------------------------------------------

    /**
     * {@link Binding} iterator that only subscribes to {@link BindingPublisher}s as required.
     */
    final class Itr
        implements Iterator>
    {
        // ----------------------------------------------------------------------
        // Implementation fields
        // ----------------------------------------------------------------------

        private final RankedSequence>.Itr itr = bindings.iterator();

        // ----------------------------------------------------------------------
        // Public methods
        // ----------------------------------------------------------------------

        public boolean hasNext()
        {
            // apply any publishers that could add bindings before the current position
            BindingPublisher publisher = pendingPublishers.peek();
            while ( null != publisher && !itr.hasNext( publisher.maxBindingRank() ) )
            {
                synchronized ( publisher )
                {
                    // check in case subscribed by another thread
                    if ( publisher == pendingPublishers.peek() )
                    {
                        // only update list _after_ subscription
                        publisher.subscribe( RankedBindings.this );
                        pendingPublishers.removeThis( publisher );
                    }
                }
                publisher = pendingPublishers.peek();
            }
            return itr.hasNext();
        }

        public Binding next()
        {
            return itr.next();
        }

        public int rank()
        {
            return itr.rank();
        }

        public void remove()
        {
            throw new UnsupportedOperationException();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy