mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-14 01:39:36 -04:00
Somewhat experimental fix for memory leaks seen in Microcontrollers. If you notice any new issues after this, please do let me know.
This essentially schedules machines for full cleanup at a later point, to allow executor threads to finish (can't close states while they're running, don't want to wait for them to finish to avoid lagging servers).
This commit is contained in:
parent
5e9861d04a
commit
d13cdc0cd8
@ -22,6 +22,7 @@ import li.cil.oc.common.tileentity.traits.power
|
||||
import li.cil.oc.integration.Mods
|
||||
import li.cil.oc.integration.util
|
||||
import li.cil.oc.server.component.Keyboard
|
||||
import li.cil.oc.server.machine.Machine
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||
import li.cil.oc.util._
|
||||
import net.minecraft.client.Minecraft
|
||||
@ -49,12 +50,16 @@ object EventHandler {
|
||||
|
||||
private val keyboards = java.util.Collections.newSetFromMap[Keyboard](new java.util.WeakHashMap[Keyboard, java.lang.Boolean])
|
||||
|
||||
private val machines = mutable.Set.empty[Machine]
|
||||
|
||||
def onRobotStart(robot: Robot): Unit = runningRobots += robot
|
||||
|
||||
def onRobotStopped(robot: Robot): Unit = runningRobots -= robot
|
||||
|
||||
def addKeyboard(keyboard: Keyboard): Unit = keyboards += keyboard
|
||||
|
||||
def scheduleClose(machine: Machine) = machines += machine
|
||||
|
||||
def schedule(tileEntity: TileEntity) {
|
||||
if (SideTracker.isServer) pending.synchronized {
|
||||
pending += (() => Network.joinOrCreateNetwork(tileEntity))
|
||||
@ -130,6 +135,10 @@ object EventHandler {
|
||||
else if (robot.world != null) robot.machine.update()
|
||||
})
|
||||
runningRobots --= invalid
|
||||
|
||||
val closed = mutable.ArrayBuffer.empty[Machine]
|
||||
machines.foreach(machine => if (machine.tryClose()) closed += machine)
|
||||
machines --= closed
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@ -243,7 +252,7 @@ object EventHandler {
|
||||
|
||||
didRecraft = recraft(e, tablet, stack => {
|
||||
// Restore EEPROM currently used in tablet.
|
||||
new TabletData(stack).items.collect { case Some(item) => item}.find(api.Items.get(_) == eeprom)
|
||||
new TabletData(stack).items.collect { case Some(item) => item }.find(api.Items.get(_) == eeprom)
|
||||
}) || didRecraft
|
||||
|
||||
// Presents?
|
||||
|
@ -127,6 +127,11 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B
|
||||
ServerPacketSender.sendComputerState(this)
|
||||
}
|
||||
|
||||
override def dispose(): Unit = {
|
||||
super.dispose()
|
||||
if (machine != null) machine.stop()
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def readFromNBTForServer(nbt: NBTTagCompound) {
|
||||
|
@ -23,6 +23,7 @@ import li.cil.oc.api.network.Message
|
||||
import li.cil.oc.api.network.Node
|
||||
import li.cil.oc.api.network.Visibility
|
||||
import li.cil.oc.api.prefab
|
||||
import li.cil.oc.common.EventHandler
|
||||
import li.cil.oc.common.SaveHandler
|
||||
import li.cil.oc.common.Slot
|
||||
import li.cil.oc.common.tileentity
|
||||
@ -257,6 +258,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
false
|
||||
case _ =>
|
||||
state.push(Machine.State.Stopping)
|
||||
EventHandler.scheduleClose(this)
|
||||
true
|
||||
})
|
||||
|
||||
@ -392,6 +394,8 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
def isExecuting = state.synchronized(state.contains(Machine.State.Running))
|
||||
|
||||
override val canUpdate = true
|
||||
|
||||
override def update() = if (state.synchronized(state.top != Machine.State.Stopped)) {
|
||||
@ -514,7 +518,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
inSynchronizedCall = false
|
||||
}
|
||||
|
||||
assert(state.top != Machine.State.Running)
|
||||
assert(!isExecuting)
|
||||
case _ => // Nothing special to do, just avoid match errors.
|
||||
})
|
||||
|
||||
@ -643,7 +647,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
|
||||
super.load(nbt)
|
||||
|
||||
state.pushAll(nbt.getIntArray("state").reverse.map(Machine.State(_)))
|
||||
state.pushAll(nbt.getIntArray("state").reverseMap(Machine.State(_)))
|
||||
nbt.getTagList("users", NBT.TAG_STRING).foreach((tag: NBTTagString) => _users += tag.func_150285_a_())
|
||||
if (nbt.hasKey("message")) {
|
||||
message = Some(nbt.getString("message"))
|
||||
@ -703,7 +707,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
}
|
||||
|
||||
override def save(nbt: NBTTagCompound): Unit = Machine.this.synchronized {
|
||||
assert(state.top != Machine.State.Running) // Lock on 'this' should guarantee this.
|
||||
assert(!isExecuting) // Lock on 'this' should guarantee this.
|
||||
|
||||
// Make sure we don't continue running until everything has saved.
|
||||
pause(0.05)
|
||||
@ -798,16 +802,25 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
false
|
||||
}
|
||||
|
||||
def tryClose(): Boolean =
|
||||
if (isExecuting) false
|
||||
else {
|
||||
close()
|
||||
true
|
||||
}
|
||||
|
||||
private def close() = state.synchronized(
|
||||
if (state.size == 0 || state.top != Machine.State.Stopped) {
|
||||
state.clear()
|
||||
state.push(Machine.State.Stopped)
|
||||
Option(architecture).foreach(_.close())
|
||||
signals.clear()
|
||||
uptime = 0
|
||||
cpuTotal = 0
|
||||
cpuStart = 0
|
||||
remainIdle = 0
|
||||
this.synchronized {
|
||||
state.clear()
|
||||
state.push(Machine.State.Stopped)
|
||||
Option(architecture).foreach(_.close())
|
||||
signals.clear()
|
||||
uptime = 0
|
||||
cpuTotal = 0
|
||||
cpuStart = 0
|
||||
remainIdle = 0
|
||||
}
|
||||
|
||||
// Mark state change in owner, to send it to clients.
|
||||
host.markChanged()
|
||||
@ -909,7 +922,7 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
case Machine.State.Stopping => // Nothing to do, we'll die anyway.
|
||||
case _ => throw new AssertionError("Invalid state in executor post-processing.")
|
||||
}
|
||||
assert(state.top != Machine.State.Running)
|
||||
assert(!isExecuting)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
|
Loading…
x
Reference in New Issue
Block a user