-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix Memory Leak of Air Capability Listeners (#1275)
* Invalidate and revive air capabilities * Reuse air capability invalidation listeners * Fix returning null instead of empty optional * Check that the invalidated listener matches current Also implement the cached listener for RegulatorModule as well. * Add missing else branch to reset the cached air capabilities * Split into getting cached and current neighbour air capabilities * move tube module neighbour caching to separate interface reduce code duplication * Implement a cache for generic capabilities and neighbouring capabilities * Stop creating a lambda on every cached capability get operation --------- Co-authored-by: Des Herriott <[email protected]>
- Loading branch information
Showing
9 changed files
with
246 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
src/main/java/me/desht/pneumaticcraft/common/capabilities/CapabilityCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package me.desht.pneumaticcraft.common.capabilities; | ||
|
||
import net.minecraftforge.common.util.LazyOptional; | ||
import net.minecraftforge.common.util.NonNullConsumer; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
/** | ||
* Generic capability cache. | ||
* <br/> | ||
* Typical usage is to {@link CapabilityCache#get()} and use it if it is present, otherwise call {@link CapabilityCache#set(LazyOptional)} to update the capability cache. | ||
*/ | ||
public final class CapabilityCache<T> { | ||
private LazyOptional<T> cachedCapability; | ||
private final NonNullConsumer<LazyOptional<T>> capabilityInvalidationListener; | ||
|
||
public CapabilityCache() { | ||
this.cachedCapability = LazyOptional.empty(); | ||
this.capabilityInvalidationListener = l -> { | ||
if (this.cachedCapability != l) { | ||
return; | ||
} | ||
|
||
this.cachedCapability = LazyOptional.empty(); | ||
}; | ||
} | ||
|
||
public @NotNull LazyOptional<T> get() { | ||
return this.cachedCapability; | ||
} | ||
|
||
/** | ||
* Sets the cached capability. | ||
* Also handles registering an invalidation listener to clear the cached capability. | ||
* | ||
* @param cap Capability to set. | ||
* @return The capability that was set. | ||
*/ | ||
public @NotNull LazyOptional<T> set(LazyOptional<T> cap) { | ||
if (this.cachedCapability == cap) { | ||
return cap; | ||
} | ||
|
||
if (!cap.isPresent()) { | ||
this.cachedCapability = LazyOptional.empty(); | ||
return this.cachedCapability; | ||
} | ||
|
||
this.cachedCapability = cap; | ||
cap.addListener(this.capabilityInvalidationListener); | ||
return this.cachedCapability; | ||
} | ||
|
||
public void clear() { | ||
this.cachedCapability = LazyOptional.empty(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
src/main/java/me/desht/pneumaticcraft/common/capabilities/NeighbouringCapabilityCache.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package me.desht.pneumaticcraft.common.capabilities; | ||
|
||
import me.desht.pneumaticcraft.common.util.CapabilityUtils; | ||
import net.minecraft.core.Direction; | ||
import net.minecraft.world.level.block.entity.BlockEntity; | ||
import net.minecraftforge.common.capabilities.Capability; | ||
import net.minecraftforge.common.util.LazyOptional; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
import java.util.EnumMap; | ||
import java.util.Map; | ||
|
||
/** | ||
* Capability cache for neighbours of a {@link BlockEntity}. | ||
* <br/> | ||
* Typical usage is to {@link NeighbouringCapabilityCache#get(Direction)} and use it if it is present, | ||
* otherwise call {@link NeighbouringCapabilityCache#set(Capability, BlockEntity, Direction)} to update the capability cache. | ||
*/ | ||
public class NeighbouringCapabilityCache<T> { | ||
private final Map<Direction, CapabilityCache<T>> neighbouringCapabilityCaches; | ||
|
||
public NeighbouringCapabilityCache() { | ||
this.neighbouringCapabilityCaches = new EnumMap<>(Direction.class); | ||
} | ||
|
||
/** | ||
* Get cached capability for a neighbouring {@link BlockEntity}. | ||
* | ||
* @param direction Direction from the original block entity to a neighbouring block entity. | ||
* @return The cached capability. | ||
*/ | ||
public @NotNull LazyOptional<T> get(@NotNull Direction direction) { | ||
CapabilityCache<T> cache = this.neighbouringCapabilityCaches.get(direction); | ||
if (cache == null) { | ||
return LazyOptional.empty(); | ||
} | ||
|
||
return cache.get(); | ||
} | ||
|
||
/** | ||
* Sets the cached capability for a neighbouring {@link BlockEntity}. | ||
* Also handles registering an invalidation listener to clear the cached capability. | ||
* | ||
* @param capability Capability to get and cache. | ||
* @param blockEntity Originating {@link BlockEntity}. | ||
* @param direction Direction from {@param blockEntity} to a neighbouring block entity to look for a capability. | ||
* @return The cached capability. | ||
*/ | ||
public @NotNull LazyOptional<T> set(@NotNull Capability<T> capability, @NotNull BlockEntity blockEntity, @NotNull Direction direction) { | ||
CapabilityCache<T> cache = this.neighbouringCapabilityCaches.get(direction); | ||
if (cache == null) { | ||
cache = new CapabilityCache<>(); | ||
this.neighbouringCapabilityCaches.put(direction, cache); | ||
} | ||
|
||
return cache.set(CapabilityUtils.getNeighbourCap(capability, blockEntity, direction)); | ||
} | ||
|
||
public void clear() { | ||
for (Direction dir : Direction.values()) { | ||
clear(dir); | ||
} | ||
} | ||
|
||
public void clear(@NotNull Direction dir) { | ||
CapabilityCache<T> cache = this.neighbouringCapabilityCaches.get(dir); | ||
if (cache == null) { | ||
return; | ||
} | ||
|
||
cache.clear(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.