Package org.carrot2.util.pool

Source Code of org.carrot2.util.pool.SoftUnboundedPool

/*
* Carrot2 project.
*
* Copyright (C) 2002-2014, Dawid Weiss, Stanisław Osiński.
* All rights reserved.
*
* Refer to the full license file "carrot2.LICENSE"
* in the root folder of the repository checkout or at:
* http://www.carrot2.org/carrot2.LICENSE
*/

package org.carrot2.util.pool;

import java.lang.ref.SoftReference;
import java.util.*;
import java.util.Map.Entry;

import org.carrot2.util.Pair;

import com.google.common.collect.Maps;

/**
* An extremely simple, unbounded object pool. The pool can provide objects of may types,
* objects get created using parameterless constructors. The pool holds objects using
* {@link SoftReference}s, so they can be garbage collected when memory is needed.
*/
public final class SoftUnboundedPool<T, P> implements IParameterizedPool<T, P>
{
    private Map<Pair<Class<? extends T>, P>, List<SoftReference<T>>> instances = Maps.newHashMap();

    private IInstantiationListener<T, P> instantiationListener;
    private IActivationListener<T, P> activationListener;
    private IPassivationListener<T, P> passivationListener;
    private IDisposalListener<T, P> disposalListener;

    public void init(IInstantiationListener<T, P> objectInstantiationListener,
        IActivationListener<T, P> objectActivationListener,
        IPassivationListener<T, P> objectPassivationListener,
        IDisposalListener<T, P> objectDisposalListener)
    {
        this.instantiationListener = objectInstantiationListener;
        this.activationListener = objectActivationListener;
        this.passivationListener = objectPassivationListener;
        this.disposalListener = objectDisposalListener;
    }
   
    @SuppressWarnings("unchecked")
    public <I extends T> I borrowObject(Class<I> clazz, P parameter)
        throws InstantiationException, IllegalAccessException
    {
        I instance = null;
        synchronized (this)
        {
            if (instances == null)
            {
                throw new IllegalStateException("The pool has already been disposed of");
            }

            final Pair<Class<? extends T>, P> key = new Pair<Class<? extends T>, P>(
                clazz, parameter);
            List<SoftReference<T>> list = instances.get(key);
            if (list == null)
            {
                list = new ArrayList<SoftReference<T>>();
                instances.put(key, list);
            }

            while (list.size() > 0 && instance == null)
            {
                // This cast goes unchecked and can be broken by bad calls, but we shift
                // the responsibility to the users of this class.
                instance = (I) list.remove(0).get();
            }
        }

        // Not a problem that many threads create new objects for now.
        if (instance == null)
        {
            instance = clazz.newInstance();
            if (instantiationListener != null)
            {
                instantiationListener.objectInstantiated(instance, parameter);
            }
        }

        if (activationListener != null)
        {
            activationListener.activate(instance, parameter);
        }

        return instance;
    }

    public void returnObject(T object, P parameter)
    {
        if (object == null)
        {
            return;
        }

        if (passivationListener != null)
        {
            passivationListener.passivate(object, parameter);
        }

        synchronized (this)
        {
            if (instances == null)
            {
                return;
            }

            @SuppressWarnings({
                "rawtypes", "unchecked"
            })
            final Pair key = new Pair(object.getClass(), parameter);
            final List<SoftReference<T>> list = instances.get(key);
            if (list == null)
            {
                throw new IllegalStateException(
                    "Returning an object that was never borrowed: " + object);
            }

            // The object must not be on the list at this point. The pool won't be large
            // enough for the linear scan to be a problem.
            for (SoftReference<T> reference : list)
            {
                final T o = reference.get();
                if (o != null && o == object)
                {
                    throw new IllegalStateException("Object has not been borrowed");
                }
            }
           
            list.add(new SoftReference<T>(object));
        }
    }

    public void dispose()
    {
        synchronized (this)
        {
            if (this.instances == null)
            {
                return;
            }
           
            Map<Pair<Class<? extends T>, P>, List<SoftReference<T>>> instancesRef = this.instances;
            this.instances = null;

            for (Entry<Pair<Class<? extends T>, P>, List<SoftReference<T>>> entry : instancesRef.entrySet())
            {
                for (SoftReference<T> reference : entry.getValue())
                {
                    T instance = reference.get();
                    if (instance != null && disposalListener != null)
                    {
                        disposalListener.dispose(instance, entry.getKey().objectB);
                    }
                }
            }
        }
    }
}
TOP

Related Classes of org.carrot2.util.pool.SoftUnboundedPool

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.