BlockLayer temporarily use DirectByteBuffer (averting the issue #26)

This commit is contained in:
minjaesong
2019-06-23 01:43:56 +09:00
parent 88a288243c
commit 601afc2636

View File

@@ -2,7 +2,7 @@ package net.torvald.terrarum.gameworld
import com.badlogic.gdx.utils.Disposable import com.badlogic.gdx.utils.Disposable
import net.torvald.terrarum.AppLoader.printdbg import net.torvald.terrarum.AppLoader.printdbg
import sun.misc.Unsafe import java.nio.ByteBuffer
/** /**
* Original version Created by minjaesong on 2016-01-17. * Original version Created by minjaesong on 2016-01-17.
@@ -12,17 +12,23 @@ import sun.misc.Unsafe
*/ */
open class BlockLayer(val width: Int, val height: Int) : Disposable { open class BlockLayer(val width: Int, val height: Int) : Disposable {
private val unsafe: Unsafe private var unsafeArrayDestroyed = false
/*private val unsafe: Unsafe
init { init {
val unsafeConstructor = Unsafe::class.java.getDeclaredConstructor() val unsafeConstructor = Unsafe::class.java.getDeclaredConstructor()
unsafeConstructor.isAccessible = true unsafeConstructor.isAccessible = true
unsafe = unsafeConstructor.newInstance() unsafe = unsafeConstructor.newInstance()
} }
private var unsafeArrayDestroyed = false
private var layerPtr = unsafe.allocateMemory(width * height * BYTES_PER_BLOCK.toLong()) private val layerPtr = unsafe.allocateMemory(width * height * BYTES_PER_BLOCK.toLong())*/
private val directByteBuffer: ByteBuffer
init { init {
unsafe.setMemory(layerPtr, width * height * BYTES_PER_BLOCK.toLong(), 0) // does reliably fill the memory with zeroes //unsafe.setMemory(layerPtr, width * height * BYTES_PER_BLOCK.toLong(), 0) // does reliably fill the memory with zeroes
directByteBuffer = ByteBuffer.allocateDirect(width * height * BYTES_PER_BLOCK)
} }
/** /**
@@ -40,7 +46,8 @@ open class BlockLayer(val width: Int, val height: Int) : Disposable {
* TL;DR: LITTLE ENDIAN PLEASE * TL;DR: LITTLE ENDIAN PLEASE
*/ */
constructor(width: Int, height: Int, data: ByteArray) : this(width, height) { constructor(width: Int, height: Int, data: ByteArray) : this(width, height) {
data.forEachIndexed { index, byte -> unsafe.putByte(layerPtr + index, byte) } TODO()
//data.forEachIndexed { index, byte -> unsafe.putByte(layerPtr + index, byte) }
} }
@@ -65,8 +72,10 @@ open class BlockLayer(val width: Int, val height: Int) : Disposable {
iteratorCount += 2 iteratorCount += 2
val offset = 2 * (y * width + x) val offset = 2 * (y * width + x)
val lsb = unsafe.getByte(layerPtr + offset) //val lsb = unsafe.getByte(layerPtr + offset)
val msb = unsafe.getByte(layerPtr + offset + 1) val lsb = directByteBuffer[offset]
//val msb = unsafe.getByte(layerPtr + offset + 1)
val msb = directByteBuffer[offset + 1]
//return data[y * width + x] //return data[y * width + x]
return lsb.toUint() + msb.toUint().shl(8) return lsb.toUint() + msb.toUint().shl(8)
@@ -91,15 +100,18 @@ open class BlockLayer(val width: Int, val height: Int) : Disposable {
override fun next(): Byte { override fun next(): Byte {
iteratorCount += 1 iteratorCount += 1
return unsafe.getByte(layerPtr + iteratorCount) //return unsafe.getByte(layerPtr + iteratorCount)
return directByteBuffer[iteratorCount]
} }
} }
} }
internal fun unsafeGetTile(x: Int, y: Int): Int { internal fun unsafeGetTile(x: Int, y: Int): Int {
val offset = BYTES_PER_BLOCK * (y * width + x) val offset = BYTES_PER_BLOCK * (y * width + x)
val lsb = unsafe.getByte(layerPtr + offset) //val lsb = unsafe.getByte(layerPtr + offset)
val msb = unsafe.getByte(layerPtr + offset + 1) //val msb = unsafe.getByte(layerPtr + offset + 1)
val lsb = directByteBuffer[offset]
val msb = directByteBuffer[offset + 1]
return lsb.toUint() + msb.toUint().shl(8) return lsb.toUint() + msb.toUint().shl(8)
} }
@@ -110,28 +122,32 @@ open class BlockLayer(val width: Int, val height: Int) : Disposable {
val lsb = tile.and(0xff).toByte() val lsb = tile.and(0xff).toByte()
val msb = tile.ushr(8).and(0xff).toByte() val msb = tile.ushr(8).and(0xff).toByte()
unsafe.putByte(layerPtr + offset, lsb)
unsafe.putByte(layerPtr + offset + 1, msb) directByteBuffer.put(offset, lsb)
directByteBuffer.put(offset + 1, msb)
//unsafe.putByte(layerPtr + offset, lsb)
//unsafe.putByte(layerPtr + offset + 1, msb)
} }
/** /**
* @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200``` * @param blockOffset Offset in blocks. BlockOffset of 0x100 is equal to ```layerPtr + 0x200```
*/ */
internal fun unsafeSetTile(blockOffset: Long, tile: Int) { /*internal fun unsafeSetTile(blockOffset: Long, tile: Int) {
val offset = 2 * blockOffset val offset = BYTES_PER_BLOCK * blockOffset
val lsb = tile.and(0xff).toByte() val lsb = tile.and(0xff).toByte()
val msb = tile.ushr(8).and(0xff).toByte() val msb = tile.ushr(8).and(0xff).toByte()
unsafe.putByte(layerPtr + offset, lsb) unsafe.putByte(layerPtr + offset, lsb)
unsafe.putByte(layerPtr + offset + 1, msb) unsafe.putByte(layerPtr + offset + 1, msb)
} }*/
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height) fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
override fun dispose() { override fun dispose() {
if (!unsafeArrayDestroyed) { if (!unsafeArrayDestroyed) {
unsafe.freeMemory(layerPtr) //unsafe.freeMemory(layerPtr)
directByteBuffer.clear()
unsafeArrayDestroyed = true unsafeArrayDestroyed = true
printdbg(this, "BlockLayer successfully freed") printdbg(this, "BlockLayer successfully freed")
} }