@@ -476,10 +476,10 @@ index 0000000000000000000000000000000000000000..f651a277fabf7f863c648c6c2658e2e6
476476+ }
477477diff --git a/src/main/java/io/multipaper/shreddedpaper/threading/ShreddedPaperRegionScheduler.java b/src/main/java/io/multipaper/shreddedpaper/threading/ShreddedPaperRegionScheduler.java
478478new file mode 100644
479- index 0000000000000000000000000000000000000000..5366386f45b931f1f6d58684757bea593347be65
479+ index 0000000000000000000000000000000000000000..ab4774d7eaf13efeb41eae3fb0b646ac11b9dbce
480480--- /dev/null
481481+++ b/src/main/java/io/multipaper/shreddedpaper/threading/ShreddedPaperRegionScheduler.java
482- @@ -0,0 +1,179 @@
482+ @@ -0,0 +1,185 @@
483483+ package io.multipaper.shreddedpaper.threading;
484484+
485485+ import net.minecraft.server.level.ServerLevel;
@@ -594,63 +594,69 @@ index 0000000000000000000000000000000000000000..5366386f45b931f1f6d58684757bea59
594594+ return;
595595+ }
596596+
597- + // Lock acquired, run the task
598- + runnable.run();
597+ + try {
598+ + runnable.run();
599+ + } finally {
600+ + lock.unlock();
601+ + }
602+ +
599603+ future.complete(null);
600604+ } catch (Exception e) {
601605+ future.completeExceptionally(e);
602- + } finally {
603- + if (lock != null) lock.unlock();
604606+ }
605607+ }
606608+
607609+ private void runOnMany(RegionPos[] regionPosArray, Runnable runnable, CompletableFuture<Void> future) {
608610+ ShreddedPaperRegionLocker.RegionLock[] locks = new ShreddedPaperRegionLocker.RegionLock[regionPosArray.length];
609611+ try {
610- + for (int i = 0; i < regionPosArray.length; i++) {
611- + locks[i] = locker.tryTakeLockNow(regionPosArray[i]);
612- + if (locks[i] == null) {
613- + locker.onUnlock(regionPosArray[i], () -> CompletableFuture.runAsync(() -> runOnMany(regionPosArray, runnable, future), ShreddedPaperTickThread.getExecutor()));
614- + return;
612+ + try {
613+ + for (int i = 0; i < regionPosArray.length; i++) {
614+ + locks[i] = locker.tryTakeLockNow(regionPosArray[i]);
615+ + if (locks[i] == null) {
616+ + locker.onUnlock(regionPosArray[i], () -> CompletableFuture.runAsync(() -> runOnMany(regionPosArray, runnable, future), ShreddedPaperTickThread.getExecutor()));
617+ + return;
618+ + }
619+ + }
620+ +
621+ + // All locks acquired, run the task
622+ + runnable.run();
623+ + } finally {
624+ + for (int i = locks.length - 1; i >= 0; i--) {
625+ + if (locks[i] != null) locks[i].unlock();
615626+ }
616627+ }
617628+
618- + // All locks acquired, run the task
619- + runnable.run();
620629+ future.complete(null);
621- +
622630+ } catch (Exception e) {
623631+ future.completeExceptionally(e);
624- + } finally {
625- + for (int i = locks.length - 1; i >= 0; i--) {
626- + if (locks[i] != null) locks[i].unlock();
627- + }
628632+ }
629633+ }
630634+
631635+ private static void runAcrossLevels(ServerLevel level1, RegionPos regionPos1, ServerLevel level2, RegionPos regionPos2, Runnable runnable, CompletableFuture<Void> future) {
632636+ ShreddedPaperRegionLocker.RegionLock lock1 = null;
633637+ ShreddedPaperRegionLocker.RegionLock lock2 = null;
634638+ try {
635- + lock1 = level1.chunkScheduler.locker.tryTakeLockNow(regionPos1);
636- + lock2 = lock1 == null ? null : level2.chunkScheduler.locker.tryTakeLockNow(regionPos2);
639+ + try {
640+ + lock1 = level1.chunkScheduler.locker.tryTakeLockNow(regionPos1);
641+ + lock2 = lock1 == null ? null : level2.chunkScheduler.locker.tryTakeLockNow(regionPos2);
642+ +
643+ + if (lock2 == null) {
644+ + Supplier<CompletableFuture<Void>> unlockCallback = () -> CompletableFuture.runAsync(() -> runAcrossLevels(level1, regionPos1, level2, regionPos2, runnable, future), ShreddedPaperTickThread.getExecutor());
645+ + if (lock1 == null) level1.chunkScheduler.locker.onUnlock(regionPos1, unlockCallback);
646+ + else level2.chunkScheduler.locker.onUnlock(regionPos2, unlockCallback);
647+ + return;
648+ + }
637649+
638- + if (lock2 == null) {
639- + Supplier<CompletableFuture<Void>> unlockCallback = () -> CompletableFuture.runAsync(() -> runAcrossLevels(level1, regionPos1, level2, regionPos2, runnable, future), ShreddedPaperTickThread.getExecutor() );
640- + if (lock1 == null) level1.chunkScheduler.locker.onUnlock(regionPos1, unlockCallback);
641- + else level2.chunkScheduler.locker.onUnlock(regionPos2, unlockCallback );
642- + return ;
650+ + // Both locks acquired, run the task
651+ + runnable.run( );
652+ + } finally {
653+ + if (lock2 != null) lock2.unlock( );
654+ + if (lock1 != null) lock1.unlock() ;
643655+ }
644656+
645- + // Both locks acquired, run the task
646- + runnable.run();
647657+ future.complete(null);
648- +
649658+ } catch (Exception e) {
650659+ future.completeExceptionally(e);
651- + } finally {
652- + if (lock2 != null) lock2.unlock();
653- + if (lock1 != null) lock1.unlock();
654660+ }
655661+ }
656662+
@@ -661,7 +667,7 @@ index 0000000000000000000000000000000000000000..5366386f45b931f1f6d58684757bea59
661667+ }
662668diff --git a/src/main/java/io/multipaper/shreddedpaper/threading/ShreddedPaperTickThread.java b/src/main/java/io/multipaper/shreddedpaper/threading/ShreddedPaperTickThread.java
663669new file mode 100644
664- index 0000000000000000000000000000000000000000..00394883983dc1e17e5e310884009802e32a7907
670+ index 0000000000000000000000000000000000000000..4083ed79587332391cedf8108f8adeeeffe4a8ad
665671--- /dev/null
666672+++ b/src/main/java/io/multipaper/shreddedpaper/threading/ShreddedPaperTickThread.java
667673@@ -0,0 +1,62 @@
@@ -710,7 +716,7 @@ index 0000000000000000000000000000000000000000..00394883983dc1e17e5e310884009802
710716+ return Thread.currentThread() instanceof ShreddedPaperTickThread;
711717+ }
712718+
713- + static ExecutorService getExecutor() {
719+ + public static ExecutorService getExecutor() {
714720+ return executor;
715721+ }
716722+
0 commit comments