/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2010-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2010-2012, Geomatys * * This library 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; * version 2.1 of the License. * * This library 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. */ package org.geotoolkit.coverage.io; /** * A pool of {@link GridCoverageReader} and {@link GridCoverageWriter} instances. * This pool can be useful if many grid coverages are likely to be read or written, * and the readers or writers are costly to create. * * {@note In Geotk implementation, <code>GridCoverageReader</code> and <code>GridCoverageWriter</code> * are not directly costly to create. However they may hold references to <code>ImageReader</code> or * <code>ImageWriter</code> instances, and some kind of those Java I/O objects are costly to create.} * * This class is typically used as below. Note that it is not strictly necessary to invoke * the {@link #release(GridCoverageReader)} method in a {@code finally} block. * * {@preformat java * class MyClass { * private final GridCoverageStorePool pool = new GridCoverageStorePool(4); * * GridCoverage2D getCoverage() throws CoverageStoreException { * GridCoverageReader reader = pool.acquireReader(); * GridCoverage2D coverage = reader.read(...); * pool.release(reader); * return coverage; * } * } * } * * The default pool implementation creates instances of {@link ImageCoverageReader}. Subclasses * can create other kind of implementations by overriding the {@link #createReader()} method. * * @author Martin Desruisseaux (Geomatys) * @version 3.10 * * @since 3.10 * @module * * @todo Needs a background task for disposing the readers or writers after some amount * of inactivity. */ public class GridCoverageStorePool { /** * The grid coverage readers. */ private final GridCoverageReader[] readers; /** * Number of valid elements in {@link #readers}. */ private int readerCount; /** * Creates a new pool which will accept the given maximal amount of readers and writers. * * @param max The maximal amount of readers and writers to keep in the pool. */ public GridCoverageStorePool(final int max) { readers = new GridCoverageReader[max]; } /** * Invoked when a new image reader needs to be created. The default implementation * returns a new instance of {@link ImageCoverageReader}. Subclasses can override * this method if they want to supply an other kind of reader. * * @return A new reader instance, to be returned by {@link #acquireReader()}. * @throws CoverageStoreException If the reader can not be created. */ protected GridCoverageReader createReader() throws CoverageStoreException { return new ImageCoverageReader(); } /** * Returns a reader from the pool, or {@linkplain #createReader() creates} a new one if the * pool is empty. Callers shall invoke {@link #release(GridCoverageReader)} when they finished * using the reader, in order to return it to the pool. However it is not necessary to perform * the release in a {@code finally} block: if the reader is never returned to the pool, it will * be garbage-collected. * * @return A reader instance available for use. * @throws CoverageStoreException If the reader can not be created. */ public GridCoverageReader acquireReader() throws CoverageStoreException { synchronized (readers) { int n = readerCount; if (n != 0) { readerCount = --n; final GridCoverageReader reader = readers[n]; readers[n] = null; return reader; } } return createReader(); } /** * Returns the given reader to the pool. This method {@linkplain GridCoverageReader#reset() * resets} the given reader and adds it to the pool if the pool is not full. If the pull is * full, then this method {@linkplain GridCoverageReader#dispose() disposes} the given reader. * * @param reader The reader to return to the pool. * @throws CoverageStoreException If an error occurred while reseting or disposing the reader. */ public void release(final GridCoverageReader reader) throws CoverageStoreException { reader.reset(); // Close the image input stream, if any. synchronized (readers) { if (readerCount != readers.length) { readers[readerCount++] = reader; return; } } reader.dispose(); } }