/* * Copyright 2016 Cel Skeggs * * This file is part of the CCRE, the Common Chicken Runtime Engine. * * The CCRE is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * The CCRE is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with the CCRE. If not, see <http://www.gnu.org/licenses/>. */ package ccre.util; import java.util.concurrent.ArrayBlockingQueue; import java.util.function.Supplier; import ccre.verifier.FlowPhase; /** * A thread-safe allocation pool with a maximum size that allocates additional * objects on demand. * * @author skeggsc * @param <E> the type of the allocated objects. */ public final class ThreadedAllocationPool<E> { private final ArrayBlockingQueue<E> queue; private final Supplier<E> constructor; /** * Creates a ThreadedAllocationPool. {@link Supplier#get()} will be called * on <code>constructor</code> whenever a new instance is needed. * * The easy way to use this is to write * <code>new ThreadedAllocationPool(1024, SomeClass::new)</code>, which will * dispatch to the zero-argument constructor of <code>SomeClass</code>. * * @param size the maximum number of cached instances, not including * instances currently handed out. * @param constructor the constructor for the pool. */ public ThreadedAllocationPool(int size, Supplier<E> constructor) { this.queue = new ArrayBlockingQueue<>(size); this.constructor = constructor; } /** * Returns an instance back to the pool. Be certain that you do not use this * instance afterward, because another thread could have taken it out. * * If the pool is full, the instance will be discarded. * * @param e the instance to return. * @return true if the instance was actually used, false if it was * discarded. */ @FlowPhase public boolean free(E e) { return this.queue.offer(e); } /** * Acquires an instance. If an instance is available in the pool, it will be * removed and returned. Otherwise, a new instance will be allocated and * returned. * * @return the instance. */ @FlowPhase public E allocate() { E ent = this.queue.poll(); if (ent == null) { ent = this.constructor.get(); } return ent; } }