Implemented auto free LWJGL byte buffers.

fix-456
javasabr 8 years ago
parent ed4e614722
commit 2136dc4484
  1. 84
      jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java

@ -2,8 +2,12 @@ package com.jme3.util;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.nio.Buffer; import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* The implementation of the {@link BufferAllocator} which use {@link MemoryUtil} to manage memory. * The implementation of the {@link BufferAllocator} which use {@link MemoryUtil} to manage memory.
@ -12,13 +16,91 @@ import java.nio.ByteBuffer;
*/ */
public class LWJGLBufferAllocator implements BufferAllocator { public class LWJGLBufferAllocator implements BufferAllocator {
/**
* The reference queue.
*/
private static final ReferenceQueue<Buffer> DUMMY_QUEUE = new ReferenceQueue<Buffer>();
/**
* The LWJGL byte buffer deallocator.
*/
private static class Deallocator extends PhantomReference<ByteBuffer> {
/**
* The address of LWJGL byte buffer.
*/
private Long address;
public Deallocator(final ByteBuffer referent, final ReferenceQueue<? super ByteBuffer> queue,
final Long address) {
super(referent, queue);
this.address = address;
}
/**
* @param address the address of LWJGL byte buffer.
*/
void setAddress(final Long address) {
this.address = address;
}
/**
* Free memory.
*/
void free() {
if (address == null) return;
MemoryUtil.nmemFree(address);
DEALLOCATORS.remove(address);
}
}
/**
* The cleaner thread.
*/
private static final Thread CLEAN_THREAD = new Thread(LWJGLBufferAllocator::freeByteBuffers);
/**
* The map with created deallocators.
*/
private static final Map<Long, Deallocator> DEALLOCATORS = new ConcurrentHashMap<>();
static {
CLEAN_THREAD.setDaemon(true);
CLEAN_THREAD.setName("Thread to free LWJGL byte buffers");
CLEAN_THREAD.start();
}
/**
* Free unnecessary LWJGL byte buffers.
*/
private static void freeByteBuffers() {
try {
for (;;) {
final Deallocator deallocator = (Deallocator) DUMMY_QUEUE.remove();
deallocator.free();
}
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
@Override @Override
public void destroyDirectBuffer(final Buffer buffer) { public void destroyDirectBuffer(final Buffer buffer) {
final long address = MemoryUtil.memAddress((ByteBuffer) buffer);
// disable deallocator
final Deallocator deallocator = DEALLOCATORS.remove(address);
if (deallocator != null) deallocator.setAddress(null);
MemoryUtil.memFree(buffer); MemoryUtil.memFree(buffer);
} }
@Override @Override
public ByteBuffer allocate(final int size) { public ByteBuffer allocate(final int size) {
return MemoryUtil.memAlloc(size); final Long address = MemoryUtil.nmemAlloc(size);
final ByteBuffer byteBuffer = MemoryUtil.memByteBuffer(address, size);
DEALLOCATORS.put(address, new Deallocator(byteBuffer, DUMMY_QUEUE, address));
return byteBuffer;
} }
} }

Loading…
Cancel
Save