<commit_before>/*
 *   @(#) $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.ExpiringStack;

/**
 * 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 (<EMAIL>)
 * @version $Rev$, $Date$
 */
public class PooledByteBufferAllocator implements ByteBufferAllocator
{
    private static final int MINIMUM_CAPACITY = 1;
    private static int threadId = 0;

    private final Expirer expirer;
    private final ExpiringStack containerStack = new ExpiringStack();
    private final ExpiringStack[] heapBufferStacks = new ExpiringStack[] {
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), };
    private final ExpiringStack[] directBufferStacks = new ExpiringStack[] {
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), };
    private int timeout;
    private boolean disposed;

    public PooledByteBufferAllocator()
    {
        this( 60 );
    }
    
    public PooledByteBufferAllocator( int timeout )
    {
        setTimeout( timeout );
        expirer = new Expirer();
        expirer.start();
    }
    
    public void dispose()
    {
        if( this == ByteBuffer.getAllocator() )
        {
            throw new IllegalStateException( "This allocator is in use." );
        }

        expirer.shutdown();
        synchronized( containerStack )
        {
            containerStack.clear();
        }
        
        for( int i = directBufferStacks.length - 1; i >= 0; i -- )
        {
            ExpiringStack stack = directBufferStacks[i];
            synchronized( stack )
            {
                stack.clear();
            }
        }
        for( int i = heapBufferStacks.length - 1; i >= 0; i -- )
        {
            ExpiringStack stack = heapBufferStacks[i];
            synchronized( stack )
            {
                stack.clear();
            }
        }
        disposed = true;
    }
    
    public int getTimeout()
    {
        return timeout;
    }
    
    public long getTimeoutMillis()
    {
        return timeout * 1000L;
    }
    
    public void setTimeout( int timeout )
    {<commit_msg>Updated documentation for PooledByteBufferAllocator<commit_after>/*
 *   @(#) $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.ExpiringStack;

/**
 * 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 releases the buffers which have not been in use for a certain
 * period.  You can adjust the period by calling {@link #setTimeout(int)}.
 * The default timeout is 1 minute (60 seconds).  To release these buffers
 * periodically, a daemon thread is started when a new instance of the allocator
 * is created.  You can stop the thread by calling {@link #dispose()}.
 * </p>
 * 
 * @author The Apache Directory Project (<EMAIL>)
 * @version $Rev$, $Date$
 */
public class PooledByteBufferAllocator implements ByteBufferAllocator
{
    private static final int MINIMUM_CAPACITY = 1;
    private static int threadId = 0;

    private final Expirer expirer;
    private final ExpiringStack containerStack = new ExpiringStack();
    private final ExpiringStack[] heapBufferStacks = new ExpiringStack[] {
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), };
    private final ExpiringStack[] directBufferStacks = new ExpiringStack[] {
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
            new ExpiringStack(), new ExpiringStack(), };
    private int timeout;
    private boolean disposed;

    /**
     * Creates a new instance with the default timeout.
     */
    public PooledByteBufferAllocator()
    {
        this( 60 );
    }

    /**
     * Creates a new instance with the specified <tt>timeout</tt>.
     */
    public PooledByteBufferAllocator( int timeout )
    {
        setTimeout( timeout );
        expirer = new Expirer();
        expirer.start();
    }

    /**
     * Stops the thread which releases unused buffers and make this allocator
     * unusable from now on.
     */
    public void dispose()
    {
        if( this == ByteBuffer.getAllocator() )
        {
            throw new IllegalStateException( "This allocator is in use." );
        }

        expirer.shutdown();
        synchronized( containerStack )
        {
            containerStack.clear();
        }
        
        for( int i = directBufferStacks.length - 1; i >= 0; i -- )
        {
            ExpiringStack stack = directBufferStacks[i];
            synchronized( stack )
            {
                stack.clear();
            }
        }
        for( int i = heapBufferStacks.length - 1; i >= 0; i -- )
        {
            ExpiringStack stack = heapBufferStacks[i];
            synchronized( stack )
            {
                stack.clear();
            }
        }
        disposed = true;
    }

    /**
     * Returns the timeout value of this allocator in seconds. 
     */
    public int getTimeout()
    {
        return timeout;
    }
    
    /**
     * Returns the timeout value of this allocator in milliseconds. 
     */
    public long getTimeoutMillis()
    {
        return timeout * 1000L;
    }
    
    /**
     * Sets the timeout value of this allocator in seconds.
     * 
     * @param timeout <tt>0</tt> or negative value to disable timeout.
     */
    public void setTimeout( int timeout )
    {
{'fraction_non_alphanumeric': 0.09822272641331065, 'fraction_numerical': 0.00548307808659482, 'mean_word_length': 2.5476190476190474, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4116068', 'n_tokens_mistral': 2777, 'n_tokens_neox': 2711, 'n_words': 981}