KLALB V3.4
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
package org.kne.cloud.network;
|
||||
|
||||
import java.lang.foreign.Arena;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.MemorySegment.Scope;
|
||||
import java.lang.ref.PhantomReference;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class BufferedArena implements Arena{
|
||||
private static long blockSize=10*1024L*1024L;
|
||||
private volatile PreAlloc buffer;
|
||||
private static ReferenceQueue<MemorySegment> refq=new ReferenceQueue<>();
|
||||
private static MemorySegmentPool msp=new MemorySegmentPool(1000, blockSize,true);
|
||||
|
||||
public static long getBlockSize() {
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void setBlockSize(long blockSizex) {
|
||||
blockSize = blockSizex;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ReentrantLock lock=new ReentrantLock();
|
||||
|
||||
private class PreAlloc{
|
||||
private MemorySegment segment;
|
||||
private AtomicLong pos=new AtomicLong(0);
|
||||
private AtomicLong refs=new AtomicLong(0);
|
||||
public MemorySegment getSegment() {
|
||||
return segment;
|
||||
}
|
||||
public AtomicLong getPos() {
|
||||
return pos;
|
||||
}
|
||||
public PreAlloc(MemorySegment segment) {
|
||||
super();
|
||||
this.segment = segment;
|
||||
}
|
||||
public long byteSize() {
|
||||
return segment.byteSize();
|
||||
}
|
||||
public AtomicLong getRefs() {
|
||||
return refs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void allocateNew(long blockSize2) {
|
||||
lock.lock();
|
||||
try {
|
||||
//buffer=Arena.ofAuto().allocate(blockSize);
|
||||
MemorySegment raw=msp.borrow();
|
||||
buffer=new PreAlloc(raw);
|
||||
|
||||
}finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static {
|
||||
Thread t= new Thread(()->{
|
||||
while(true) {
|
||||
try {
|
||||
Reference<? extends MemorySegment> ref;
|
||||
ref = refq.remove();
|
||||
if(ref!=null) {
|
||||
ref.clear();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
t.setDaemon(true);
|
||||
t.setPriority(Thread.MAX_PRIORITY-1);
|
||||
t.start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public BufferedArena() {
|
||||
super();
|
||||
allocateNew(blockSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySegment allocate(long byteSize, long byteAlignment) {
|
||||
if(byteSize>blockSize)
|
||||
throw new IndexOutOfBoundsException("byteSize can't large than buffer block");
|
||||
long pos;
|
||||
PreAlloc bufferx;
|
||||
do{
|
||||
bufferx=this.buffer;
|
||||
pos=bufferx.getPos().getAndAdd(byteSize);
|
||||
if(pos+byteSize>bufferx.byteSize()) {
|
||||
allocateNew(blockSize);
|
||||
}else {
|
||||
break;
|
||||
}
|
||||
}while(true);
|
||||
bufferx.getRefs().incrementAndGet();
|
||||
MemorySegment sliced=bufferx.getSegment().asSlice(pos, byteSize);
|
||||
new MemorySegmentPhantomReference(sliced, refq, bufferx, msp);
|
||||
return sliced;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scope scope() {
|
||||
return Arena.ofAuto().scope();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
Arena.ofAuto().close();
|
||||
}
|
||||
public static BufferedArena ofBuffered() {
|
||||
return new BufferedArena();
|
||||
}
|
||||
|
||||
private class MemorySegmentPhantomReference extends PhantomReference<MemorySegment>{
|
||||
|
||||
private static AtomicReference<MemorySegmentPhantomReference> first=new AtomicReference<>(null);
|
||||
|
||||
private AtomicReference<MemorySegmentPhantomReference> next=new AtomicReference<>(null);
|
||||
private AtomicReference<MemorySegmentPhantomReference> prev=new AtomicReference<>(null);
|
||||
|
||||
private PreAlloc father;
|
||||
private MemorySegmentPool pool;
|
||||
|
||||
public MemorySegmentPhantomReference(MemorySegment referent, ReferenceQueue<? super MemorySegment> q,PreAlloc bufferx,MemorySegmentPool pool) {
|
||||
super(referent, q);
|
||||
this.father=bufferx;
|
||||
this.pool=pool;
|
||||
insert();
|
||||
}
|
||||
|
||||
private void insert() {
|
||||
MemorySegmentPhantomReference refn= first.getAndSet(this);
|
||||
if(refn!=null) {
|
||||
next.set(refn);
|
||||
refn.prev.set(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void remove() {
|
||||
MemorySegmentPhantomReference prevn= prev.getAndSet(null);
|
||||
MemorySegmentPhantomReference nextn=next.getAndSet(null);
|
||||
if(prevn!=null)
|
||||
prevn.next.set(nextn);
|
||||
if(nextn!=null)
|
||||
nextn.prev.set(prevn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if(father.getRefs().decrementAndGet()<=0) {
|
||||
if(buffer!=father)
|
||||
pool.back(father.getSegment());
|
||||
}
|
||||
remove();
|
||||
super.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user