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

net.rubyeye.xmemcached.buffer.CachedBufferAllocator Maven / Gradle / Ivy

There is a newer version: 2.4.8
Show newest version
/**
 *Copyright [2009-2010] [dennis zhuang([email protected])]
 *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
 */
/**
 *Copyright [2009-2010] [dennis zhuang([email protected])]
 *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 net.rubyeye.xmemcached.buffer;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;

import net.rubyeye.xmemcached.utils.ByteUtils;

import com.google.code.yanf4j.util.CircularQueue;

/**
 * Cached IoBuffer allocator,cached buffer in ThreadLocal.
 * 
 * @author dennis
 * 
 */
@Deprecated
public class CachedBufferAllocator implements BufferAllocator {

	private static final int DEFAULT_MAX_POOL_SIZE = 8;
	private static final int DEFAULT_MAX_CACHED_BUFFER_SIZE = 1 << 18; // 256KB
	private final int maxPoolSize;
	private final int maxCachedBufferSize;
	private final ThreadLocal>> heapBuffers;
	private final IoBuffer EMPTY_IO_BUFFER = new CachedBufferAllocator.CachedIoBuffer(
			ByteBuffer.allocate(0));

	/**
	 * Creates a new instance with the default parameters ({@literal
	 * #DEFAULT_MAX_POOL_SIZE} and {@literal #DEFAULT_MAX_CACHED_BUFFER_SIZE}).
	 */
	public CachedBufferAllocator() {
		this(DEFAULT_MAX_POOL_SIZE, DEFAULT_MAX_CACHED_BUFFER_SIZE);
	}

	/**
	 * Creates a new instance.
	 * 
	 * @param maxPoolSize
	 *            the maximum number of buffers with the same capacity per
	 *            thread. 0 disables this limitation.
	 * @param maxCachedBufferSize
	 *            the maximum capacity of a cached buffer. A buffer whose
	 *            capacity is bigger than this value is not pooled. 0
	 *            disables this limitation.
	 */
	public CachedBufferAllocator(int maxPoolSize, int maxCachedBufferSize) {
		if (maxPoolSize < 0) {
			throw new IllegalArgumentException("maxPoolSize: " + maxPoolSize);
		}
		if (maxCachedBufferSize < 0) {
			throw new IllegalArgumentException("maxCachedBufferSize: "
					+ maxCachedBufferSize);
		}

		this.maxPoolSize = maxPoolSize;
		this.maxCachedBufferSize = maxCachedBufferSize;

		this.heapBuffers = new ThreadLocal>>() {

			
			@Override
			protected Map> initialValue() {
				return newPoolMap();
			}
		};
	}

	public int getMaxPoolSize() {
		return this.maxPoolSize;
	}

	public int getMaxCachedBufferSize() {
		return this.maxCachedBufferSize;
	}

	/**
	 * 初始化缓冲池
	 * 
	 * @return
	 */
	private Map> newPoolMap() {
		Map> poolMap = new HashMap>();
		int poolSize = this.maxPoolSize == 0 ? DEFAULT_MAX_POOL_SIZE
				: this.maxPoolSize;
		for (int i = 0; i < 31; i++) {
			poolMap.put(1 << i, new CircularQueue(poolSize));
		}
		poolMap.put(0, new CircularQueue(poolSize));
		poolMap.put(Integer.MAX_VALUE, new CircularQueue(
				poolSize));
		return poolMap;
	}

	public final IoBuffer allocate(int requestedCapacity) {
		if (requestedCapacity == 0) {
			return this.EMPTY_IO_BUFFER;
		}
		// 圆整requestedCapacity到2的x次方
		int actualCapacity = ByteUtils.normalizeCapacity(requestedCapacity);
		IoBuffer buf;
		if (this.maxCachedBufferSize != 0
				&& actualCapacity > this.maxCachedBufferSize) {
			buf = wrap(ByteBuffer.allocate(actualCapacity));
		} else {
			Queue pool;
			pool = this.heapBuffers.get().get(actualCapacity);
			// 从池中取
			buf = pool.poll();
			if (buf != null) {
				buf.clear();
			} else {
				buf = wrap(ByteBuffer.allocate(actualCapacity));
			}
		}
		buf.limit(requestedCapacity);
		return buf;
	}

	public final IoBuffer wrap(ByteBuffer nioBuffer) {
		return new CachedIoBuffer(nioBuffer);
	}

	public void dispose() {
		this.heapBuffers.remove();
	}

	public static BufferAllocator newInstance() {
		return new CachedBufferAllocator();
	}

	public static BufferAllocator newInstance(int maxPoolSize,
			int maxCachedBufferSize) {
		return new CachedBufferAllocator(maxPoolSize, maxCachedBufferSize);
	}

	public class CachedIoBuffer implements IoBuffer {

		Thread ownerThread; // 所分配的线程
		ByteBuffer origBuffer;

		public CachedIoBuffer(ByteBuffer origBuffer) {
			super();
			this.ownerThread = Thread.currentThread();
			this.origBuffer = origBuffer;
		}

		
		public void putInt(int i) {
			this.origBuffer.putInt(i);

		}

		
		public void putShort(short s) {
			this.origBuffer.putShort(s);
		}

		
		public ByteOrder order() {
			return this.origBuffer.order();
		}

		
		public boolean isDirect() {
			return this.origBuffer.isDirect();
		}

		
		public void order(ByteOrder byteOrder) {
			this.origBuffer.order(byteOrder);
		}
		
		public void putLong(long l) {
			this.origBuffer.putLong(l);

		}
		
		public final void free() {
			if (this.origBuffer == null
					|| this.origBuffer.capacity() > CachedBufferAllocator.this.maxCachedBufferSize
					|| Thread.currentThread() != this.ownerThread) {
				return;
			}

			// Add to the cache.
			Queue pool;
			pool = CachedBufferAllocator.this.heapBuffers.get().get(
					this.origBuffer.capacity());
			if (pool == null) {
				return;
			}
			// 防止OOM
			if (CachedBufferAllocator.this.maxPoolSize == 0
					|| pool.size() < CachedBufferAllocator.this.maxPoolSize) {
				pool.offer(new CachedIoBuffer(this.origBuffer));
			}
			this.origBuffer = null;

		}

		
		public final ByteBuffer[] getByteBuffers() {
			return new ByteBuffer[] { this.origBuffer };
		}

		
		public final void put(byte[] bytes) {
			this.origBuffer.put(bytes);
		}

		
		public final int capacity() {
			return this.origBuffer.capacity();
		}

		
		public final void clear() {
			this.origBuffer.clear();
		}

		
		public final void reset() {
			this.origBuffer.reset();
		}

		
		public final int remaining() {
			return this.origBuffer.remaining();
		}

		
		public final int position() {
			return this.origBuffer.position();
		}

		
		public final void mark() {
			this.origBuffer.mark();
		}

		
		public final int limit() {
			return this.origBuffer.limit();
		}

		
		public final boolean hasRemaining() {
			return this.origBuffer.hasRemaining();
		}

		
		public final void flip() {
			this.origBuffer.flip();
		}

		
		public final void put(byte b) {
			this.origBuffer.put(b);
		}

		
		public final void put(ByteBuffer buff) {
			this.origBuffer.put(buff);
		}

		
		public final ByteBuffer getByteBuffer() {
			return this.origBuffer;
		}

		
		public final void limit(int limit) {
			this.origBuffer.limit(limit);
		}

		
		public final void position(int pos) {
			this.origBuffer.position(pos);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy