Move memory device class to own file.
This commit is contained in:
153
src/main/java/li/cil/oc2/common/bus/device/MemoryDevice.java
Normal file
153
src/main/java/li/cil/oc2/common/bus/device/MemoryDevice.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package li.cil.oc2.common.bus.device;
|
||||
|
||||
import li.cil.oc2.Constants;
|
||||
import li.cil.oc2.api.bus.device.vm.*;
|
||||
import li.cil.oc2.common.bus.device.provider.util.AbstractObjectProxy;
|
||||
import li.cil.oc2.common.serialization.BlobStorage;
|
||||
import li.cil.oc2.common.util.NBTTagIds;
|
||||
import li.cil.sedna.api.device.PhysicalMemory;
|
||||
import li.cil.sedna.device.memory.Memory;
|
||||
import li.cil.sedna.memory.PhysicalMemoryInputStream;
|
||||
import li.cil.sedna.memory.PhysicalMemoryOutputStream;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalLong;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class MemoryDevice extends AbstractObjectProxy<ItemStack> implements VMDevice, VMDeviceLifecycleListener {
|
||||
private static final UUID SERIALIZATION_KEY = UUID.fromString("c82f8c1c-d7ff-43b0-ab44-989e1fe818bb");
|
||||
|
||||
private static final String BLOB_HANDLE_NBT_TAG_NAME = "blob";
|
||||
private static final String ADDRESS_NBT_TAG_NAME = "address";
|
||||
|
||||
final int RAM_SIZE = 8 * Constants.MEGABYTE;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private BlobStorage.JobHandle jobHandle;
|
||||
private PhysicalMemory device;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private UUID blobHandle;
|
||||
private Long address;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
public MemoryDevice(final ItemStack value) {
|
||||
super(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VMDeviceLoadResult load(final VMContext context) {
|
||||
if (!allocateDevice(context)) {
|
||||
return VMDeviceLoadResult.fail();
|
||||
}
|
||||
|
||||
if (!claimAddress(context)) {
|
||||
return VMDeviceLoadResult.fail();
|
||||
}
|
||||
|
||||
loadPersistedState();
|
||||
|
||||
return VMDeviceLoadResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLifecycleEvent(final VMDeviceLifecycleEventType event) {
|
||||
switch (event) {
|
||||
case RESUME_RUNNING:
|
||||
awaitStorageOperation();
|
||||
break;
|
||||
case UNLOAD:
|
||||
unload();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> getSerializationKey() {
|
||||
return Optional.of(SERIALIZATION_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT serializeNBT() {
|
||||
final CompoundNBT nbt = new CompoundNBT();
|
||||
|
||||
if (device != null) {
|
||||
blobHandle = BlobStorage.validateHandle(blobHandle);
|
||||
nbt.putUniqueId(BLOB_HANDLE_NBT_TAG_NAME, blobHandle);
|
||||
|
||||
jobHandle = BlobStorage.submitSave(blobHandle, new PhysicalMemoryInputStream(device));
|
||||
}
|
||||
if (address != null) {
|
||||
nbt.putLong(ADDRESS_NBT_TAG_NAME, address);
|
||||
}
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(final CompoundNBT nbt) {
|
||||
if (nbt.hasUniqueId(BLOB_HANDLE_NBT_TAG_NAME)) {
|
||||
blobHandle = nbt.getUniqueId(BLOB_HANDLE_NBT_TAG_NAME);
|
||||
}
|
||||
if (nbt.contains(ADDRESS_NBT_TAG_NAME, NBTTagIds.TAG_LONG)) {
|
||||
address = nbt.getLong(ADDRESS_NBT_TAG_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private boolean allocateDevice(final VMContext context) {
|
||||
if (!context.getMemoryAllocator().claimMemory(RAM_SIZE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
device = Memory.create(RAM_SIZE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean claimAddress(final VMContext context) {
|
||||
final OptionalLong claimedAddress;
|
||||
if (this.address != null) {
|
||||
claimedAddress = context.getMemoryRangeAllocator().claimMemoryRange(this.address, device);
|
||||
} else {
|
||||
claimedAddress = context.getMemoryRangeAllocator().claimMemoryRange(device);
|
||||
}
|
||||
|
||||
if (!claimedAddress.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.address = claimedAddress.getAsLong();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void loadPersistedState() {
|
||||
if (blobHandle != null) {
|
||||
jobHandle = BlobStorage.submitLoad(blobHandle, new PhysicalMemoryOutputStream(device));
|
||||
}
|
||||
}
|
||||
|
||||
private void awaitStorageOperation() {
|
||||
if (jobHandle != null) {
|
||||
jobHandle.await();
|
||||
jobHandle = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void unload() {
|
||||
// RAM is volatile, so free up our persisted blob when device is unloaded.
|
||||
BlobStorage.freeHandle(blobHandle);
|
||||
blobHandle = null;
|
||||
|
||||
device = null;
|
||||
address = null;
|
||||
jobHandle = null;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,12 @@
|
||||
package li.cil.oc2.common.bus.device.provider;
|
||||
|
||||
import li.cil.oc2.Constants;
|
||||
import li.cil.oc2.api.bus.device.Device;
|
||||
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
|
||||
import li.cil.oc2.api.bus.device.vm.*;
|
||||
import li.cil.oc2.common.bus.device.MemoryDevice;
|
||||
import li.cil.oc2.common.bus.device.provider.util.AbstractItemDeviceProvider;
|
||||
import li.cil.oc2.common.bus.device.provider.util.AbstractObjectProxy;
|
||||
import li.cil.oc2.common.init.Items;
|
||||
import li.cil.oc2.common.serialization.BlobStorage;
|
||||
import li.cil.oc2.common.util.NBTTagIds;
|
||||
import li.cil.sedna.api.device.PhysicalMemory;
|
||||
import li.cil.sedna.device.memory.Memory;
|
||||
import li.cil.sedna.memory.PhysicalMemoryInputStream;
|
||||
import li.cil.sedna.memory.PhysicalMemoryOutputStream;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalLong;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class MemoryItemDeviceProvider extends AbstractItemDeviceProvider {
|
||||
public MemoryItemDeviceProvider() {
|
||||
super(Items.RAM_8M_ITEM.get());
|
||||
@@ -35,139 +21,4 @@ public final class MemoryItemDeviceProvider extends AbstractItemDeviceProvider {
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
private static final class MemoryDevice extends AbstractObjectProxy<ItemStack> implements VMDevice, VMDeviceLifecycleListener {
|
||||
private static final UUID SERIALIZATION_KEY = UUID.fromString("c82f8c1c-d7ff-43b0-ab44-989e1fe818bb");
|
||||
|
||||
private static final String BLOB_HANDLE_NBT_TAG_NAME = "blob";
|
||||
private static final String ADDRESS_NBT_TAG_NAME = "address";
|
||||
|
||||
final int RAM_SIZE = 8 * Constants.MEGABYTE;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private BlobStorage.JobHandle jobHandle;
|
||||
private PhysicalMemory device;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private UUID blobHandle;
|
||||
private Long address;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
public MemoryDevice(final ItemStack value) {
|
||||
super(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VMDeviceLoadResult load(final VMContext context) {
|
||||
if (!allocateDevice(context)) {
|
||||
return VMDeviceLoadResult.fail();
|
||||
}
|
||||
|
||||
if (!claimAddress(context)) {
|
||||
return VMDeviceLoadResult.fail();
|
||||
}
|
||||
|
||||
loadPersistedState();
|
||||
|
||||
return VMDeviceLoadResult.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleLifecycleEvent(final VMDeviceLifecycleEventType event) {
|
||||
switch (event) {
|
||||
case RESUME_RUNNING:
|
||||
awaitStorageOperation();
|
||||
break;
|
||||
case UNLOAD:
|
||||
unload();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<UUID> getSerializationKey() {
|
||||
return Optional.of(SERIALIZATION_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT serializeNBT() {
|
||||
final CompoundNBT nbt = new CompoundNBT();
|
||||
|
||||
if (device != null) {
|
||||
blobHandle = BlobStorage.validateHandle(blobHandle);
|
||||
nbt.putUniqueId(BLOB_HANDLE_NBT_TAG_NAME, blobHandle);
|
||||
|
||||
jobHandle = BlobStorage.submitSave(blobHandle, new PhysicalMemoryInputStream(device));
|
||||
}
|
||||
if (address != null) {
|
||||
nbt.putLong(ADDRESS_NBT_TAG_NAME, address);
|
||||
}
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(final CompoundNBT nbt) {
|
||||
if (nbt.hasUniqueId(BLOB_HANDLE_NBT_TAG_NAME)) {
|
||||
blobHandle = nbt.getUniqueId(BLOB_HANDLE_NBT_TAG_NAME);
|
||||
}
|
||||
if (nbt.contains(ADDRESS_NBT_TAG_NAME, NBTTagIds.TAG_LONG)) {
|
||||
address = nbt.getLong(ADDRESS_NBT_TAG_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private boolean allocateDevice(final VMContext context) {
|
||||
if (!context.getMemoryAllocator().claimMemory(RAM_SIZE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
device = Memory.create(RAM_SIZE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean claimAddress(final VMContext context) {
|
||||
final OptionalLong claimedAddress;
|
||||
if (this.address != null) {
|
||||
claimedAddress = context.getMemoryRangeAllocator().claimMemoryRange(this.address, device);
|
||||
} else {
|
||||
claimedAddress = context.getMemoryRangeAllocator().claimMemoryRange(device);
|
||||
}
|
||||
|
||||
if (!claimedAddress.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.address = claimedAddress.getAsLong();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void loadPersistedState() {
|
||||
if (blobHandle != null) {
|
||||
jobHandle = BlobStorage.submitLoad(blobHandle, new PhysicalMemoryOutputStream(device));
|
||||
}
|
||||
}
|
||||
|
||||
private void awaitStorageOperation() {
|
||||
if (jobHandle != null) {
|
||||
jobHandle.await();
|
||||
jobHandle = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void unload() {
|
||||
// RAM is volatile, so free up our persisted blob when device is unloaded.
|
||||
BlobStorage.freeHandle(blobHandle);
|
||||
blobHandle = null;
|
||||
|
||||
device = null;
|
||||
address = null;
|
||||
jobHandle = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user