You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by jc...@apache.org on 2005/11/23 14:16:51 UTC
svn commit: r348429 - in /jakarta/commons/proper/collections/trunk: ./
data/test/ src/java/org/apache/commons/collections/
src/java/org/apache/commons/collections/buffer/
src/test/org/apache/commons/collections/buffer/
Author: jcarman
Date: Wed Nov 23 05:16:43 2005
New Revision: 348429
URL: http://svn.apache.org/viewcvs?rev=348429&view=rev
Log:
37473: Implement a BoundedBuffer class
Added:
jakarta/commons/proper/collections/trunk/data/test/BoundedBuffer.emptyCollection.version3.2.obj (with props)
jakarta/commons/proper/collections/trunk/data/test/BoundedBuffer.fullCollection.version3.2.obj (with props)
jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/BoundedBuffer.java (with props)
jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestBoundedBuffer.java (with props)
Modified:
jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html
jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/BufferUtils.java
Modified: jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html?rev=348429&r1=348428&r2=348429&view=diff
==============================================================================
--- jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html (original)
+++ jakarta/commons/proper/collections/trunk/RELEASE-NOTES.html Wed Nov 23 05:16:43 2005
@@ -58,6 +58,7 @@
<li>DefaultedMap - Returns a default value when the key is not found, without adding the default value to the map itself [30911]</li>
<li>GrowthList - Decorator that causes set and indexed add to expand the list rather than throw IndexOutOfBoundsException [34171]</li>
<li>LoopingListIterator - When the end of the list is reached the iteration continues from the start [30166]</li>
+<li>BoundedBuffer - A new wrapper class which can make any buffer bounded [37473]</li>
</ul>
<center><h3>ENHANCEMENTS</h3></center>
Added: jakarta/commons/proper/collections/trunk/data/test/BoundedBuffer.emptyCollection.version3.2.obj
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/data/test/BoundedBuffer.emptyCollection.version3.2.obj?rev=348429&view=auto
==============================================================================
Binary file - no diff available.
Propchange: jakarta/commons/proper/collections/trunk/data/test/BoundedBuffer.emptyCollection.version3.2.obj
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: jakarta/commons/proper/collections/trunk/data/test/BoundedBuffer.fullCollection.version3.2.obj
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/data/test/BoundedBuffer.fullCollection.version3.2.obj?rev=348429&view=auto
==============================================================================
Binary file - no diff available.
Propchange: jakarta/commons/proper/collections/trunk/data/test/BoundedBuffer.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=348429&r1=348428&r2=348429&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 Wed Nov 23 05:16:43 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.BoundedBuffer;
/**
* Provides utility methods and decorators for {@link Buffer} instances.
@@ -102,6 +103,33 @@
return BlockingBuffer.decorate(buffer, timeout);
}
+ /**
+ * Returns a synchronized buffer backed by the given buffer that will block on {@link Buffer#add(Object)} and
+ * {@link Buffer#addAll(java.util.Collection)} until enough object(s) are removed from the buffer to allow
+ * the object(s) to be added and still maintain the maximum size.
+ * @param buffer the buffer to make bounded
+ * @param maximumSize the maximum size
+ * @return a bounded buffer backed by the given buffer
+ * @throws IllegalArgumentException if the given buffer is null
+ */
+ public static Buffer boundedBuffer( Buffer buffer, int maximumSize ) {
+ return BoundedBuffer.decorate( buffer, maximumSize );
+ }
+
+ /**
+ * Returns a synchronized buffer backed by the given buffer that will block on {@link Buffer#add(Object)} and
+ * {@link Buffer#addAll(java.util.Collection)} until enough object(s) are removed from the buffer to allow
+ * the object(s) to be added and still maintain the maximum size or the timeout expires.
+ * @param buffer the buffer to make bounded
+ * @param maximumSize the maximum size
+ * @param timeout the maximum time to wait
+ * @return a bounded buffer backed by the given buffer
+ * @throws IllegalArgumentException if the given buffer is null
+ */
+ public static Buffer boundedBuffer( Buffer buffer, int maximumSize, long timeout ) {
+ return BoundedBuffer.decorate( buffer, maximumSize, timeout );
+ }
+
/**
* Returns an unmodifiable buffer backed by the given buffer.
*
Added: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/BoundedBuffer.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/BoundedBuffer.java?rev=348429&view=auto
==============================================================================
--- jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/BoundedBuffer.java (added)
+++ jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/BoundedBuffer.java Wed Nov 23 05:16:43 2005
@@ -0,0 +1,161 @@
+/*
+ * 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;
+import org.apache.commons.collections.BufferOverflowException;
+import org.apache.commons.collections.BufferUnderflowException;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * A wrapper class for buffers which makes them bounded.
+ * @author James Carman
+ * @since 3.2
+ */
+public class BoundedBuffer extends SynchronizedBuffer {
+
+ private static final long serialVersionUID = 1536432911093974264L;
+
+ private final int maximumSize;
+ private final long timeout;
+
+ /**
+ * Factory method to create a bounded buffer.
+ * @param buffer the buffer to decorate, must not be null
+ * @param maximumSize the maximum size
+ * @return a new bounded buffer
+ * @throws IllegalArgumentException if the buffer is null
+ */
+ public static Buffer decorate( Buffer buffer, int maximumSize ) {
+ return new BoundedBuffer( buffer, maximumSize );
+ }
+
+ /**
+ * Factory method to create a bounded buffer that blocks for a maximum
+ * amount of time.
+ * @param buffer the buffer to decorate, must not be null
+ * @param maximumSize the maximum size
+ * @param timeout the maximum amount of time to wait.
+ * @return a new bounded buffer
+ * @throws IllegalArgumentException if the buffer is null
+ */
+ public static Buffer decorate( Buffer buffer, int maximumSize, long timeout ) {
+ return new BoundedBuffer( buffer, maximumSize, timeout );
+ }
+
+ /**
+ * Constructor that wraps (not copies) another buffer, making it bounded.
+ * @param buffer the buffer to wrap, must not be null
+ * @param maximumSize the maximum size of the buffer
+ * @throws IllegalArgumentException if the buffer is null
+ */
+ protected BoundedBuffer( Buffer buffer, int maximumSize ) {
+ this( buffer, maximumSize, -1 );
+ }
+
+ /**
+ * Constructor that wraps (not copies) another buffer, making it bounded waiting only up to
+ * a maximum amount of time.
+ * @param buffer the buffer to wrap, must not be null
+ * @param maximumSize the maximum size of the buffer
+ * @param timeout the maximum amount of time to wait
+ * @throws IllegalArgumentException if the buffer is null
+ */
+ protected BoundedBuffer( Buffer buffer, int maximumSize, long timeout ) {
+ super( buffer );
+ this.maximumSize = maximumSize;
+ this.timeout = timeout;
+ }
+
+ public Object remove() {
+ synchronized( lock ) {
+ Object returnValue = getBuffer().remove();
+ lock.notifyAll();
+ return returnValue;
+ }
+ }
+
+ public boolean add( Object o ) {
+ synchronized( lock ) {
+ timeoutWait( 1 );
+ return getBuffer().add( o );
+ }
+ }
+
+ public boolean addAll( final Collection c ) {
+ synchronized( lock ) {
+ timeoutWait( c.size() );
+ return getBuffer().addAll( c );
+ }
+ }
+
+ public Iterator iterator() {
+ return new NotifyingIterator( collection.iterator() );
+ }
+
+ private void timeoutWait( final int nAdditions ) {
+ synchronized( lock ) {
+ if( timeout < 0 && getBuffer().size() + nAdditions > maximumSize ) {
+ throw new BufferOverflowException( "Buffer size cannot exceed " + maximumSize + "." );
+ }
+ final long expiration = System.currentTimeMillis() + timeout;
+ long timeLeft = expiration - System.currentTimeMillis();
+ while( timeLeft > 0 && getBuffer().size() + nAdditions > maximumSize ) {
+ try {
+ lock.wait( timeLeft );
+ timeLeft = expiration - System.currentTimeMillis();
+ }
+ catch( InterruptedException e ) {
+ PrintWriter out = new PrintWriter( new StringWriter() );
+ e.printStackTrace( out );
+ throw new BufferUnderflowException( "Caused by InterruptedException: " + out.toString() );
+ }
+ }
+ if( getBuffer().size() + nAdditions > maximumSize ) {
+ throw new BufferOverflowException( "Timeout expired." );
+ }
+ }
+ }
+
+ private class NotifyingIterator implements Iterator {
+
+ private final Iterator i;
+
+ public NotifyingIterator( Iterator i ) {
+ this.i = i;
+ }
+
+ public void remove() {
+ synchronized( lock ) {
+ i.remove();
+ lock.notifyAll();
+ }
+ }
+
+ public boolean hasNext() {
+ return i.hasNext();
+ }
+
+ public Object next() {
+ return i.next();
+ }
+ }
+}
+
Propchange: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/BoundedBuffer.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jakarta/commons/proper/collections/trunk/src/java/org/apache/commons/collections/buffer/BoundedBuffer.java
------------------------------------------------------------------------------
svn:keywords = Id
Added: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestBoundedBuffer.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestBoundedBuffer.java?rev=348429&view=auto
==============================================================================
--- jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestBoundedBuffer.java (added)
+++ jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestBoundedBuffer.java Wed Nov 23 05:16:43 2005
@@ -0,0 +1,181 @@
+/*
+ * 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.AbstractTestObject;
+import org.apache.commons.collections.Buffer;
+import org.apache.commons.collections.BufferOverflowException;
+
+import java.util.Iterator;
+import java.util.Collections;
+import java.util.Arrays;
+
+public class TestBoundedBuffer extends AbstractTestObject {
+
+ public TestBoundedBuffer( String testName ) {
+ super( testName );
+ }
+
+ public String getCompatibilityVersion() {
+ return "3.2";
+ }
+
+ public boolean isEqualsCheckable() {
+ return false;
+ }
+
+ public Object makeObject() {
+ return BoundedBuffer.decorate( new UnboundedFifoBuffer(), 1 );
+ }
+
+ public void testAddToFullBufferNoTimeout() {
+ final Buffer bounded = BoundedBuffer.decorate( new UnboundedFifoBuffer(), 1 );
+ bounded.add( "Hello" );
+ try {
+ bounded.add( "World" );
+ fail();
+ }
+ catch( BufferOverflowException e ) {
+ }
+ }
+
+ public void testAddAllToFullBufferNoTimeout() {
+ final Buffer bounded = BoundedBuffer.decorate( new UnboundedFifoBuffer(), 1 );
+ bounded.add( "Hello" );
+ try {
+ bounded.addAll( Collections.singleton( "World" ) );
+ fail();
+ }
+ catch( BufferOverflowException e ) {
+ }
+ }
+
+ public void testAddToFullBufferRemoveViaIterator() {
+ final Buffer bounded = BoundedBuffer.decorate( new UnboundedFifoBuffer(), 1, 500 );
+ bounded.add( "Hello" );
+ new DelayedIteratorRemove( bounded, 200 ).start();
+ bounded.add( "World" );
+ assertEquals( 1, bounded.size() );
+ assertEquals( "World", bounded.get() );
+
+ }
+
+ public void testAddAllToFullBufferRemoveViaIterator() {
+ final Buffer bounded = BoundedBuffer.decorate( new UnboundedFifoBuffer(), 2, 500 );
+ bounded.add( "Hello" );
+ bounded.add( "World" );
+ new DelayedIteratorRemove( bounded, 200, 2 ).start();
+ bounded.addAll( Arrays.asList( new String[] { "Foo", "Bar" } ) );
+ assertEquals( 2, bounded.size() );
+ assertEquals( "Foo", bounded.remove() );
+ assertEquals( "Bar", bounded.remove() );
+ }
+
+ public void testAddToFullBufferWithTimeout() {
+ final Buffer bounded = BoundedBuffer.decorate( new UnboundedFifoBuffer(), 1, 500 );
+ bounded.add( "Hello" );
+ new DelayedRemove( bounded, 200 ).start();
+ bounded.add( "World" );
+ assertEquals( 1, bounded.size() );
+ assertEquals( "World", bounded.get() );
+ try {
+ bounded.add( "!" );
+ fail();
+ }
+ catch( BufferOverflowException e ) {
+ }
+ }
+
+ public void testAddAllToFullBufferWithTimeout() {
+ final Buffer bounded = BoundedBuffer.decorate( new UnboundedFifoBuffer(), 2, 500 );
+ bounded.add( "Hello" );
+ bounded.add( "World" );
+ new DelayedRemove( bounded, 200, 2 ).start();
+
+ bounded.addAll( Arrays.asList( new String[] { "Foo", "Bar" } ) );
+ assertEquals( 2, bounded.size() );
+ assertEquals( "Foo", bounded.get() );
+ try {
+ bounded.add( "!" );
+ fail();
+ }
+ catch( BufferOverflowException e ) {
+ }
+ }
+
+ private class DelayedIteratorRemove extends Thread {
+
+ private final Buffer buffer;
+
+ private final long delay;
+
+ private final int nToRemove;
+
+ public DelayedIteratorRemove( Buffer buffer, long delay, int nToRemove ) {
+ this.buffer = buffer;
+ this.delay = delay;
+ this.nToRemove = nToRemove;
+ }
+
+ public DelayedIteratorRemove( Buffer buffer, long delay ) {
+ this( buffer, delay, 1 );
+ }
+
+ public void run() {
+ try {
+ Thread.sleep( delay );
+ Iterator iter = buffer.iterator();
+ for( int i = 0; i < nToRemove; ++i ) {
+ iter.next();
+ iter.remove();
+ }
+
+ }
+ catch( InterruptedException e ) {
+ }
+ }
+ }
+
+ private class DelayedRemove extends Thread {
+
+ private final Buffer buffer;
+
+ private final long delay;
+
+ private final int nToRemove;
+
+ public DelayedRemove( Buffer buffer, long delay, int nToRemove ) {
+ this.buffer = buffer;
+ this.delay = delay;
+ this.nToRemove = nToRemove;
+ }
+
+ public DelayedRemove( Buffer buffer, long delay ) {
+ this( buffer, delay, 1 );
+ }
+
+ public void run() {
+ try {
+ Thread.sleep( delay );
+ for( int i = 0; i < nToRemove; ++i ) {
+ buffer.remove();
+ }
+ }
+ catch( InterruptedException e ) {
+ }
+ }
+ }
+}
\ No newline at end of file
Propchange: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestBoundedBuffer.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jakarta/commons/proper/collections/trunk/src/test/org/apache/commons/collections/buffer/TestBoundedBuffer.java
------------------------------------------------------------------------------
svn:keywords = Id
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org