org.eigenbase.runtime
Class TimeoutQueueTupleIter

java.lang.Object
  extended by org.eigenbase.runtime.TimeoutQueueTupleIter

public class TimeoutQueueTupleIter
extends Object

Adapter which allows you to iterate over an TupleIter with a timeout.

The interface is similar to an TupleIter: the fetchNext(long) method retrieves rows and indicates when there are no more rows. It has a timeout parameter, and throws a QueueIterator.TimeoutException if the timeout is exceeded. There is also a closeAllocation(long) method, which you must call.

The class is implemented using a thread which reads from the underlying TupleIter and places the results into a QueueIterator. If a method call times out, the underlying thread will wait for the result of the call until it completes.

There is no facility to cancel the fetch from the underlying iterator.

Reader/writer synchronization and the FENCEPOST. The thread within this class that reads row objects from the underlying TupleIter(s) must be careful not to read a subsequent row until the reading thread (e.g., the driver) is finished with the row. This is because the same row object may be re-used for subsequent rows. To achieve this, this class's thread always inserts FENCEPOST after every row object and the fetchNext(long) method detects and discards the fencepost. The nature of the underlying QueueIterator's SynchronousQueue prevents the writing thread from completing the put operation of the fencepost until the reading thread is prepared to read the value. In this way we guarantee that the row object is not modified until the reader has requested the next row object, at which point we assume it's safe to modify the row object.

Version:
$Id: //open/dev/farrago/src/org/eigenbase/runtime/TimeoutQueueTupleIter.java#11 $
Author:
Stephan Zuecher (based on tleung's TimeoutQueueIterator)

Nested Class Summary
private static class TimeoutQueueTupleIter.Fencepost
           
 
Field Summary
private static TimeoutQueueTupleIter.Fencepost FENCEPOST
          Prevents reader's row object from being clobbered by the next row.
private  TupleIter producer
           
private  QueueIterator queueIterator
           
private  Thread thread
           
 
Constructor Summary
TimeoutQueueTupleIter(TupleIter producer)
           
 
Method Summary
 void closeAllocation(long timeoutMillis)
          Releases the resources used by this iterator, including killing the underlying thread.
private  void doWork()
          Reads objects from the producer and writes them into the QueueIterator.
 Object fetchNext(long timeoutMillis)
          Retrieve the next row from the underlying TupleIter, with the given timeout, in milliseconds.
 void start()
          Starts the thread which reads from the consumer.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

FENCEPOST

private static final TimeoutQueueTupleIter.Fencepost FENCEPOST
Prevents reader's row object from being clobbered by the next row. See class description for how this works.


queueIterator

private final QueueIterator queueIterator

producer

private final TupleIter producer

thread

private Thread thread
Constructor Detail

TimeoutQueueTupleIter

public TimeoutQueueTupleIter(TupleIter producer)
Method Detail

fetchNext

public Object fetchNext(long timeoutMillis)
                 throws QueueIterator.TimeoutException
Retrieve the next row from the underlying TupleIter, with the given timeout, in milliseconds.

See class description re: FENCEPOST.

Parameters:
timeoutMillis - number of milliseconds to wait for the next row; less than or equal to 0 means do not wait
Returns:
next row
Throws:
QueueIterator.TimeoutException - on timeout

start

public void start()
Starts the thread which reads from the consumer.

"Precondition:"
thread == null // not previously started

closeAllocation

public void closeAllocation(long timeoutMillis)
Releases the resources used by this iterator, including killing the underlying thread.

Parameters:
timeoutMillis - Timeout while waiting for the underlying thread to die. Zero means wait forever.

doWork

private void doWork()
Reads objects from the producer and writes them into the QueueIterator. This is the method called by the thread when you call start(). Never throws an exception.

See class description re: FENCEPOST.