@@ -20,6 +20,7 @@ public final class ChunkCacheEntry {
2020 private final McChunkPos pos ;
2121
2222 private volatile @ Nullable CompletableFuture <@ Nullable ByteBuf > future ;
23+ private volatile boolean released = false ;
2324
2425 public ChunkCacheEntry (LevelHook level , McChunkPos pos ) {
2526 this .level = level ;
@@ -56,19 +57,25 @@ public ChunkCacheEntry(LevelHook level, McChunkPos pos) {
5657 }
5758
5859 public CompletableFuture <@ Nullable ByteBuf > get () {
59- // all of this code runs synchronized on this cache entry to
60+ // all of this code runs synchronized on this cache entry
6061 synchronized (this ) {
62+ if (this .released ) {
63+ throw new IllegalStateException ("Can't get buffer for " + this .pos + " in "
64+ + this .level .getName () + ", cache entry has already been released" );
65+ }
6166 {
6267 CompletableFuture <@ Nullable ByteBuf > future = this .future ;
6368 if (future != null ) {
64- // future is valid , return immediately
69+ // future is already set , return
6570 return future ;
6671 }
6772 }
6873 CompletableFuture <@ Nullable ByteBuf > future = CompletableFuture .completedFuture (null )
6974 // launch chunk handling asynchronously to minimize lock time
7075 .thenComposeAsync (__ -> this .tryGet ())
7176 .thenApply (buf -> {
77+ // if the bytebuf is null, clear the future; this makes it
78+ // possible to retry getting this chunk on the next attempt
7279 if (buf == null ) {
7380 // can't cause deadlock as this is run asynchronously
7481 synchronized (this ) {
@@ -77,8 +84,8 @@ public ChunkCacheEntry(LevelHook level, McChunkPos pos) {
7784 }
7885 return buf ;
7986 });
80- // mark the running future as valid; if chunk generation fails,
81- // it will be automatically marked as invalid after it's done
87+ // save the future to return for later calls; this future will
88+ // be cleared if getting the chunk fails (see above)
8289 this .future = future ;
8390 return future ;
8491 }
@@ -90,6 +97,9 @@ public void release() {
9097 if (future != null ) {
9198 future .thenAccept (ReferenceCountUtil ::release );
9299 }
100+ // clear saved future and mark chunk as released
101+ this .future = null ;
102+ this .released = true ;
93103 }
94104 }
95105}
0 commit comments