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

com.zusmart.base.buffer.support.DefaultBufferAllocator Maven / Gradle / Ivy

Go to download

提供基础的工具类及方法类,Logging,Scanner,Buffer,NetWork,Future,Thread

There is a newer version: 1.0.6
Show newest version
package com.zusmart.base.buffer.support;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import com.zusmart.base.buffer.Buffer;
import com.zusmart.base.buffer.BufferAllocator;

public class DefaultBufferAllocator implements BufferAllocator {

	private static final int MIN_CACHABLE_LENGTH;
	private static final int MAX_CACHABLE_LENGTH;
	private static final int POSITIVE_INTEGER_SIZE;

	static {
		MIN_CACHABLE_LENGTH = 512;
		MAX_CACHABLE_LENGTH = Integer.MAX_VALUE;
		POSITIVE_INTEGER_SIZE = 31;
	}

	private final BufferSoftReference[] directPools = new BufferSoftReference[POSITIVE_INTEGER_SIZE];
	private final BufferSoftReference[] heaperPools = new BufferSoftReference[POSITIVE_INTEGER_SIZE];

	private final Lock[] directLocks = new ReentrantLock[POSITIVE_INTEGER_SIZE];
	private final Lock[] heaperLocks = new ReentrantLock[POSITIVE_INTEGER_SIZE];

	private final AtomicInteger getCount = new AtomicInteger();
	private final AtomicInteger hitCount = new AtomicInteger();

	public DefaultBufferAllocator() {
		for (int i = 0; i < POSITIVE_INTEGER_SIZE; i++) {
			this.directLocks[i] = new ReentrantLock();
			this.heaperLocks[i] = new ReentrantLock();
		}
	}

	@Override
	public Buffer allocate(int capacity, boolean direct) {
		this.getCount.incrementAndGet();
		int index = indexFor(capacity);
		if (index >= 0) {
			Integer key = new Integer(capacity);
			Object obj = get(direct, index, key);
			if (obj == null && ++index != POSITIVE_INTEGER_SIZE) {
				obj = get(direct, index, key);
			}
			if (obj != null) {
				this.hitCount.incrementAndGet();
				if (direct) {
					ByteBuffer content = (ByteBuffer) obj;
					content.clear();
					return new DirectBuffer(content, capacity);
				} else {
					return new HeaperBuffer((byte[]) obj, capacity);
				}
			}
		}

		try {
			return allocateNew(capacity, direct);
		} catch (OutOfMemoryError e) {
			clear();
			return allocateNew(capacity, direct);
		}
	}

	@Override
	public void clear() {
		for (int i = 0; i < POSITIVE_INTEGER_SIZE; i++) {
			clear(heaperLocks[i], heaperPools[i]);
			clear(directLocks[i], directPools[i]);
		}
	}

	private final int indexFor(int capacity) {
		if (capacity > MAX_CACHABLE_LENGTH || capacity < MIN_CACHABLE_LENGTH) {
			return -1;
		}
		for (int i = POSITIVE_INTEGER_SIZE - 1; i > 0; i--) {
			if ((capacity >>> i) > 0) {
				return i;
			}
		}
		return 0;
	}

	private final TreeMap getPool(BufferSoftReference reference) {
		return reference == null ? null : (TreeMap) reference.get();
	}

	private final TreeMap createPool(BufferSoftReference[] references, int index) {
		BufferSoftReference reference = references[index];
		TreeMap pool = reference == null ? null : (TreeMap) reference.get();
		if (pool == null) {
			pool = new TreeMap();
			references[index] = new BufferSoftReference(pool);
		}
		return pool;
	}

	private Object get(boolean direct, int index, Integer key) {
		Lock lock = direct ? directLocks[index] : heaperLocks[index];
		lock.lock();
		try {
			TreeMap pool = getPool(direct ? directPools[index] : heaperPools[index]);
			if (pool != null) {
				for (Iterator iter = pool.tailMap(key).values().iterator(); iter.hasNext();) {
					Entry first = (Entry) iter.next();
					Entry next = first.next;
					if (next != null) {
						first.next = next.next;
						next.next = null;
						return next.obj;
					} else {
						iter.remove();
						return first.obj;
					}
				}
			}
		} finally {
			lock.unlock();
		}
		return null;
	}

	private Buffer allocateNew(int capacity, boolean direct) {
		return direct ? (Buffer) new DirectBuffer(capacity) : new HeaperBuffer(capacity);
	}

	private void clear(Lock lock, BufferSoftReference reference) {
		lock.lock();
		try {
			TreeMap pool = getPool(reference);
			if (pool != null) {
				pool.clear();
			}
		} finally {
			lock.unlock();
		}
	}

	public double getHitRate() {
		return (double) hitCount.get() / getCount.get();
	}

	public String toString() {
		return super.toString() + " [hitRate] " + getHitRate();
	}

	private final class DirectBuffer extends ByteBufferBuffer {

		private ByteBuffer content;

		private DirectBuffer(ByteBuffer content, int capacity) {
			super(content, 0, capacity);
			this.content = content;
		}

		private DirectBuffer(int capacity) {
			this(ByteBuffer.allocateDirect(capacity), capacity);
		}

		@Override
		protected void doRelease() {
			int index = indexFor(content.capacity());
			if (index >= 0) {
				Lock lock = directLocks[index];
				Integer key = new Integer(content.capacity());
				Entry value = new Entry(content);

				lock.lock();
				try {
					value.next = (Entry) createPool(directPools, index).put(key, value);
				} finally {
					lock.unlock();
				}
			}
			content = null;
			super.doRelease();
		}

	}

	private final class HeaperBuffer extends ByteArrayBuffer {

		private byte[] content;

		private HeaperBuffer(byte[] content, int capacity) {
			super(content, 0, capacity);
			this.content = content;
		}

		private HeaperBuffer(int capacity) {
			this(new byte[capacity], capacity);
		}

		@Override
		protected void doRelease() {
			int index = indexFor(content.length);
			if (index >= 0) {
				Lock lock = heaperLocks[index];
				Integer key = new Integer(content.length);
				Entry value = new Entry(content);

				lock.lock();
				try {
					value.next = (Entry) createPool(heaperPools, index).put(key, value);
				} finally {
					lock.unlock();
				}
			}
			content = null;
			super.doRelease();
		}
	}

	private static class Entry {
		public final Object obj;
		public Entry next;

		public Entry(Object obj) {
			assert obj != null;
			this.obj = obj;
		}
	}

	private static class BufferSoftReference extends SoftReference> {

		public BufferSoftReference(TreeMap referent, ReferenceQueue> q) {
			super(referent, q);
		}

		public BufferSoftReference(TreeMap referent) {
			super(referent);
		}

	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy