Author: jcarman Date: Fri Nov 11 12:39:13 2005 New Revision: 332643 URL: http://svn.apache.org/viewcvs?rev=332643&view=rev Log: Bug 37472: Implement a TimeoutBuffer class
Added: jakarta/commons/proper/collections/trunk/data/test/TimeoutBuffer.emptyCollection.version3.2.obj (with props) jakarta/commons/proper/collections/trunk/data/test/TimeoutBuffer.fullCollection.version3.2.obj (with props) jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/TimeoutBuffer.java (with props) jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestTimeoutBuffer.java (with props) jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/functors/ Modified: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/BufferUtils.java jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestAll.java Added: jakarta/commons/proper/collections/trunk/data/test/TimeoutBuffer.emptyCollection.version3.2.obj URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/data/test/TimeoutBuffer.emptyCollection.version3.2.obj?rev=332643&view=auto ============================================================================== Binary file - no diff available. Propchange: jakarta/commons/proper/collections/trunk/data/test/TimeoutBuffer.emptyCollection.version3.2.obj ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: jakarta/commons/proper/collections/trunk/data/test/TimeoutBuffer.fullCollection.version3.2.obj URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/data/test/TimeoutBuffer.fullCollection.version3.2.obj?rev=332643&view=auto ============================================================================== Binary file - no diff available. Propchange: jakarta/commons/proper/collections/trunk/data/test/TimeoutBuffer.fullCollection.version3.2.obj ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Modified: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/BufferUtils.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/BufferUtils.java?rev=332643&r1=332642&r2=332643&view=diff ============================================================================== --- jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/BufferUtils.java (original) +++ jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/BufferUtils.java Fri Nov 11 12:39:13 2005 @@ -21,6 +21,7 @@ import org.apache.commons.collections.buffer.TransformedBuffer; import org.apache.commons.collections.buffer.TypedBuffer; import org.apache.commons.collections.buffer.UnmodifiableBuffer; +import org.apache.commons.collections.buffer.TimeoutBuffer; /** * Provides utility methods and decorators for [EMAIL PROTECTED] Buffer} instances. @@ -37,7 +38,7 @@ * An empty unmodifiable buffer. */ public static final Buffer EMPTY_BUFFER = UnmodifiableBuffer.decorate(new ArrayStack(1)); - + /** * <code>BufferUtils</code> should not normally be instantiated. */ @@ -86,6 +87,22 @@ } /** + * Returns a synchronized buffer backed by the given buffer that will + * block on [EMAIL PROTECTED] Buffer#get()} and [EMAIL PROTECTED] Buffer#remove()} operations until + * <code>timeout</code> expires. If the buffer is empty, then the + * [EMAIL PROTECTED] Buffer#get()} and [EMAIL PROTECTED] Buffer#remove()} operations will block + * until new elements are added to the buffer, rather than immediately throwing a + * <code>BufferUnderflowException</code>. + * + * @param buffer the buffer to synchronize, must not be null + * @return a blocking buffer backed by that buffer + * @throws IllegalArgumentException if the Buffer is null + */ + public static Buffer timeoutBuffer(Buffer buffer, long timeout) { + return TimeoutBuffer.decorate(buffer, timeout); + } + + /** * Returns an unmodifiable buffer backed by the given buffer. * * @param buffer the buffer to make unmodifiable, must not be null @@ -142,5 +159,5 @@ public static Buffer transformedBuffer(Buffer buffer, Transformer transformer) { return TransformedBuffer.decorate(buffer, transformer); } - + } Added: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/TimeoutBuffer.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/TimeoutBuffer.java?rev=332643&view=auto ============================================================================== --- jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/TimeoutBuffer.java (added) +++ jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/TimeoutBuffer.java Fri Nov 11 12:39:13 2005 @@ -0,0 +1,103 @@ +/* + * Copyright 2001-2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.collections.buffer; + +import org.apache.commons.collections.Buffer; + +/** + * Decorates another <code>Buffer</code> to make [EMAIL PROTECTED] #get()} and + * [EMAIL PROTECTED] #remove()} block (until timeout expires) when the <code>Buffer</code> is empty. + * <p> + * If either <code>get</code> or <code>remove</code> is called on an empty + * <code>Buffer</code>, the calling thread waits (until timeout expires) for notification that + * an <code>add</code> or <code>addAll</code> operation has completed. + * <p> + * When one or more entries are added to an empty <code>Buffer</code>, + * all threads blocked in <code>get</code> or <code>remove</code> are notified. + * There is no guarantee that concurrent blocked <code>get</code> or + * <code>remove</code> requests will be "unblocked" and receive data in the + * order that they arrive. + * <p> + * This class is Serializable from Commons Collections 3.2. + * + * @author James Carman + * @version $Revision$ $Date$ + * @since Commons Collections 3.2 + */ +public class TimeoutBuffer extends BlockingBuffer { +//---------------------------------------------------------------------------------------------------------------------- +// Fields +//---------------------------------------------------------------------------------------------------------------------- + private static final long serialVersionUID = 1719328905017860541L; + + private final long timeout; + +//---------------------------------------------------------------------------------------------------------------------- +// Static Methods +//---------------------------------------------------------------------------------------------------------------------- + + public static Buffer decorate( Buffer buffer, long timeout ) { + return new TimeoutBuffer( buffer, timeout ); + } + +//---------------------------------------------------------------------------------------------------------------------- +// Constructors +//---------------------------------------------------------------------------------------------------------------------- + + public TimeoutBuffer( Buffer buffer, long timeout ) { + super( buffer ); + this.timeout = timeout; + } + + public long getTimeout() { + return timeout; + } +//---------------------------------------------------------------------------------------------------------------------- +// Buffer Implementation +//---------------------------------------------------------------------------------------------------------------------- + + public Object get() { + return get( timeout ); + } + + public Object remove() { + return remove( timeout ); + } + + public boolean equals( Object o ) { + if( this == o ) { + return true; + } + if( o == null || getClass() != o.getClass() ) { + return false; + } + if( !super.equals( o ) ) { + return false; + } + final TimeoutBuffer that = ( TimeoutBuffer ) o; + if( timeout != that.timeout ) { + return false; + } + return true; + } + + public int hashCode() { + int result = super.hashCode(); + result = 29 * result + ( int ) ( timeout ^ ( timeout >>> 32 ) ); + return result; + } +} + Propchange: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/TimeoutBuffer.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/TimeoutBuffer.java ------------------------------------------------------------------------------ svn:keywords = Id Modified: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestAll.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestAll.java?rev=332643&r1=332642&r2=332643&view=diff ============================================================================== --- jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestAll.java (original) +++ jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestAll.java Fri Nov 11 12:39:13 2005 @@ -52,7 +52,7 @@ suite.addTest(TestSynchronizedBuffer.suite()); suite.addTest(TestTransformedBuffer.suite()); suite.addTest(TestUnmodifiableBuffer.suite()); - + suite.addTest(TestTimeoutBuffer.suite()); return suite; } Added: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestTimeoutBuffer.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestTimeoutBuffer.java?rev=332643&view=auto ============================================================================== --- jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestTimeoutBuffer.java (added) +++ jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestTimeoutBuffer.java Fri Nov 11 12:39:13 2005 @@ -0,0 +1,242 @@ +/* + * Copyright 2001-2005 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.collections.buffer; + +import junit.framework.Test; +import junit.framework.TestSuite; +import org.apache.commons.collections.AbstractTestObject; +import org.apache.commons.collections.ArrayStack; +import org.apache.commons.collections.Buffer; +import org.apache.commons.collections.BufferUnderflowException; +import org.apache.commons.collections.BufferUtils; + +/** + * @author James Carman + * @version 1.0 + */ +public class TestTimeoutBuffer extends AbstractTestObject { +//---------------------------------------------------------------------------------------------------------------------- +// Fields +//---------------------------------------------------------------------------------------------------------------------- + + private static final int FULL_SIZE = 100; + + private static final int TIMEOUT = 100; + +//---------------------------------------------------------------------------------------------------------------------- +// Static Methods +//---------------------------------------------------------------------------------------------------------------------- + + public static Test suite() { + return new TestSuite( TestTimeoutBuffer.class ); + } + +//---------------------------------------------------------------------------------------------------------------------- +// Constructors +//---------------------------------------------------------------------------------------------------------------------- + + public TestTimeoutBuffer( String testName ) { + super( testName ); + } + +//---------------------------------------------------------------------------------------------------------------------- +// Other Methods +//---------------------------------------------------------------------------------------------------------------------- + + public String getCompatibilityVersion() { + return "3.2"; + } + + public boolean isEqualsCheckable() { + return false; + } + + public Object makeObject() { + return BufferUtils.timeoutBuffer( new ArrayStack(), TIMEOUT ); + } + + public void testEmptySerialization() { + try { + final TimeoutBuffer b = ( TimeoutBuffer ) readExternalFormFromDisk( + getCanonicalEmptyCollectionName( makeObject() ) ); + assertTrue( b.isEmpty() ); + } + catch( Exception e ) { + fail( "Could not read object from disk." ); + } + } + + public void testFullSerialization() { + try { + final TimeoutBuffer b = ( TimeoutBuffer ) readExternalFormFromDisk( + getCanonicalFullCollectionName( makeObject() ) ); + assertEquals( FULL_SIZE, b.size() ); + } + catch( Exception e ) { + fail( "Could not read object from disk." ); + } + } + + public void testSuccessfulWaitOnGet() { + Buffer b = ( Buffer ) makeObject(); + executeAsynchronously( new Getter( b ) ); + executeAsynchronously( new Adder( b, "Hello" ) ); + } + + private static void executeAsynchronously( Runnable r ) { + new Thread( r ).start(); + } + + public void testSuccessfulWaitOnRemove() { + Buffer b = ( Buffer ) makeObject(); + executeAsynchronously( new Remover( b ) ); + executeAsynchronously( new Adder( b, "Hello" ) ); + } + + public void testTimeoutOnGet() { + final Buffer buffer = makeBuffer(); + try { + Getter remover = new Getter( buffer ); + executeAsynchronously( remover ); + executeAsynchronously( new Adder( buffer, "Howdy" ), TIMEOUT * 2 ); + assertFalse( remover.isSuccesful() ); + } + catch( BufferUnderflowException e ) { + } + } + + private TimeoutBuffer makeBuffer() { + return ( TimeoutBuffer ) makeObject(); + } + + private static void executeAsynchronously( Runnable r, long delay ) { + new Thread( new DelayedRunnable( r, delay ) ).start(); + } + + public void testTimeoutOnRemove() { + final Buffer buffer = makeBuffer(); + try { + Remover remover = new Remover( buffer ); + executeAsynchronously( remover ); + executeAsynchronously( new Adder( buffer, "Howdy" ), TIMEOUT * 2 ); + assertFalse( remover.isSuccesful() ); + } + catch( BufferUnderflowException e ) { + } + } + +//---------------------------------------------------------------------------------------------------------------------- +// Inner Classes +//---------------------------------------------------------------------------------------------------------------------- + + private static class DelayedRunnable implements Runnable { + private final Runnable r; + + private final long delay; + public DelayedRunnable( Runnable r, long delay ) { + this.r = r; + this.delay = delay; + } + + public void run() { + try { + Thread.sleep( delay ); + } + catch( InterruptedException e ) { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + r.run(); + } + } + + private static class Adder implements Runnable { + private final Buffer b; + + private final Object o; + public Adder( Buffer b, Object o ) { + this.b = b; + this.o = o; + } + + public void run() { + b.add( o ); + } + } + + private static class Remover extends BufferReader { + public Remover( Buffer b ) { + super( b ); + } + + protected void performOperation() { + b.remove(); + } + } + + private static abstract class BufferReader implements Runnable { + + protected final Buffer b; + private Boolean succesful; + + protected BufferReader( Buffer b ) { + this.b = b; + } + + protected abstract void performOperation(); + + public final synchronized void run() { + try { + performOperation(); + succesful = Boolean.TRUE; + } + catch( BufferUnderflowException e ) { + succesful = Boolean.FALSE; + } + notifyAll(); + } + + public synchronized boolean isSuccesful() { + while( succesful == null ) { + try { + wait(); + } + catch( InterruptedException e ) { + } + } + return succesful.booleanValue(); + } + } + + private static class Getter extends BufferReader { + public Getter( Buffer b ) { + super( b ); + } + + protected void performOperation() { + b.get(); + } + } + +//---------------------------------------------------------------------------------------------------------------------- +// main() method +//---------------------------------------------------------------------------------------------------------------------- + + public static void main( String args[] ) { + String[] testCaseName = {TestTimeoutBuffer.class.getName()}; + junit.textui.TestRunner.main( testCaseName ); + } +} + Propchange: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestTimeoutBuffer.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestTimeoutBuffer.java ------------------------------------------------------------------------------ svn:keywords = Id --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]