/*
Copyright (c) 2007 Health Market Science, Inc.
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; either
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.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
You can contact Health Market Science at info@healthmarketscience.com
or at the following address:
Health Market Science
2700 Horizon Drive
Suite 200
King of Prussia, PA 19406
*/
package com.healthmarketscience.rmiio;
import java.io.IOException;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Convenience base class for CloseableIOIterator implementations, especially
* suited for use as the local iterator for a RemoteIteratorServer
* instance. This implementation manages the closing of the local resources
* through three separate mechanisms. The {@link #close} method will be
* called:
* <ul>
* <li>by the {@link #next} method when the {@link #hasNext} method starts
* returning {@code false}</li>
* <li>when the close method is called directly (duh)</li>
* <li>if used with a RemoteIteratorServer, when the server is shutdown</li>
* </ul>
* This three-pronged attack provides a pretty strong guarantee that the local
* resources will be closed at some point in time. Note that the
* implementation of the {@link #close} method will call the
* {@link #closeImpl} method at most once. Extraneous invocations will be
* ignored.
*
* @author James Ahlborn
*/
public abstract class AbstractCloseableIOIterator<DataType>
implements CloseableIOIterator<DataType>
{
/** value which guarantees that the {@link #closeImpl} method is called at
most once */
private final AtomicBoolean _closed = new AtomicBoolean();
public AbstractCloseableIOIterator() {
}
public final DataType next()
throws IOException
{
if(!hasNext()) {
throw new NoSuchElementException();
}
// grab current element
DataType next = nextImpl();
if(!hasNext()) {
// all done with local resources, close them
close();
}
// return current element
return next;
}
public final void close()
{
// only close once
if(_closed.compareAndSet(false, true)) {
closeImpl();
}
}
/**
* Does the actual work of the {@link #next} method. Will only be called if
* {@link #hasNext} is currently returning {@code true}.
*/
protected abstract DataType nextImpl() throws IOException;
/**
* Does the actual closing of the local resources. Will be called at most
* once by the {@link #close} method regardless of how many times that
* method is invoked.
* <p>
* Note, this method does not throw {@code IOException} because it can be
* called in a variety of different scenarios and throwing an IOException
* would be useless in many of them (and often, failure to close is merely a
* nuisance, not a cause for failure).
*/
protected abstract void closeImpl();
}