All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xsocket.connection.IoQueue Maven / Gradle / Ivy

There is a newer version: 2.8.15
Show newest version
/*
 * Copyright (c) xlightweb.org, 2006 - 2010. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
 * The latest copy of this software may be found on http://www.xsocket.org/
 */
package org.xsocket.connection;

import java.nio.ByteBuffer;
import java.util.ArrayList;



/**
 *
 * @author [email protected]
 */
final class IoQueue  {

	/*
	 * the implementation is driven by the assumption, that
	 * in most cases just one buffer or one buffer array 
	 * will be enqueued
	 */
	
	
	private ByteBuffer[] buffers = null;
	private ByteBuffer[] leased = null;
	
		
	/**
	 * returns true, if empty
	 *
	 * @return true, if empty
	 */
	public synchronized boolean isEmpty() {
		if ((buffers == null) && (leased == null)) {
			return true;
			
		} else {
			return (getSize() == 0);
		}
	}

	

	/**
	 * return the current size
	 *
	 * @return  the current size
	 */
	public synchronized int getSize() {
		int size = 0; 
		
		if (buffers != null) {
			for (int i = 0; i < buffers.length; i++) {
				if (buffers[i] != null) {
					size += buffers[i].remaining();
				}
			}
		}

		if (leased != null) {
		    for (int i = 0; i < leased.length; i++) {
		        if (leased[i] != null) {
		            size += leased[i].remaining();
		        }
		    }
		}

		
		return size;
	}
	
	
	
	/**
	 * append a byte buffer to this queue.
	 *
	 * @param data the ByteBuffer to append
	 */
	public synchronized void append(ByteBuffer data) {
		if ((data == null) || (data.remaining() == 0)) {
			return;
		}
		
		if (buffers == null) {
			buffers = new ByteBuffer[1];
			buffers[0] = data;

		} else {
			ByteBuffer[] newBuffers = new ByteBuffer[buffers.length + 1];
			System.arraycopy(buffers, 0, newBuffers, 0, buffers.length);
			newBuffers[buffers.length] = data;
			buffers = newBuffers;
		}
	}

		
	/**
	 * append a list of byte buffer to this queue. By adding a list,
	 * the list becomes part of to the buffer, and should not be modified outside the buffer
	 * to avoid side effects
	 *
	 * @param bufs  the list of ByteBuffer
	 */
	public synchronized void append(ByteBuffer[] data) {
		if (data == null) {
			return;
		}

		if (buffers == null) {
			buffers = data;

		} else {
			ByteBuffer[] newBuffers = new ByteBuffer[buffers.length + data.length];
			System.arraycopy(buffers, 0, newBuffers, 0, buffers.length);
			System.arraycopy(data, 0, newBuffers, buffers.length, data.length);
			buffers = newBuffers;
		}
	}

	
	
	
	/**
	 * add the given ByteBuffer array into the head of the queue
	 *
	 * @param bufs  the list of ByteBuffer
	 */
	public synchronized void addFirst(ByteBuffer[] data) {
		if (data == null) {
			return;
		}

		if (buffers == null) {
			buffers = data;

		} else {
			ByteBuffer[] newBuffers = new ByteBuffer[buffers.length + data.length];
			System.arraycopy(data, 0, newBuffers, 0, data.length);
			System.arraycopy(buffers, 0, newBuffers, data.length, buffers.length);
			buffers = newBuffers;
		}
	}
	
	

	private void addFirst(ByteBuffer data) {
		if (data == null) {
			return;
		}

		if (buffers == null) {
			buffers = new ByteBuffer[] { data };

		} else {
			ByteBuffer[] newBuffers = new ByteBuffer[buffers.length + 1];
			newBuffers[0] = data;
			System.arraycopy(buffers, 0, newBuffers, 1, buffers.length);
			buffers = newBuffers;
		}
	}
	

	/**
	 * drain this queue
	 *  
	 * @return  the contained ByteBuffer array or null
	 */
	public synchronized ByteBuffer[] drain() {
		ByteBuffer[] result = buffers;
		buffers = null;
		return result;
	}
	
	
	
	/**
	 * lease 
	 * 
     * @param maxSize  max size to drain if buffer array will be returned
	 *  
	 * @return  the contained ByteBuffer array or null
	 */
	public synchronized ByteBuffer[] lease(int maxSize) {
	
		if ((buffers != null) && (buffers.length == 1)) {
		    ByteBuffer[] data = drain();
            leased = data;
            return data;
		}
		
		if (getSize() <= maxSize) {
		    ByteBuffer[] data = drain();
            leased = data;
            return data;
		
		} else {
			ArrayList result = new ArrayList();
			int remaining = maxSize;
			
			for (int i = 0; i < buffers.length; i++) {
				
				int size = buffers[i].remaining();
				
				if (size > 0) {
					
					if (size <= remaining) {
						result.add(buffers[i]);
						remaining -= size;
						
						if (remaining == 0) {
							removeBuffersFromHead(i + 1);
							break;
						}
						
					} else {
						int savedPos = buffers[i].position();
						int savedLimit = buffers[i].limit();
						
						buffers[i].limit(savedPos + remaining);
						ByteBuffer buffer = buffers[i].slice();
						result.add(buffer);
						
						buffers[i].limit(savedLimit);
						buffers[i].position(savedPos + remaining);
						addFirst(buffers[i]);
						
						removeBuffersFromHead(i + 1);
						
						break;
					}					
				}
			}
		
			ByteBuffer[] data = result.toArray(new ByteBuffer[result.size()]);
			leased = data;
			return data;
		}
	}
	
	
	   
    public synchronized void removeLeased() {
        leased = null;
    }

	
	
	private void removeBuffersFromHead(int count) {
		
		int newSize = buffers.length - count;
		
		if (newSize == 0) {
			buffers = null;
			
		} else {
			
			ByteBuffer[] newBuffers = new ByteBuffer[newSize]; 
			System.arraycopy(buffers, count, newBuffers, 0, newBuffers.length);
			buffers = newBuffers;
		}		
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy