You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2006/03/11 07:08:24 UTC

svn commit: r385023 - in /directory/trunks/mina/core/src/main/java/org/apache/mina/common: ByteBuffer.java ByteBufferAllocator.java PooledByteBufferAllocator.java SimpleByteBufferAllocator.java

Author: trustin
Date: Fri Mar 10 22:08:21 2006
New Revision: 385023

URL: http://svn.apache.org/viewcvs?rev=385023&view=rev
Log:
Related issue: DIRMINA-176 (ByteBuffer pool manager which prevents endlessly increasing pool size.)
* Separated buffer pool from ByteBuffer to PooledByteBufferAllocator
* Added a new interface, ByteBufferAllocator
* Added SimpleByteBufferAllocator

Added:
    directory/trunks/mina/core/src/main/java/org/apache/mina/common/ByteBufferAllocator.java   (with props)
    directory/trunks/mina/core/src/main/java/org/apache/mina/common/PooledByteBufferAllocator.java   (with props)
    directory/trunks/mina/core/src/main/java/org/apache/mina/common/SimpleByteBufferAllocator.java   (with props)
Modified:
    directory/trunks/mina/core/src/main/java/org/apache/mina/common/ByteBuffer.java

Modified: directory/trunks/mina/core/src/main/java/org/apache/mina/common/ByteBuffer.java
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/core/src/main/java/org/apache/mina/common/ByteBuffer.java?rev=385023&r1=385022&r2=385023&view=diff
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/common/ByteBuffer.java (original)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/common/ByteBuffer.java Fri Mar 10 22:08:21 2006
@@ -40,10 +40,9 @@
 
 import org.apache.mina.common.support.ByteBufferHexDumper;
 import org.apache.mina.filter.codec.ProtocolEncoderOutput;
-import org.apache.mina.util.Stack;
 
 /**
- * A pooled byte buffer used by MINA applications.
+ * A byte buffer used by MINA applications.
  * <p>
  * This is a replacement for {@link java.nio.ByteBuffer}. Please refer to
  * {@link java.nio.ByteBuffer} and {@link java.nio.Buffer} documentation for
@@ -121,34 +120,47 @@
  * increase by two times, and its limit will increase to the last position
  * the string is written.
  * 
+ * <h2>Changing Buffer Allocation and Management Policy</h2>
+ * <p>
+ * MINA provides a {@link ByteBufferAllocator} interface to let you override
+ * the default buffer management behavior.  There are two allocators provided
+ * out-of-the-box:
+ * <ul>
+ *   <li>{@link PooledByteBufferAllocator} (Default)</li>
+ *   <li>{@link SimpleByteBufferAllocator}</li>
+ * </ul>
+ * You can change the allocator by calling {@link #setAllocator(ByteBufferAllocator)}.
+ * </p>
+ * 
  * @author The Apache Directory Project (dev@directory.apache.org)
  * @version $Rev$, $Date$
+ * 
+ * @see ByteBufferAllocator
  */
 public abstract class ByteBuffer implements Comparable
 {
-    private static final int MINIMUM_CAPACITY = 1;
-
-    private static final Stack containerStack = new Stack();
+    private static ByteBufferAllocator allocator = new PooledByteBufferAllocator();
+    
+    /**
+     * Returns the current allocator which manages the allocated buffers.
+     */
+    public static ByteBufferAllocator getAllocator()
+    {
+        return allocator;
+    }
 
-    private static final Stack[] heapBufferStacks = new Stack[] {
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(), };
-    
-    private static final Stack[] directBufferStacks = new Stack[] {
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(),
-            new Stack(), new Stack(), new Stack(), new Stack(), };
+    /**
+     * Changes the current allocator with the specified one to manage
+     * the allocated buffers from now.
+     */
+    public static void setAllocator( ByteBufferAllocator newAllocator )
+    {
+        if( newAllocator == null )
+        {
+            throw new NullPointerException( "allocator" );
+        }
+        allocator = newAllocator;
+    }
     
     /**
      * Returns the direct or heap buffer which is capable of the specified
@@ -181,68 +193,15 @@
      */
     public static ByteBuffer allocate( int capacity, boolean direct )
     {
-        java.nio.ByteBuffer nioBuffer = allocate0( capacity, direct );
-        DefaultByteBuffer buf = allocateContainer();
-        buf.init( nioBuffer, true );
-        return buf;
+        return allocator.allocate( capacity, direct );
     }
 
-    private static DefaultByteBuffer allocateContainer()
-    {
-        DefaultByteBuffer buf;
-        synchronized( containerStack )
-        {
-            buf = ( DefaultByteBuffer ) containerStack.pop();
-        }
-        
-        if( buf == null )
-        {
-            buf = new DefaultByteBuffer();
-        }
-        return buf;
-    }
-    
-    private static java.nio.ByteBuffer allocate0( int capacity, boolean direct )
-    {
-        Stack[] bufferStacks = direct? directBufferStacks : heapBufferStacks;
-        int idx = getBufferStackIndex( bufferStacks, capacity );
-        Stack stack = bufferStacks[ idx ];
-
-        java.nio.ByteBuffer buf;
-        synchronized( stack )
-        {
-            buf = ( java.nio.ByteBuffer ) stack.pop();
-        }
-
-        if( buf == null )
-        {
-            buf = direct ? java.nio.ByteBuffer.allocateDirect( MINIMUM_CAPACITY << idx ) :
-                           java.nio.ByteBuffer.allocate( MINIMUM_CAPACITY << idx );
-        }
-        
-        return buf;
-    }
-    
-    private static void release0( java.nio.ByteBuffer buf )
-    {
-        Stack[] bufferStacks = buf.isDirect()? directBufferStacks : heapBufferStacks;
-        Stack stack = bufferStacks[ getBufferStackIndex( bufferStacks, buf.capacity() ) ];
-        synchronized( stack )
-        {
-            // push back
-            stack.push( buf );
-        }
-    }
-    
     /**
      * Wraps the specified NIO {@link java.nio.ByteBuffer} into MINA buffer.
      */
     public static ByteBuffer wrap( java.nio.ByteBuffer nioBuffer )
     {
-        DefaultByteBuffer buf = allocateContainer();
-        buf.init( nioBuffer, false );
-        buf.setPooled( false );
-        return buf;
+        return allocator.wrap( nioBuffer );
     }
     
     /**
@@ -264,24 +223,6 @@
         return wrap( java.nio.ByteBuffer.wrap( byteArray, offset, length ) );
     }
     
-    private static int getBufferStackIndex( Stack[] bufferStacks, int size )
-    {
-        int targetSize = MINIMUM_CAPACITY;
-        int stackIdx = 0;
-        while( size > targetSize )
-        {
-            targetSize <<= 1;
-            stackIdx ++ ;
-            if( stackIdx >= bufferStacks.length )
-            {
-                throw new IllegalArgumentException(
-                        "Buffer size is too big: " + size );
-            }
-        }
-
-        return stackIdx;
-    }
-
     protected ByteBuffer()
     {
     }
@@ -1844,475 +1785,12 @@
         return this;
     }
     
-
     private static void checkFieldSize( int fieldSize )
     {
         if( fieldSize < 0 )
         {
             throw new IllegalArgumentException(
                     "fieldSize cannot be negative: " + fieldSize );
-        }
-    }
-    
-    private static class DefaultByteBuffer extends ByteBuffer
-    {
-        private java.nio.ByteBuffer buf;
-        private int refCount = 1;
-        private boolean autoExpand;
-        private boolean pooled;
-
-        protected DefaultByteBuffer()
-        {
-        }
-
-        private synchronized void init( java.nio.ByteBuffer buf, boolean clear )
-        {
-            this.buf = buf;
-            if( clear )
-            {
-                buf.clear();
-            }
-            buf.order( ByteOrder.BIG_ENDIAN );
-            autoExpand = false;
-            pooled = true;
-            refCount = 1;
-        }
-        
-        public synchronized void acquire()
-        {
-            if( refCount <= 0 )
-            {
-                throw new IllegalStateException( "Already released buffer." );
-            }
-
-            refCount ++;
-        }
-
-        public void release()
-        {
-            synchronized( this )
-            {
-                if( refCount <= 0 )
-                {
-                    refCount = 0;
-                    throw new IllegalStateException(
-                            "Already released buffer.  You released the buffer too many times." );
-                }
-
-                refCount --;
-                if( refCount > 0)
-                {
-                    return;
-                }
-            }
-
-            if( pooled )
-            {
-                release0( buf );
-            }
-
-            synchronized( containerStack )
-            {
-                containerStack.push( this );
-            }
-        }
-
-        public java.nio.ByteBuffer buf()
-        {
-            return buf;
-        }
-        
-        public boolean isDirect()
-        {
-            return buf.isDirect();
-        }
-        
-        public boolean isReadOnly()
-        {
-            return buf.isReadOnly();
-        }
-        
-        public boolean isAutoExpand()
-        {
-            return autoExpand;
-        }
-        
-        public ByteBuffer setAutoExpand( boolean autoExpand )
-        {
-            this.autoExpand = autoExpand;
-            return this;
-        }
-        
-        public boolean isPooled()
-        {
-            return pooled;
-        }
-        
-        public void setPooled( boolean pooled )
-        {
-            this.pooled = pooled;
-        }
-
-        public int capacity()
-        {
-            return buf.capacity();
-        }
-        
-        public int position()
-        {
-            return buf.position();
-        }
-
-        public ByteBuffer position( int newPosition )
-        {
-            autoExpand( newPosition, 0 );
-            buf.position( newPosition );
-            return this;
-        }
-
-        public int limit()
-        {
-            return buf.limit();
-        }
-
-        public ByteBuffer limit( int newLimit )
-        {
-            autoExpand( newLimit, 0 );
-            buf.limit( newLimit );
-            return this;
-        }
-
-        public ByteBuffer mark()
-        {
-            buf.mark();
-            return this;
-        }
-
-        public ByteBuffer reset()
-        {
-            buf.reset();
-            return this;
-        }
-
-        public ByteBuffer clear()
-        {
-            buf.clear();
-            return this;
-        }
-
-        public ByteBuffer flip()
-        {
-            buf.flip();
-            return this;
-        }
-
-        public ByteBuffer rewind()
-        {
-            buf.rewind();
-            return this;
-        }
-
-        public int remaining()
-        {
-            return buf.remaining();
-        }
-
-        public byte get()
-        {
-            return buf.get();
-        }
-
-        public ByteBuffer put( byte b )
-        {
-            autoExpand( 1 );
-            buf.put( b );
-            return this;
-        }
-
-        public byte get( int index )
-        {
-            return buf.get( index );
-        }
-
-        public ByteBuffer put( int index, byte b )
-        {
-            autoExpand( index, 1 );
-            buf.put( index, b );
-            return this;
-        }
-
-        public ByteBuffer get( byte[] dst, int offset, int length )
-        {
-            buf.get( dst, offset, length );
-            return this;
-        }
-
-        public ByteBuffer put( java.nio.ByteBuffer src )
-        {
-            autoExpand( src.remaining() );
-            buf.put( src );
-            return this;
-        }
-
-        public ByteBuffer put( byte[] src, int offset, int length )
-        {
-            autoExpand( length );
-            buf.put( src, offset, length );
-            return this;
-        }
-
-        public ByteBuffer compact()
-        {
-            buf.compact();
-            return this;
-        }
-
-        public int compareTo( ByteBuffer that )
-        {
-            return this.buf.compareTo( that.buf() );
-        }
-
-        public ByteOrder order()
-        {
-            return buf.order();
-        }
-
-        public ByteBuffer order( ByteOrder bo )
-        {
-            buf.order( bo );
-            return this;
-        }
-
-        public char getChar()
-        {
-            return buf.getChar();
-        }
-
-        public ByteBuffer putChar( char value )
-        {
-            autoExpand( 2 );
-            buf.putChar( value );
-            return this;
-        }
-
-        public char getChar( int index )
-        {
-            return buf.getChar( index );
-        }
-
-        public ByteBuffer putChar( int index, char value )
-        {
-            autoExpand( index, 2 );
-            buf.putChar( index, value );
-            return this;
-        }
-
-        public CharBuffer asCharBuffer()
-        {
-            return buf.asCharBuffer();
-        }
-
-        public short getShort()
-        {
-            return buf.getShort();
-        }
-
-        public ByteBuffer putShort( short value )
-        {
-            autoExpand( 2 );
-            buf.putShort( value );
-            return this;
-        }
-
-        public short getShort( int index )
-        {
-            return buf.getShort( index );
-        }
-
-        public ByteBuffer putShort( int index, short value )
-        {
-            autoExpand( index, 2 );
-            buf.putShort( index, value );
-            return this;
-        }
-
-        public ShortBuffer asShortBuffer()
-        {
-            return buf.asShortBuffer();
-        }
-
-        public int getInt()
-        {
-            return buf.getInt();
-        }
-
-        public ByteBuffer putInt( int value )
-        {
-            autoExpand( 4 );
-            buf.putInt( value );
-            return this;
-        }
-
-        public int getInt( int index )
-        {
-            return buf.getInt( index );
-        }
-
-        public ByteBuffer putInt( int index, int value )
-        {
-            autoExpand( index, 4 );
-            buf.putInt( index, value );
-            return this;
-        }
-
-        public IntBuffer asIntBuffer()
-        {
-            return buf.asIntBuffer();
-        }
-
-        public long getLong()
-        {
-            return buf.getLong();
-        }
-
-        public ByteBuffer putLong( long value )
-        {
-            autoExpand( 8 );
-            buf.putLong( value );
-            return this;
-        }
-
-        public long getLong( int index )
-        {
-            return buf.getLong( index );
-        }
-
-        public ByteBuffer putLong( int index, long value )
-        {
-            autoExpand( index, 8 );
-            buf.putLong( index, value );
-            return this;
-        }
-
-        public LongBuffer asLongBuffer()
-        {
-            return buf.asLongBuffer();
-        }
-
-        public float getFloat()
-        {
-            return buf.getFloat();
-        }
-
-        public ByteBuffer putFloat( float value )
-        {
-            autoExpand( 4 );
-            buf.putFloat( value );
-            return this;
-        }
-
-        public float getFloat( int index )
-        {
-            return buf.getFloat( index );
-        }
-
-        public ByteBuffer putFloat( int index, float value )
-        {
-            autoExpand( index, 4 );
-            buf.putFloat( index, value );
-            return this;
-        }
-
-        public FloatBuffer asFloatBuffer()
-        {
-            return buf.asFloatBuffer();
-        }
-
-        public double getDouble()
-        {
-            return buf.getDouble();
-        }
-
-        public ByteBuffer putDouble( double value )
-        {
-            autoExpand( 8 );
-            buf.putDouble( value );
-            return this;
-        }
-
-        public double getDouble( int index )
-        {
-            return buf.getDouble( index );
-        }
-
-        public ByteBuffer putDouble( int index, double value )
-        {
-            autoExpand( index, 8 );
-            buf.putDouble( index, value );
-            return this;
-        }
-
-        public DoubleBuffer asDoubleBuffer()
-        {
-            return buf.asDoubleBuffer();
-        }
-
-        public ByteBuffer expand( int expectedRemaining )
-        {
-            if( autoExpand )
-            {
-                int pos = buf.position();
-                int limit = buf.limit();
-                int end = pos + expectedRemaining;
-                if( end > limit ) {
-                    ensureCapacity( end );
-                    buf.limit( end );
-                }
-            }
-            return this;
-        }
-        
-        public ByteBuffer expand( int pos, int expectedRemaining )
-        {
-            if( autoExpand )
-            {
-                int limit = buf.limit();
-                int end = pos + expectedRemaining;
-                if( end > limit ) {
-                    ensureCapacity( end );
-                    buf.limit( end );
-                }
-            }
-            return this;
-        }
-        
-        private void ensureCapacity( int requestedCapacity )
-        {
-            if( requestedCapacity <= buf.capacity() )
-            {
-                return;
-            }
-            
-            int newCapacity = MINIMUM_CAPACITY;
-            while( newCapacity < requestedCapacity )
-            {
-                newCapacity <<= 1;
-            }
-            
-            java.nio.ByteBuffer oldBuf = this.buf;
-            java.nio.ByteBuffer newBuf = allocate0( newCapacity, isDirect() );
-            newBuf.clear();
-            newBuf.order( oldBuf.order() );
-
-            int pos = oldBuf.position();
-            int limit = oldBuf.limit();
-            oldBuf.clear();
-            newBuf.put( oldBuf );
-            newBuf.position( 0 );
-            newBuf.limit( limit );
-            newBuf.position( pos );
-            this.buf = newBuf;
-            release0( oldBuf );
         }
     }
 }

Added: directory/trunks/mina/core/src/main/java/org/apache/mina/common/ByteBufferAllocator.java
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/core/src/main/java/org/apache/mina/common/ByteBufferAllocator.java?rev=385023&view=auto
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/common/ByteBufferAllocator.java (added)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/common/ByteBufferAllocator.java Fri Mar 10 22:08:21 2006
@@ -0,0 +1,43 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 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.mina.common;
+
+/**
+ * Allocates {@link ByteBuffer}s and manages them.  Please implement this
+ * interface if you need more advanced memory management scheme.
+ * 
+ * @author The Apache Directory Project (dev@directory.apache.org)
+ * @version $Rev$, $Date$
+ */
+public interface ByteBufferAllocator
+{
+    /**
+     * Returns the buffer which is capable of the specified size.
+     * 
+     * @param capacity the capacity of the buffer
+     * @param direct <tt>true</tt> to get a direct buffer,
+     *               <tt>false</tt> to get a heap buffer.
+     */
+    public ByteBuffer allocate( int capacity, boolean direct );
+
+    /**
+     * Wraps the specified NIO {@link java.nio.ByteBuffer} into MINA buffer.
+     */
+    public ByteBuffer wrap( java.nio.ByteBuffer nioBuffer );
+}

Propchange: directory/trunks/mina/core/src/main/java/org/apache/mina/common/ByteBufferAllocator.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/trunks/mina/core/src/main/java/org/apache/mina/common/PooledByteBufferAllocator.java
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/core/src/main/java/org/apache/mina/common/PooledByteBufferAllocator.java?rev=385023&view=auto
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/common/PooledByteBufferAllocator.java (added)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/common/PooledByteBufferAllocator.java Fri Mar 10 22:08:21 2006
@@ -0,0 +1,619 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 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.mina.common;
+
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.LongBuffer;
+import java.nio.ShortBuffer;
+
+import org.apache.mina.util.Stack;
+
+/**
+ * A {@link ByteBufferAllocator} which pools allocated buffers.
+ * <p>
+ * All buffers are allocated with the size of power of 2 (e.g. 16, 32, 64, ...)
+ * This means that you cannot simply assume that the actual capacity of the
+ * buffer and the capacity you requested are same.
+ * </p>
+ * <p>
+ * This allocator doesn't deallocate buffers once they are allocated, so the
+ * overall memory usage increase as time goes by and cause some applications
+ * get {@link OutOfMemoryError} under high load. 
+ * </p>
+ * 
+ * @author The Apache Directory Project (dev@directory.apache.org)
+ * @version $Rev$, $Date$
+ */
+public class PooledByteBufferAllocator implements ByteBufferAllocator
+{
+    private final int MINIMUM_CAPACITY = 1;
+
+    private final Stack containerStack = new Stack();
+
+    private final Stack[] heapBufferStacks = new Stack[] {
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(), };
+    
+    private final Stack[] directBufferStacks = new Stack[] {
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(),
+            new Stack(), new Stack(), new Stack(), new Stack(), };
+    
+    public PooledByteBufferAllocator()
+    {
+    }
+    
+    public ByteBuffer allocate( int capacity, boolean direct )
+    {
+        java.nio.ByteBuffer nioBuffer = allocate0( capacity, direct );
+        PooledByteBuffer buf = allocateContainer();
+        buf.init( nioBuffer, true );
+        return buf;
+    }
+
+    private PooledByteBuffer allocateContainer()
+    {
+        PooledByteBuffer buf;
+        synchronized( containerStack )
+        {
+            buf = ( PooledByteBuffer ) containerStack.pop();
+        }
+        
+        if( buf == null )
+        {
+            buf = new PooledByteBuffer();
+        }
+        return buf;
+    }
+    
+    private java.nio.ByteBuffer allocate0( int capacity, boolean direct )
+    {
+        Stack[] bufferStacks = direct? directBufferStacks : heapBufferStacks;
+        int idx = getBufferStackIndex( bufferStacks, capacity );
+        Stack stack = bufferStacks[ idx ];
+
+        java.nio.ByteBuffer buf;
+        synchronized( stack )
+        {
+            buf = ( java.nio.ByteBuffer ) stack.pop();
+        }
+
+        if( buf == null )
+        {
+            buf = direct ? java.nio.ByteBuffer.allocateDirect( MINIMUM_CAPACITY << idx ) :
+                           java.nio.ByteBuffer.allocate( MINIMUM_CAPACITY << idx );
+        }
+        
+        return buf;
+    }
+    
+    private void release0( java.nio.ByteBuffer buf )
+    {
+        Stack[] bufferStacks = buf.isDirect()? directBufferStacks : heapBufferStacks;
+        Stack stack = bufferStacks[ getBufferStackIndex( bufferStacks, buf.capacity() ) ];
+        synchronized( stack )
+        {
+            // push back
+            stack.push( buf );
+        }
+    }
+    
+    public ByteBuffer wrap( java.nio.ByteBuffer nioBuffer )
+    {
+        PooledByteBuffer buf = allocateContainer();
+        buf.init( nioBuffer, false );
+        buf.setPooled( false );
+        return buf;
+    }
+
+    private int getBufferStackIndex( Stack[] bufferStacks, int size )
+    {
+        int targetSize = MINIMUM_CAPACITY;
+        int stackIdx = 0;
+        while( size > targetSize )
+        {
+            targetSize <<= 1;
+            stackIdx ++ ;
+            if( stackIdx >= bufferStacks.length )
+            {
+                throw new IllegalArgumentException(
+                        "Buffer size is too big: " + size );
+            }
+        }
+
+        return stackIdx;
+    }
+
+    private class PooledByteBuffer extends ByteBuffer
+    {
+        private java.nio.ByteBuffer buf;
+        private int refCount = 1;
+        private boolean autoExpand;
+        private boolean pooled;
+
+        protected PooledByteBuffer()
+        {
+        }
+
+        private synchronized void init( java.nio.ByteBuffer buf, boolean clear )
+        {
+            this.buf = buf;
+            if( clear )
+            {
+                buf.clear();
+            }
+            buf.order( ByteOrder.BIG_ENDIAN );
+            autoExpand = false;
+            pooled = true;
+            refCount = 1;
+        }
+        
+        public synchronized void acquire()
+        {
+            if( refCount <= 0 )
+            {
+                throw new IllegalStateException( "Already released buffer." );
+            }
+
+            refCount ++;
+        }
+
+        public void release()
+        {
+            synchronized( this )
+            {
+                if( refCount <= 0 )
+                {
+                    refCount = 0;
+                    throw new IllegalStateException(
+                            "Already released buffer.  You released the buffer too many times." );
+                }
+
+                refCount --;
+                if( refCount > 0)
+                {
+                    return;
+                }
+            }
+
+            if( pooled )
+            {
+                release0( buf );
+            }
+
+            synchronized( containerStack )
+            {
+                containerStack.push( this );
+            }
+        }
+
+        public java.nio.ByteBuffer buf()
+        {
+            return buf;
+        }
+        
+        public boolean isDirect()
+        {
+            return buf.isDirect();
+        }
+        
+        public boolean isReadOnly()
+        {
+            return buf.isReadOnly();
+        }
+        
+        public boolean isAutoExpand()
+        {
+            return autoExpand;
+        }
+        
+        public ByteBuffer setAutoExpand( boolean autoExpand )
+        {
+            this.autoExpand = autoExpand;
+            return this;
+        }
+        
+        public boolean isPooled()
+        {
+            return pooled;
+        }
+        
+        public void setPooled( boolean pooled )
+        {
+            this.pooled = pooled;
+        }
+
+        public int capacity()
+        {
+            return buf.capacity();
+        }
+        
+        public int position()
+        {
+            return buf.position();
+        }
+
+        public ByteBuffer position( int newPosition )
+        {
+            autoExpand( newPosition, 0 );
+            buf.position( newPosition );
+            return this;
+        }
+
+        public int limit()
+        {
+            return buf.limit();
+        }
+
+        public ByteBuffer limit( int newLimit )
+        {
+            autoExpand( newLimit, 0 );
+            buf.limit( newLimit );
+            return this;
+        }
+
+        public ByteBuffer mark()
+        {
+            buf.mark();
+            return this;
+        }
+
+        public ByteBuffer reset()
+        {
+            buf.reset();
+            return this;
+        }
+
+        public ByteBuffer clear()
+        {
+            buf.clear();
+            return this;
+        }
+
+        public ByteBuffer flip()
+        {
+            buf.flip();
+            return this;
+        }
+
+        public ByteBuffer rewind()
+        {
+            buf.rewind();
+            return this;
+        }
+
+        public int remaining()
+        {
+            return buf.remaining();
+        }
+
+        public byte get()
+        {
+            return buf.get();
+        }
+
+        public ByteBuffer put( byte b )
+        {
+            autoExpand( 1 );
+            buf.put( b );
+            return this;
+        }
+
+        public byte get( int index )
+        {
+            return buf.get( index );
+        }
+
+        public ByteBuffer put( int index, byte b )
+        {
+            autoExpand( index, 1 );
+            buf.put( index, b );
+            return this;
+        }
+
+        public ByteBuffer get( byte[] dst, int offset, int length )
+        {
+            buf.get( dst, offset, length );
+            return this;
+        }
+
+        public ByteBuffer put( java.nio.ByteBuffer src )
+        {
+            autoExpand( src.remaining() );
+            buf.put( src );
+            return this;
+        }
+
+        public ByteBuffer put( byte[] src, int offset, int length )
+        {
+            autoExpand( length );
+            buf.put( src, offset, length );
+            return this;
+        }
+
+        public ByteBuffer compact()
+        {
+            buf.compact();
+            return this;
+        }
+
+        public int compareTo( ByteBuffer that )
+        {
+            return this.buf.compareTo( that.buf() );
+        }
+
+        public ByteOrder order()
+        {
+            return buf.order();
+        }
+
+        public ByteBuffer order( ByteOrder bo )
+        {
+            buf.order( bo );
+            return this;
+        }
+
+        public char getChar()
+        {
+            return buf.getChar();
+        }
+
+        public ByteBuffer putChar( char value )
+        {
+            autoExpand( 2 );
+            buf.putChar( value );
+            return this;
+        }
+
+        public char getChar( int index )
+        {
+            return buf.getChar( index );
+        }
+
+        public ByteBuffer putChar( int index, char value )
+        {
+            autoExpand( index, 2 );
+            buf.putChar( index, value );
+            return this;
+        }
+
+        public CharBuffer asCharBuffer()
+        {
+            return buf.asCharBuffer();
+        }
+
+        public short getShort()
+        {
+            return buf.getShort();
+        }
+
+        public ByteBuffer putShort( short value )
+        {
+            autoExpand( 2 );
+            buf.putShort( value );
+            return this;
+        }
+
+        public short getShort( int index )
+        {
+            return buf.getShort( index );
+        }
+
+        public ByteBuffer putShort( int index, short value )
+        {
+            autoExpand( index, 2 );
+            buf.putShort( index, value );
+            return this;
+        }
+
+        public ShortBuffer asShortBuffer()
+        {
+            return buf.asShortBuffer();
+        }
+
+        public int getInt()
+        {
+            return buf.getInt();
+        }
+
+        public ByteBuffer putInt( int value )
+        {
+            autoExpand( 4 );
+            buf.putInt( value );
+            return this;
+        }
+
+        public int getInt( int index )
+        {
+            return buf.getInt( index );
+        }
+
+        public ByteBuffer putInt( int index, int value )
+        {
+            autoExpand( index, 4 );
+            buf.putInt( index, value );
+            return this;
+        }
+
+        public IntBuffer asIntBuffer()
+        {
+            return buf.asIntBuffer();
+        }
+
+        public long getLong()
+        {
+            return buf.getLong();
+        }
+
+        public ByteBuffer putLong( long value )
+        {
+            autoExpand( 8 );
+            buf.putLong( value );
+            return this;
+        }
+
+        public long getLong( int index )
+        {
+            return buf.getLong( index );
+        }
+
+        public ByteBuffer putLong( int index, long value )
+        {
+            autoExpand( index, 8 );
+            buf.putLong( index, value );
+            return this;
+        }
+
+        public LongBuffer asLongBuffer()
+        {
+            return buf.asLongBuffer();
+        }
+
+        public float getFloat()
+        {
+            return buf.getFloat();
+        }
+
+        public ByteBuffer putFloat( float value )
+        {
+            autoExpand( 4 );
+            buf.putFloat( value );
+            return this;
+        }
+
+        public float getFloat( int index )
+        {
+            return buf.getFloat( index );
+        }
+
+        public ByteBuffer putFloat( int index, float value )
+        {
+            autoExpand( index, 4 );
+            buf.putFloat( index, value );
+            return this;
+        }
+
+        public FloatBuffer asFloatBuffer()
+        {
+            return buf.asFloatBuffer();
+        }
+
+        public double getDouble()
+        {
+            return buf.getDouble();
+        }
+
+        public ByteBuffer putDouble( double value )
+        {
+            autoExpand( 8 );
+            buf.putDouble( value );
+            return this;
+        }
+
+        public double getDouble( int index )
+        {
+            return buf.getDouble( index );
+        }
+
+        public ByteBuffer putDouble( int index, double value )
+        {
+            autoExpand( index, 8 );
+            buf.putDouble( index, value );
+            return this;
+        }
+
+        public DoubleBuffer asDoubleBuffer()
+        {
+            return buf.asDoubleBuffer();
+        }
+
+        public ByteBuffer expand( int expectedRemaining )
+        {
+            if( autoExpand )
+            {
+                int pos = buf.position();
+                int limit = buf.limit();
+                int end = pos + expectedRemaining;
+                if( end > limit ) {
+                    ensureCapacity( end );
+                    buf.limit( end );
+                }
+            }
+            return this;
+        }
+        
+        public ByteBuffer expand( int pos, int expectedRemaining )
+        {
+            if( autoExpand )
+            {
+                int limit = buf.limit();
+                int end = pos + expectedRemaining;
+                if( end > limit ) {
+                    ensureCapacity( end );
+                    buf.limit( end );
+                }
+            }
+            return this;
+        }
+        
+        private void ensureCapacity( int requestedCapacity )
+        {
+            if( requestedCapacity <= buf.capacity() )
+            {
+                return;
+            }
+            
+            int newCapacity = MINIMUM_CAPACITY;
+            while( newCapacity < requestedCapacity )
+            {
+                newCapacity <<= 1;
+            }
+            
+            java.nio.ByteBuffer oldBuf = this.buf;
+            java.nio.ByteBuffer newBuf = allocate0( newCapacity, isDirect() );
+            newBuf.clear();
+            newBuf.order( oldBuf.order() );
+
+            int pos = oldBuf.position();
+            int limit = oldBuf.limit();
+            oldBuf.clear();
+            newBuf.put( oldBuf );
+            newBuf.position( 0 );
+            newBuf.limit( limit );
+            newBuf.position( pos );
+            this.buf = newBuf;
+            release0( oldBuf );
+        }
+    }
+}

Propchange: directory/trunks/mina/core/src/main/java/org/apache/mina/common/PooledByteBufferAllocator.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/trunks/mina/core/src/main/java/org/apache/mina/common/SimpleByteBufferAllocator.java
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/core/src/main/java/org/apache/mina/common/SimpleByteBufferAllocator.java?rev=385023&view=auto
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/common/SimpleByteBufferAllocator.java (added)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/common/SimpleByteBufferAllocator.java Fri Mar 10 22:08:21 2006
@@ -0,0 +1,515 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 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.mina.common;
+
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.LongBuffer;
+import java.nio.ShortBuffer;
+
+/**
+ * A simplistic {@link ByteBufferAllocator} which simply allocates a new
+ * buffer every time.
+ * 
+ * @author The Apache Directory Project (dev@directory.apache.org)
+ * @version $Rev$, $Date$
+ */
+public class SimpleByteBufferAllocator implements ByteBufferAllocator
+{
+    private static final int MINIMUM_CAPACITY = 1;
+
+    public SimpleByteBufferAllocator()
+    {
+    }
+    
+    public ByteBuffer allocate( int capacity, boolean direct )
+    {
+        java.nio.ByteBuffer nioBuffer;
+        if( direct )
+        {
+            nioBuffer = java.nio.ByteBuffer.allocateDirect( capacity );            
+        }
+        else
+        {
+            nioBuffer = java.nio.ByteBuffer.allocate( capacity );            
+        }
+        return new SimpleByteBuffer( nioBuffer, true );
+    }
+    
+    public ByteBuffer wrap( java.nio.ByteBuffer nioBuffer )
+    {
+        return new SimpleByteBuffer( nioBuffer, false );
+    }
+
+    private static class SimpleByteBuffer extends ByteBuffer
+    {
+        private java.nio.ByteBuffer buf;
+        private int refCount = 1;
+        private boolean autoExpand;
+
+        protected SimpleByteBuffer( java.nio.ByteBuffer buf, boolean clear )
+        {
+            this.buf = buf;
+            if( clear )
+            {
+                buf.clear();
+            }
+            buf.order( ByteOrder.BIG_ENDIAN );
+            autoExpand = false;
+            refCount = 1;
+        }
+
+        public synchronized void acquire()
+        {
+            if( refCount <= 0 )
+            {
+                throw new IllegalStateException( "Already released buffer." );
+            }
+
+            refCount ++;
+        }
+
+        public void release()
+        {
+            synchronized( this )
+            {
+                if( refCount <= 0 )
+                {
+                    refCount = 0;
+                    throw new IllegalStateException(
+                            "Already released buffer.  You released the buffer too many times." );
+                }
+
+                refCount --;
+                if( refCount > 0)
+                {
+                    return;
+                }
+            }
+        }
+
+        public java.nio.ByteBuffer buf()
+        {
+            return buf;
+        }
+        
+        public boolean isDirect()
+        {
+            return buf.isDirect();
+        }
+        
+        public boolean isReadOnly()
+        {
+            return buf.isReadOnly();
+        }
+        
+        public boolean isAutoExpand()
+        {
+            return autoExpand;
+        }
+        
+        public ByteBuffer setAutoExpand( boolean autoExpand )
+        {
+            this.autoExpand = autoExpand;
+            return this;
+        }
+        
+        public boolean isPooled()
+        {
+            return false;
+        }
+        
+        public void setPooled( boolean pooled )
+        {
+        }
+
+        public int capacity()
+        {
+            return buf.capacity();
+        }
+        
+        public int position()
+        {
+            return buf.position();
+        }
+
+        public ByteBuffer position( int newPosition )
+        {
+            autoExpand( newPosition, 0 );
+            buf.position( newPosition );
+            return this;
+        }
+
+        public int limit()
+        {
+            return buf.limit();
+        }
+
+        public ByteBuffer limit( int newLimit )
+        {
+            autoExpand( newLimit, 0 );
+            buf.limit( newLimit );
+            return this;
+        }
+
+        public ByteBuffer mark()
+        {
+            buf.mark();
+            return this;
+        }
+
+        public ByteBuffer reset()
+        {
+            buf.reset();
+            return this;
+        }
+
+        public ByteBuffer clear()
+        {
+            buf.clear();
+            return this;
+        }
+
+        public ByteBuffer flip()
+        {
+            buf.flip();
+            return this;
+        }
+
+        public ByteBuffer rewind()
+        {
+            buf.rewind();
+            return this;
+        }
+
+        public int remaining()
+        {
+            return buf.remaining();
+        }
+
+        public byte get()
+        {
+            return buf.get();
+        }
+
+        public ByteBuffer put( byte b )
+        {
+            autoExpand( 1 );
+            buf.put( b );
+            return this;
+        }
+
+        public byte get( int index )
+        {
+            return buf.get( index );
+        }
+
+        public ByteBuffer put( int index, byte b )
+        {
+            autoExpand( index, 1 );
+            buf.put( index, b );
+            return this;
+        }
+
+        public ByteBuffer get( byte[] dst, int offset, int length )
+        {
+            buf.get( dst, offset, length );
+            return this;
+        }
+
+        public ByteBuffer put( java.nio.ByteBuffer src )
+        {
+            autoExpand( src.remaining() );
+            buf.put( src );
+            return this;
+        }
+
+        public ByteBuffer put( byte[] src, int offset, int length )
+        {
+            autoExpand( length );
+            buf.put( src, offset, length );
+            return this;
+        }
+
+        public ByteBuffer compact()
+        {
+            buf.compact();
+            return this;
+        }
+
+        public int compareTo( ByteBuffer that )
+        {
+            return this.buf.compareTo( that.buf() );
+        }
+
+        public ByteOrder order()
+        {
+            return buf.order();
+        }
+
+        public ByteBuffer order( ByteOrder bo )
+        {
+            buf.order( bo );
+            return this;
+        }
+
+        public char getChar()
+        {
+            return buf.getChar();
+        }
+
+        public ByteBuffer putChar( char value )
+        {
+            autoExpand( 2 );
+            buf.putChar( value );
+            return this;
+        }
+
+        public char getChar( int index )
+        {
+            return buf.getChar( index );
+        }
+
+        public ByteBuffer putChar( int index, char value )
+        {
+            autoExpand( index, 2 );
+            buf.putChar( index, value );
+            return this;
+        }
+
+        public CharBuffer asCharBuffer()
+        {
+            return buf.asCharBuffer();
+        }
+
+        public short getShort()
+        {
+            return buf.getShort();
+        }
+
+        public ByteBuffer putShort( short value )
+        {
+            autoExpand( 2 );
+            buf.putShort( value );
+            return this;
+        }
+
+        public short getShort( int index )
+        {
+            return buf.getShort( index );
+        }
+
+        public ByteBuffer putShort( int index, short value )
+        {
+            autoExpand( index, 2 );
+            buf.putShort( index, value );
+            return this;
+        }
+
+        public ShortBuffer asShortBuffer()
+        {
+            return buf.asShortBuffer();
+        }
+
+        public int getInt()
+        {
+            return buf.getInt();
+        }
+
+        public ByteBuffer putInt( int value )
+        {
+            autoExpand( 4 );
+            buf.putInt( value );
+            return this;
+        }
+
+        public int getInt( int index )
+        {
+            return buf.getInt( index );
+        }
+
+        public ByteBuffer putInt( int index, int value )
+        {
+            autoExpand( index, 4 );
+            buf.putInt( index, value );
+            return this;
+        }
+
+        public IntBuffer asIntBuffer()
+        {
+            return buf.asIntBuffer();
+        }
+
+        public long getLong()
+        {
+            return buf.getLong();
+        }
+
+        public ByteBuffer putLong( long value )
+        {
+            autoExpand( 8 );
+            buf.putLong( value );
+            return this;
+        }
+
+        public long getLong( int index )
+        {
+            return buf.getLong( index );
+        }
+
+        public ByteBuffer putLong( int index, long value )
+        {
+            autoExpand( index, 8 );
+            buf.putLong( index, value );
+            return this;
+        }
+
+        public LongBuffer asLongBuffer()
+        {
+            return buf.asLongBuffer();
+        }
+
+        public float getFloat()
+        {
+            return buf.getFloat();
+        }
+
+        public ByteBuffer putFloat( float value )
+        {
+            autoExpand( 4 );
+            buf.putFloat( value );
+            return this;
+        }
+
+        public float getFloat( int index )
+        {
+            return buf.getFloat( index );
+        }
+
+        public ByteBuffer putFloat( int index, float value )
+        {
+            autoExpand( index, 4 );
+            buf.putFloat( index, value );
+            return this;
+        }
+
+        public FloatBuffer asFloatBuffer()
+        {
+            return buf.asFloatBuffer();
+        }
+
+        public double getDouble()
+        {
+            return buf.getDouble();
+        }
+
+        public ByteBuffer putDouble( double value )
+        {
+            autoExpand( 8 );
+            buf.putDouble( value );
+            return this;
+        }
+
+        public double getDouble( int index )
+        {
+            return buf.getDouble( index );
+        }
+
+        public ByteBuffer putDouble( int index, double value )
+        {
+            autoExpand( index, 8 );
+            buf.putDouble( index, value );
+            return this;
+        }
+
+        public DoubleBuffer asDoubleBuffer()
+        {
+            return buf.asDoubleBuffer();
+        }
+
+        public ByteBuffer expand( int expectedRemaining )
+        {
+            if( autoExpand )
+            {
+                int pos = buf.position();
+                int limit = buf.limit();
+                int end = pos + expectedRemaining;
+                if( end > limit ) {
+                    ensureCapacity( end );
+                    buf.limit( end );
+                }
+            }
+            return this;
+        }
+        
+        public ByteBuffer expand( int pos, int expectedRemaining )
+        {
+            if( autoExpand )
+            {
+                int limit = buf.limit();
+                int end = pos + expectedRemaining;
+                if( end > limit ) {
+                    ensureCapacity( end );
+                    buf.limit( end );
+                }
+            }
+            return this;
+        }
+        
+        private void ensureCapacity( int requestedCapacity )
+        {
+            if( requestedCapacity <= buf.capacity() )
+            {
+                return;
+            }
+            
+            int newCapacity = MINIMUM_CAPACITY;
+            while( newCapacity < requestedCapacity )
+            {
+                newCapacity <<= 1;
+            }
+            
+            java.nio.ByteBuffer oldBuf = this.buf;
+            java.nio.ByteBuffer newBuf;
+            if( isDirect() )
+            {
+                newBuf = java.nio.ByteBuffer.allocateDirect( newCapacity );
+            }
+            else
+            {
+                newBuf = java.nio.ByteBuffer.allocate( newCapacity );
+            }
+
+            newBuf.clear();
+            newBuf.order( oldBuf.order() );
+
+            int pos = oldBuf.position();
+            int limit = oldBuf.limit();
+            oldBuf.clear();
+            newBuf.put( oldBuf );
+            newBuf.position( 0 );
+            newBuf.limit( limit );
+            newBuf.position( pos );
+            this.buf = newBuf;
+        }
+    }
+}

Propchange: directory/trunks/mina/core/src/main/java/org/apache/mina/common/SimpleByteBufferAllocator.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision