forked from KNEMC/KLALB
134 lines
3.5 KiB
Java
134 lines
3.5 KiB
Java
package org.kne.cloud.network;
|
|
|
|
import java.lang.ref.Cleaner;
|
|
import java.lang.ref.PhantomReference;
|
|
import java.lang.ref.Reference;
|
|
import java.lang.ref.ReferenceQueue;
|
|
import java.lang.ref.WeakReference;
|
|
import java.nio.BufferOverflowException;
|
|
import java.nio.ByteBuffer;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
import org.kne.debug.TimeDebugger;
|
|
public class ByteBufferAllocator {
|
|
private List<ByteBufferPool> bbfps=new ArrayList<>();
|
|
|
|
private ByteBufferPool[]bbfpsarr;
|
|
|
|
|
|
private ReferenceQueue<ByteBuffer> refq=new ReferenceQueue<>();
|
|
private boolean isDirect;
|
|
|
|
public ByteBufferAllocator(boolean isDirect) {
|
|
this.isDirect=isDirect;
|
|
int i=1;
|
|
int maxi=0;
|
|
int mps=16;
|
|
for (int j = 0; j < 18; j++) {
|
|
int count=100;
|
|
mps+=count;
|
|
bbfps.add(new ByteBufferPool(mps, i,isDirect));
|
|
maxi=i;
|
|
i<<=1;
|
|
}
|
|
bbfpsarr=new ByteBufferPool[maxi];
|
|
for (int j = 0; j < bbfpsarr.length; j++) {
|
|
bbfpsarr[j]=getByteBufferPool(j);
|
|
}
|
|
|
|
Thread t= new Thread(()->{
|
|
while(true) {
|
|
try {
|
|
Reference<? extends ByteBuffer> ref;
|
|
ref = refq.remove();
|
|
if(ref!=null) {
|
|
ref.clear();
|
|
}
|
|
} catch (InterruptedException e) {
|
|
// TODO 自动生成的 catch 块
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
t.setPriority(Thread.MAX_PRIORITY-1);
|
|
t.start();
|
|
}
|
|
public ByteBuffer allocate(int capacity) {
|
|
if(true) {
|
|
return allocateHeap(capacity);
|
|
}
|
|
//new Exception().printStackTrace();
|
|
ByteBufferPool bbfp=bbfpsarr[capacity];
|
|
ByteBuffer bbf=null;
|
|
try {
|
|
bbf=bbfp.borrow();
|
|
}catch(OutOfMemoryError err) {
|
|
System.gc();
|
|
Thread.yield();
|
|
bbf=bbfp.borrow();
|
|
}
|
|
ByteBuffer bbfs=bbf.slice(0, capacity);
|
|
|
|
new ByteBufferPhantomReference(bbfs,refq,bbf,bbfp);
|
|
return bbfs;
|
|
}
|
|
private static ByteBuffer allocateHeap(int capacity) {
|
|
return ByteBuffer.wrap(new byte[capacity]);
|
|
}
|
|
private ByteBufferPool getByteBufferPool(int capacity) {
|
|
int elen=0;
|
|
for (int i = 0; i < bbfps.size(); i++) {
|
|
ByteBufferPool bfp=bbfps.get(i);
|
|
if(capacity<=(elen= bfp.getLength())) {
|
|
return bfp;
|
|
}
|
|
}
|
|
throw new RuntimeException("capacity:"+capacity+">"+elen);
|
|
}
|
|
private static class ByteBufferPhantomReference extends PhantomReference<ByteBuffer>{
|
|
|
|
private static AtomicReference<ByteBufferPhantomReference> first=new AtomicReference<>(null);
|
|
|
|
private AtomicReference<ByteBufferPhantomReference> next=new AtomicReference<>(null);
|
|
private AtomicReference<ByteBufferPhantomReference> prev=new AtomicReference<>(null);
|
|
|
|
private ByteBuffer father;
|
|
private ByteBufferPool pool;
|
|
|
|
public ByteBufferPhantomReference(ByteBuffer referent, ReferenceQueue<? super ByteBuffer> q,ByteBuffer father,ByteBufferPool pool) {
|
|
super(referent, q);
|
|
this.father=father;
|
|
this.pool=pool;
|
|
insert();
|
|
}
|
|
|
|
private void insert() {
|
|
ByteBufferPhantomReference refn= first.getAndSet(this);
|
|
if(refn!=null) {
|
|
next.set(refn);
|
|
refn.prev.set(this);
|
|
}
|
|
}
|
|
|
|
private void remove() {
|
|
ByteBufferPhantomReference prevn= prev.getAndSet(null);
|
|
ByteBufferPhantomReference nextn=next.getAndSet(null);
|
|
if(prevn!=null)
|
|
prevn.next.set(nextn);
|
|
if(nextn!=null)
|
|
nextn.prev.set(prevn);
|
|
}
|
|
|
|
@Override
|
|
public void clear() {
|
|
//System.out.println("clear");
|
|
pool.back(father);
|
|
remove();
|
|
super.clear();
|
|
}
|
|
}
|
|
}
|