Hopefully improve the synchronization of the networks' transmitter sets

This commit is contained in:
Ben Spiers 2015-01-07 23:13:10 +00:00
parent 5e9131a59f
commit 4b75a2f6a2
4 changed files with 100 additions and 138 deletions

View file

@ -135,12 +135,12 @@ public class GasNetwork extends DynamicNetwork<IGasHandler, GasNetwork>
gasStored = null; gasStored = null;
} }
public synchronized int getGasNeeded() public int getGasNeeded()
{ {
return getCapacity()-(gasStored != null ? gasStored.amount : 0); return getCapacity()-(gasStored != null ? gasStored.amount : 0);
} }
public synchronized int tickEmit(GasStack stack) public int tickEmit(GasStack stack)
{ {
List availableAcceptors = Arrays.asList(getAcceptors(stack.getGas()).toArray()); List availableAcceptors = Arrays.asList(getAcceptors(stack.getGas()).toArray());
@ -185,7 +185,7 @@ public class GasNetwork extends DynamicNetwork<IGasHandler, GasNetwork>
return sent; return sent;
} }
public synchronized int emit(GasStack stack) public int emit(GasStack stack)
{ {
if(gasStored != null && gasStored.getGas() != stack.getGas()) if(gasStored != null && gasStored.getGas() != stack.getGas())
{ {
@ -276,12 +276,12 @@ public class GasNetwork extends DynamicNetwork<IGasHandler, GasNetwork>
} }
@Override @Override
public synchronized Set<IGasHandler> getAcceptors(Object... data) public Set<IGasHandler> getAcceptors(Object... data)
{ {
Gas type = (Gas)data[0]; Gas type = (Gas)data[0];
Set<IGasHandler> toReturn = new HashSet<IGasHandler>(); Set<IGasHandler> toReturn = new HashSet<IGasHandler>();
for(IGasHandler acceptor : ((Map<Coord4D, IGasHandler>)possibleAcceptors.clone()).values()) for(IGasHandler acceptor : possibleAcceptors.values())
{ {
if(acceptorDirections.get(acceptor) == null) if(acceptorDirections.get(acceptor) == null)
{ {
@ -298,35 +298,7 @@ public class GasNetwork extends DynamicNetwork<IGasHandler, GasNetwork>
} }
@Override @Override
public synchronized void refresh() public void refresh(IGridTransmitter<GasNetwork> transmitter)
{
Set<IGridTransmitter<GasNetwork>> iterTubes = (Set<IGridTransmitter<GasNetwork>>)transmitters.clone();
Iterator<IGridTransmitter<GasNetwork>> it = iterTubes.iterator();
boolean networkChanged = false;
while(it.hasNext())
{
IGridTransmitter<GasNetwork> conductor = (IGridTransmitter<GasNetwork>)it.next();
if(conductor == null || conductor.getTile().isInvalid())
{
it.remove();
networkChanged = true;
transmitters.remove(conductor);
}
else {
conductor.setTransmitterNetwork(this);
}
}
if(networkChanged)
{
updateCapacity();
}
}
@Override
public synchronized void refresh(IGridTransmitter<GasNetwork> transmitter)
{ {
IGasHandler[] acceptors = GasTransmission.getConnectedAcceptors(transmitter.getTile()); IGasHandler[] acceptors = GasTransmission.getConnectedAcceptors(transmitter.getTile());

View file

@ -2,6 +2,7 @@ package mekanism.api.transmitters;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -24,7 +25,7 @@ import cpw.mods.fml.common.eventhandler.Event;
public abstract class DynamicNetwork<A, N extends DynamicNetwork<A, N>> implements ITransmitterNetwork<A, N>, IClientTicker, INetworkDataHandler public abstract class DynamicNetwork<A, N extends DynamicNetwork<A, N>> implements ITransmitterNetwork<A, N>, IClientTicker, INetworkDataHandler
{ {
public LinkedHashSet<IGridTransmitter<N>> transmitters = new LinkedHashSet<IGridTransmitter<N>>(); public final Set<IGridTransmitter<N>> transmitters = Collections.synchronizedSet(new LinkedHashSet<IGridTransmitter<N>>());
public HashMap<Coord4D, A> possibleAcceptors = new HashMap<Coord4D, A>(); public HashMap<Coord4D, A> possibleAcceptors = new HashMap<Coord4D, A>();
public HashMap<A, ForgeDirection> acceptorDirections = new HashMap<A, ForgeDirection>(); public HashMap<A, ForgeDirection> acceptorDirections = new HashMap<A, ForgeDirection>();
@ -92,14 +93,45 @@ public abstract class DynamicNetwork<A, N extends DynamicNetwork<A, N>> implemen
possibleAcceptors.clear(); possibleAcceptors.clear();
acceptorDirections.clear(); acceptorDirections.clear();
for(IGridTransmitter<N> transmitter : transmitters) synchronized(transmitters)
{ {
refresh(transmitter); for(IGridTransmitter<N> transmitter : transmitters)
{
refresh(transmitter);
}
} }
refresh(); refresh();
} }
@Override
public void refresh()
{
boolean networkChanged = false;
synchronized(transmitters)
{
for(Iterator<IGridTransmitter<N>> it = transmitters.iterator(); it.hasNext();)
{
IGridTransmitter<N> conductor = it.next();
if(conductor == null || conductor.getTile().isInvalid())
{
it.remove();
networkChanged = true;
} else
{
conductor.setTransmitterNetwork((N)this);
}
}
}
if(networkChanged)
{
updateCapacity();
}
}
public Range4D getPacketRange() public Range4D getPacketRange()
{ {
if(packetRange == null) if(packetRange == null)
@ -128,7 +160,9 @@ public abstract class DynamicNetwork<A, N extends DynamicNetwork<A, N>> implemen
return null; return null;
} }
Coord4D initCoord = Coord4D.get(transmitters.iterator().next().getTile()); Coord4D initCoord;
initCoord = Coord4D.get(transmitters.iterator().next().getTile());
int minX = initCoord.xCoord; int minX = initCoord.xCoord;
int minY = initCoord.yCoord; int minY = initCoord.yCoord;
@ -137,16 +171,19 @@ public abstract class DynamicNetwork<A, N extends DynamicNetwork<A, N>> implemen
int maxY = initCoord.yCoord; int maxY = initCoord.yCoord;
int maxZ = initCoord.zCoord; int maxZ = initCoord.zCoord;
for(IGridTransmitter transmitter : transmitters) synchronized(transmitters)
{ {
Coord4D coord = Coord4D.get(transmitter.getTile()); for(IGridTransmitter transmitter : transmitters)
{
Coord4D coord = Coord4D.get(transmitter.getTile());
if(coord.xCoord < minX) minX = coord.xCoord; if(coord.xCoord < minX) minX = coord.xCoord;
if(coord.yCoord < minY) minY = coord.yCoord; if(coord.yCoord < minY) minY = coord.yCoord;
if(coord.zCoord < minZ) minZ = coord.zCoord; if(coord.zCoord < minZ) minZ = coord.zCoord;
if(coord.xCoord > maxX) maxX = coord.xCoord; if(coord.xCoord > maxX) maxX = coord.xCoord;
if(coord.yCoord > maxY) maxY = coord.yCoord; if(coord.yCoord > maxY) maxY = coord.yCoord;
if(coord.zCoord > maxZ) maxZ = coord.zCoord; if(coord.zCoord > maxZ) maxZ = coord.zCoord;
}
} }
return new Range4D(minX, minY, minZ, maxX, maxY, maxZ, getWorld().provider.dimensionId); return new Range4D(minX, minY, minZ, maxX, maxY, maxZ, getWorld().provider.dimensionId);
@ -175,8 +212,8 @@ public abstract class DynamicNetwork<A, N extends DynamicNetwork<A, N>> implemen
if(!((TileEntity)aTransmitter).getWorldObj().isRemote) if(!((TileEntity)aTransmitter).getWorldObj().isRemote)
{ {
TransmitterNetworkRegistry.getInstance().registerNetwork(this); TransmitterNetworkRegistry.getInstance().registerNetwork(this);
} } else
else { {
MinecraftForge.EVENT_BUS.post(new ClientTickUpdate(this, (byte)1)); MinecraftForge.EVENT_BUS.post(new ClientTickUpdate(this, (byte)1));
} }
} }
@ -209,7 +246,7 @@ public abstract class DynamicNetwork<A, N extends DynamicNetwork<A, N>> implemen
return possibleAcceptors.size(); return possibleAcceptors.size();
} }
public synchronized void updateCapacity() public void updateCapacity()
{ {
updateMeanCapacity(); updateMeanCapacity();
capacity = (int)meanCapacity * transmitters.size(); capacity = (int)meanCapacity * transmitters.size();
@ -219,7 +256,7 @@ public abstract class DynamicNetwork<A, N extends DynamicNetwork<A, N>> implemen
* Override this if things can have variable capacity along the network. * Override this if things can have variable capacity along the network.
* @return An 'average' value of capacity. Calculate it how you will. * @return An 'average' value of capacity. Calculate it how you will.
*/ */
protected synchronized void updateMeanCapacity() protected void updateMeanCapacity()
{ {
if(transmitters.size() > 0) if(transmitters.size() > 0)
{ {
@ -294,7 +331,7 @@ public abstract class DynamicNetwork<A, N extends DynamicNetwork<A, N>> implemen
} }
@Override @Override
public synchronized void fixMessedUpNetwork(IGridTransmitter<N> transmitter) public void fixMessedUpNetwork(IGridTransmitter<N> transmitter)
{ {
if(transmitter instanceof TileEntity) if(transmitter instanceof TileEntity)
{ {
@ -321,7 +358,7 @@ public abstract class DynamicNetwork<A, N extends DynamicNetwork<A, N>> implemen
} }
@Override @Override
public synchronized void split(IGridTransmitter<N> splitPoint) public void split(IGridTransmitter<N> splitPoint)
{ {
if(splitPoint instanceof TileEntity) if(splitPoint instanceof TileEntity)
{ {

View file

@ -80,15 +80,18 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
} }
@Override @Override
protected synchronized void updateMeanCapacity() protected void updateMeanCapacity()
{ {
int numCables = transmitters.size(); int numCables = transmitters.size();
double reciprocalSum = 0; double reciprocalSum = 0;
for(IGridTransmitter<EnergyNetwork> cable : transmitters) synchronized(transmitters)
{ {
reciprocalSum += 1.0/(double)cable.getCapacity(); for(IGridTransmitter<EnergyNetwork> cable : transmitters)
} {
reciprocalSum += 1.0 / (double)cable.getCapacity();
}
}
meanCapacity = (double)numCables / reciprocalSum; meanCapacity = (double)numCables / reciprocalSum;
} }
@ -119,7 +122,7 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
} }
} }
public synchronized double getEnergyNeeded() public double getEnergyNeeded()
{ {
if(FMLCommonHandler.instance().getEffectiveSide().isClient()) if(FMLCommonHandler.instance().getEffectiveSide().isClient())
{ {
@ -129,7 +132,7 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
return getCapacity()-electricityStored; return getCapacity()-electricityStored;
} }
public synchronized double tickEmit(double energyToSend) public double tickEmit(double energyToSend)
{ {
if(FMLCommonHandler.instance().getEffectiveSide().isClient()) if(FMLCommonHandler.instance().getEffectiveSide().isClient())
{ {
@ -153,7 +156,7 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
return sent; return sent;
} }
public synchronized double emit(double energyToSend, boolean doEmit) public double emit(double energyToSend, boolean doEmit)
{ {
double toUse = Math.min(getEnergyNeeded(), energyToSend); double toUse = Math.min(getEnergyNeeded(), energyToSend);
if(doEmit) if(doEmit)
@ -166,7 +169,7 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
/** /**
* @return sent * @return sent
*/ */
public synchronized double doEmit(double energyToSend, boolean tryAgain) public double doEmit(double energyToSend, boolean tryAgain)
{ {
double sent = 0; double sent = 0;
@ -219,7 +222,7 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
} }
@Override @Override
public synchronized Set<TileEntity> getAcceptors(Object... data) public Set<TileEntity> getAcceptors(Object... data)
{ {
Set<TileEntity> toReturn = new HashSet<TileEntity>(); Set<TileEntity> toReturn = new HashSet<TileEntity>();
@ -228,7 +231,7 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
return toReturn; return toReturn;
} }
for(TileEntity acceptor : ((Map<Coord4D, TileEntity>)possibleAcceptors.clone()).values()) for(TileEntity acceptor : possibleAcceptors.values())
{ {
ForgeDirection side = acceptorDirections.get(acceptor); ForgeDirection side = acceptorDirections.get(acceptor);
@ -246,7 +249,6 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
if(handler.getMaxEnergy() - handler.getEnergy() > 0) if(handler.getMaxEnergy() - handler.getEnergy() > 0)
{ {
toReturn.add(acceptor); toReturn.add(acceptor);
continue;
} }
} }
} }
@ -259,7 +261,6 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
if(handler.receiveEnergy(side.getOpposite(), 1, true) > 0) if(handler.receiveEnergy(side.getOpposite(), 1, true) > 0)
{ {
toReturn.add(acceptor); toReturn.add(acceptor);
continue;
} }
} }
} }
@ -276,7 +277,6 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
if(Math.min(demanded, max) > 0) if(Math.min(demanded, max) > 0)
{ {
toReturn.add(acceptor); toReturn.add(acceptor);
continue;
} }
} }
} }
@ -286,37 +286,15 @@ public class EnergyNetwork extends DynamicNetwork<TileEntity, EnergyNetwork>
} }
@Override @Override
public synchronized void refresh() public void refresh()
{ {
Set<IGridTransmitter<EnergyNetwork>> iterCables = (Set<IGridTransmitter<EnergyNetwork>>)transmitters.clone(); super.refresh();
Iterator<IGridTransmitter<EnergyNetwork>> it = iterCables.iterator();
boolean networkChanged = false;
while(it.hasNext())
{
IGridTransmitter<EnergyNetwork> conductor = (IGridTransmitter<EnergyNetwork>)it.next();
if(conductor == null || conductor.getTile().isInvalid())
{
it.remove();
transmitters.remove(conductor);
networkChanged = true;
}
else {
conductor.setTransmitterNetwork(this);
}
}
if(networkChanged)
{
updateCapacity();
}
needsUpdate = true; needsUpdate = true;
} }
@Override @Override
public synchronized void refresh(IGridTransmitter<EnergyNetwork> transmitter) public void refresh(IGridTransmitter<EnergyNetwork> transmitter)
{ {
TileEntity[] acceptors = CableUtils.getConnectedEnergyAcceptors(transmitter.getTile()); TileEntity[] acceptors = CableUtils.getConnectedEnergyAcceptors(transmitter.getTile());

View file

@ -99,14 +99,17 @@ public class FluidNetwork extends DynamicNetwork<IFluidHandler, FluidNetwork>
} }
@Override @Override
protected synchronized void updateMeanCapacity() protected void updateMeanCapacity()
{ {
int numCables = transmitters.size(); int numCables = transmitters.size();
double sum = 0; double sum = 0;
for(IGridTransmitter<FluidNetwork> pipe : transmitters) synchronized(transmitters)
{ {
sum += pipe.getCapacity(); for(IGridTransmitter<FluidNetwork> pipe : transmitters)
{
sum += pipe.getCapacity();
}
} }
meanCapacity = sum / (double)numCables; meanCapacity = sum / (double)numCables;
@ -148,12 +151,12 @@ public class FluidNetwork extends DynamicNetwork<IFluidHandler, FluidNetwork>
refFluid = null; refFluid = null;
} }
public synchronized int getFluidNeeded() public int getFluidNeeded()
{ {
return getCapacity()-(fluidStored != null ? fluidStored.amount : 0); return getCapacity()-(fluidStored != null ? fluidStored.amount : 0);
} }
public synchronized int tickEmit(FluidStack fluidToSend, boolean doTransfer) public int tickEmit(FluidStack fluidToSend, boolean doTransfer)
{ {
List availableAcceptors = Arrays.asList(getAcceptors(fluidToSend).toArray()); List availableAcceptors = Arrays.asList(getAcceptors(fluidToSend).toArray());
@ -197,7 +200,7 @@ public class FluidNetwork extends DynamicNetwork<IFluidHandler, FluidNetwork>
return fluidSent; return fluidSent;
} }
public synchronized int emit(FluidStack fluidToSend, boolean doTransfer) public int emit(FluidStack fluidToSend, boolean doTransfer)
{ {
if(fluidToSend == null || (fluidStored != null && fluidStored.getFluid() != fluidToSend.getFluid())) if(fluidToSend == null || (fluidStored != null && fluidStored.getFluid() != fluidToSend.getFluid()))
{ {
@ -294,12 +297,12 @@ public class FluidNetwork extends DynamicNetwork<IFluidHandler, FluidNetwork>
} }
@Override @Override
public synchronized Set<IFluidHandler> getAcceptors(Object... data) public Set<IFluidHandler> getAcceptors(Object... data)
{ {
FluidStack fluidToSend = (FluidStack)data[0]; FluidStack fluidToSend = (FluidStack)data[0];
Set<IFluidHandler> toReturn = new HashSet<IFluidHandler>(); Set<IFluidHandler> toReturn = new HashSet<IFluidHandler>();
for(IFluidHandler acceptor : ((Map<Coord4D, IFluidHandler>)possibleAcceptors.clone()).values()) for(IFluidHandler acceptor : possibleAcceptors.values())
{ {
if(acceptorDirections.get(acceptor) == null) if(acceptorDirections.get(acceptor) == null)
{ {
@ -316,35 +319,7 @@ public class FluidNetwork extends DynamicNetwork<IFluidHandler, FluidNetwork>
} }
@Override @Override
public synchronized void refresh() public void refresh(IGridTransmitter<FluidNetwork> transmitter)
{
Set<IGridTransmitter<FluidNetwork>> iterPipes = (Set<IGridTransmitter<FluidNetwork>>)transmitters.clone();
Iterator it = iterPipes.iterator();
boolean networkChanged = false;
while(it.hasNext())
{
IGridTransmitter<FluidNetwork> conductor = (IGridTransmitter<FluidNetwork>)it.next();
if(conductor == null || conductor.getTile().isInvalid())
{
it.remove();
networkChanged = true;
transmitters.remove(conductor);
}
else {
conductor.setTransmitterNetwork(this);
}
}
if(networkChanged)
{
updateCapacity();
}
}
@Override
public synchronized void refresh(IGridTransmitter<FluidNetwork> transmitter)
{ {
IFluidHandler[] acceptors = PipeUtils.getConnectedAcceptors(transmitter.getTile()); IFluidHandler[] acceptors = PipeUtils.getConnectedAcceptors(transmitter.getTile());