2626import io .leangen .geantyref .TypeToken ;
2727import java .util .Collection ;
2828import java .util .Collections ;
29- import java .util .HashMap ;
3029import java .util .HashSet ;
3130import java .util .LinkedList ;
3231import java .util .List ;
33- import java .util .Map ;
3432import java .util .Objects ;
3533import java .util .Set ;
36- import java .util .concurrent .atomic .AtomicInteger ;
3734import java .util .concurrent .atomic .AtomicReference ;
3835import java .util .function .Consumer ;
39- import java .util .function .Function ;
4036import java .util .stream .Collectors ;
4137import org .apiguardian .api .API ;
4238import org .checkerframework .checker .nullness .qual .NonNull ;
6662import org .incendo .cloud .injection .ParameterInjectorRegistry ;
6763import org .incendo .cloud .internal .CommandNode ;
6864import org .incendo .cloud .internal .CommandRegistrationHandler ;
65+ import org .incendo .cloud .internal .ThreadLocalPermissionCache ;
6966import org .incendo .cloud .meta .CommandMeta ;
7067import org .incendo .cloud .parser .ArgumentParser ;
7168import org .incendo .cloud .parser .ParserParameter ;
@@ -112,6 +109,7 @@ public abstract class CommandManager<C> implements Stateful<RegistrationState>,
112109 private final Set <CloudCapability > capabilities = new HashSet <>();
113110 private final ExceptionController <C > exceptionController = new ExceptionController <>();
114111 private final CommandExecutor <C > commandExecutor ;
112+ final ThreadLocalPermissionCache <C > threadLocalPermissionCache = new ThreadLocalPermissionCache <>(this .settings );
115113
116114 private CaptionFormatter <C , String > captionVariableReplacementHandler = CaptionFormatter .placeholderReplacing ();
117115 private CommandSyntaxFormatter <C > commandSyntaxFormatter = new StandardCommandSyntaxFormatter <>(this );
@@ -349,22 +347,6 @@ public boolean hasCapability(final @NonNull CloudCapability capability) {
349347 return Collections .unmodifiableSet (new HashSet <>(this .capabilities ));
350348 }
351349
352- private final ThreadLocal <Pair <Map <Pair <C , Permission >, PermissionResult >, AtomicInteger >> threadLocalPermissionCache =
353- ThreadLocal .withInitial (() -> Pair .of (new HashMap <>(), new AtomicInteger (0 )));
354-
355- @ SuppressWarnings ("rawtypes" )
356- private @ NonNull <T > PermissionResult testPermissionCaching (
357- final @ NonNull C sender ,
358- final @ NonNull T permission ,
359- final @ NonNull Function <Pair <C , T >, @ NonNull PermissionResult > tester
360- ) {
361- if (!this .settings .get (ManagerSetting .REDUCE_REDUNDANT_PERMISSION_CHECKS )) {
362- return tester .apply (Pair .of (sender , permission ));
363- }
364- return this .threadLocalPermissionCache .get ().first ()
365- .computeIfAbsent ((Pair ) Pair .of (sender , permission ), (Function ) tester );
366- }
367-
368350 /**
369351 * Checks if the command sender has the required permission and returns the result.
370352 *
@@ -377,30 +359,13 @@ public boolean hasCapability(final @NonNull CloudCapability capability) {
377359 final @ NonNull C sender ,
378360 final @ NonNull Permission permission
379361 ) {
380- final boolean cache = this .settings .get (ManagerSetting .REDUCE_REDUNDANT_PERMISSION_CHECKS );
381- try {
382- if (cache ) {
383- final int prev = this .threadLocalPermissionCache .get ().second ().getAndIncrement ();
384- if (prev == 0 ) {
385- // Cleanup from case where cache was enabled mid-permission check
386- this .threadLocalPermissionCache .get ().first ().clear ();
387- }
388- }
389- return this .testPermission_ (sender , permission );
390- } finally {
391- if (cache ) {
392- final Pair <Map <Pair <C , Permission >, PermissionResult >, AtomicInteger > pair = this .threadLocalPermissionCache .get ();
393- if (pair .second ().getAndDecrement () == 1 ) {
394- pair .first ().clear ();
395- }
396- }
397- }
362+ return this .threadLocalPermissionCache .withPermissionCache (() -> this .testPermission_ (sender , permission ));
398363 }
399364
400365 @ SuppressWarnings ("unchecked" )
401366 private @ NonNull PermissionResult testPermission_ (final @ NonNull C sender , final @ NonNull Permission permission ) {
402367 if (permission instanceof PredicatePermission ) {
403- return this .testPermissionCaching (sender , (PredicatePermission <C >) permission , pair -> {
368+ return this .threadLocalPermissionCache . testPermissionCaching (sender , (PredicatePermission <C >) permission , pair -> {
404369 return pair .second ().testPermission (pair .first ());
405370 });
406371 } else if (permission instanceof OrPermission ) {
@@ -420,7 +385,7 @@ public boolean hasCapability(final @NonNull CloudCapability capability) {
420385 }
421386 return PermissionResult .allowed (permission );
422387 }
423- return this .testPermissionCaching (sender , permission , pair -> {
388+ return this .threadLocalPermissionCache . testPermissionCaching (sender , permission , pair -> {
424389 return PermissionResult .of (
425390 pair .second ().isEmpty () || this .hasPermission (pair .first (), pair .second ().permissionString ()), pair .second ());
426391 });
0 commit comments