11package org .embeddedt .modernfix .dfu ;
22
3- import com .google .common .cache .Cache ;
4- import com .google .common .cache .CacheBuilder ;
5- import com .mojang .datafixers .RewriteResult ;
6- import com .mojang .datafixers .TypeRewriteRule ;
7- import com .mojang .datafixers .functions .PointFreeRule ;
8- import com .mojang .datafixers .types .Type ;
9- import com .mojang .datafixers .util .Pair ;
10- import org .apache .commons .lang3 .tuple .Triple ;
113import org .embeddedt .modernfix .ModernFix ;
12- import sun .misc .Unsafe ;
134
145import java .lang .reflect .Field ;
15- import java .util .Optional ;
6+ import java .util .ArrayList ;
7+ import java .util .List ;
8+ import java .util .Map ;
169import java .util .concurrent .TimeUnit ;
17- import java .util .function .IntFunction ;
10+ import java .util .concurrent .atomic .AtomicLong ;
11+ import java .util .concurrent .locks .LockSupport ;
1812
1913public class DFUBlaster {
20- private static final Cache <Pair <IntFunction <RewriteResult <?, ?>>, Integer >, RewriteResult <?, ?>> hmapApplyCache = CacheBuilder .newBuilder ()
21- .expireAfterAccess (3 , TimeUnit .MINUTES )
22- .build ();
23- private static final Cache <Triple <Type <?>, TypeRewriteRule , PointFreeRule >, Optional <? extends RewriteResult <?, ?>>> rewriteCache = CacheBuilder .newBuilder ()
24- .expireAfterAccess (3 , TimeUnit .MINUTES )
25- .build ();
26- public static void blastMaps () {
14+ private static final List <Map <?, ?>> TRACKED_MAPS = buildTrackedMaps ();
15+ private static final long DELAY_TIME = TimeUnit .SECONDS .toNanos (60 );
16+ private static final AtomicLong NEXT_WAKE_TIME = new AtomicLong (System .nanoTime () + DELAY_TIME );
17+
18+ private static List <Map <?, ?>> buildTrackedMaps () {
19+ var list = new ArrayList <Map <?, ?>>();
20+ tryAdd (list , "com.mojang.datafixers.DSL$Instances" , "TAGGED_CHOICE_TYPE_CACHE" );
21+ tryAdd (list , "com.mojang.datafixers.functions.Fold" , "HMAP_APPLY_CACHE" );
22+ tryAdd (list , "com.mojang.datafixers.types.Type" , "REWRITE_CACHE" );
23+ return list ;
24+ }
25+
26+ private static void tryAdd (List <Map <?, ?>> list , String className , String fieldName ) {
2727 try {
28- Class <?> FOLD_CLASS = Class .forName ("com.mojang.datafixers.functions.Fold" );
29- Field hmapField = FOLD_CLASS .getDeclaredField ("HMAP_APPLY_CACHE" );
30- hmapField .setAccessible (true );
31- final Field theUnsafe = Unsafe .class .getDeclaredField ("theUnsafe" );
32- theUnsafe .setAccessible (true );
33- Unsafe unsafe = (Unsafe )theUnsafe .get (null );
34- Object base = unsafe .staticFieldBase (hmapField );
35- long offset = unsafe .staticFieldOffset (hmapField );
36- unsafe .putObject (base , offset , hmapApplyCache .asMap ());
37- Field rewriteCacheField = Type .class .getDeclaredField ("REWRITE_CACHE" );
38- rewriteCacheField .setAccessible (true );
39- base = unsafe .staticFieldBase (rewriteCacheField );
40- offset = unsafe .staticFieldOffset (rewriteCacheField );
41- unsafe .putObject (base , offset , rewriteCache .asMap ());
42- new CleanerThread ().start ();
43- } catch (Throwable e ) {
44- ModernFix .LOGGER .error ("Could not replace DFU map" , e );
28+ Class <?> clz = Class .forName (className );
29+ Field field = clz .getDeclaredField (fieldName );
30+ field .setAccessible (true );
31+ if (Map .class .isAssignableFrom (field .getType ())) {
32+ list .add ((Map <?, ?>)field .get (null ));
33+ } else {
34+ ModernFix .LOGGER .error ("Field {} on class {} is not a map" , field , className );
35+ }
36+ } catch (ReflectiveOperationException e ) {
37+ ModernFix .LOGGER .error ("Error tracking DFU field {} on class {}" , fieldName , className , e );
4538 }
4639 }
4740
41+ public static void blastMaps () {
42+ new CleanerThread ().start ();
43+ }
44+
45+ public static void kick () {
46+ NEXT_WAKE_TIME .getAndAdd (DELAY_TIME );
47+ }
48+
4849 static class CleanerThread extends Thread {
4950 CleanerThread () {
5051 this .setName ("DFU cleaning thread" );
@@ -55,13 +56,18 @@ static class CleanerThread extends Thread {
5556 @ Override
5657 public void run () {
5758 while (true ) {
58- try {
59- Thread .sleep (15000 );
60- } catch (InterruptedException e ){
61- return ;
59+ long waitTime = NEXT_WAKE_TIME .get () - System .nanoTime ();
60+ if (waitTime > 0 ) {
61+ LockSupport .parkNanos (waitTime );
62+ }
63+
64+ long lastStamp = NEXT_WAKE_TIME .get ();
65+ if (System .nanoTime () >= lastStamp ) {
66+ // Nobody kicked the watchdog again, we should clear the maps
67+ TRACKED_MAPS .forEach (Map ::clear );
68+ NEXT_WAKE_TIME .compareAndSet (lastStamp , System .nanoTime () + DELAY_TIME );
6269 }
63- rewriteCache .cleanUp ();
64- hmapApplyCache .cleanUp ();
70+ // Otherwise, we were told to wait for longer, so don't do anything
6571 }
6672 }
6773 }
0 commit comments