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 ;
@@ -115,6 +112,7 @@ public abstract class CommandManager<C> implements Stateful<RegistrationState>,
115112 private final Set <CloudCapability > capabilities = new HashSet <>();
116113 private final ExceptionController <C > exceptionController = new ExceptionController <>();
117114 private final CommandExecutor <C > commandExecutor ;
115+ final ThreadLocalPermissionCache <C > threadLocalPermissionCache = new ThreadLocalPermissionCache <>(this .settings );
118116
119117 private CaptionFormatter <C , String > captionVariableReplacementHandler = CaptionFormatter .placeholderReplacing ();
120118 private CommandSyntaxFormatter <C > commandSyntaxFormatter = new StandardCommandSyntaxFormatter <>(this );
@@ -382,22 +380,6 @@ public boolean hasCapability(final @NonNull CloudCapability capability) {
382380 return Collections .unmodifiableSet (new HashSet <>(this .capabilities ));
383381 }
384382
385- private final ThreadLocal <Pair <Map <Pair <C , Permission >, PermissionResult >, AtomicInteger >> threadLocalPermissionCache =
386- ThreadLocal .withInitial (() -> Pair .of (new HashMap <>(), new AtomicInteger (0 )));
387-
388- @ SuppressWarnings ("rawtypes" )
389- private @ NonNull <T > PermissionResult testPermissionCaching (
390- final @ NonNull C sender ,
391- final @ NonNull T permission ,
392- final @ NonNull Function <Pair <C , T >, @ NonNull PermissionResult > tester
393- ) {
394- if (!this .settings .get (ManagerSetting .REDUCE_REDUNDANT_PERMISSION_CHECKS )) {
395- return tester .apply (Pair .of (sender , permission ));
396- }
397- return this .threadLocalPermissionCache .get ().first ()
398- .computeIfAbsent ((Pair ) Pair .of (sender , permission ), (Function ) tester );
399- }
400-
401383 /**
402384 * Checks if the command sender has the required permission and returns the result.
403385 *
@@ -410,30 +392,13 @@ public boolean hasCapability(final @NonNull CloudCapability capability) {
410392 final @ NonNull C sender ,
411393 final @ NonNull Permission permission
412394 ) {
413- final boolean cache = this .settings .get (ManagerSetting .REDUCE_REDUNDANT_PERMISSION_CHECKS );
414- try {
415- if (cache ) {
416- final int prev = this .threadLocalPermissionCache .get ().second ().getAndIncrement ();
417- if (prev == 0 ) {
418- // Cleanup from case where cache was enabled mid-permission check
419- this .threadLocalPermissionCache .get ().first ().clear ();
420- }
421- }
422- return this .testPermission_ (sender , permission );
423- } finally {
424- if (cache ) {
425- final Pair <Map <Pair <C , Permission >, PermissionResult >, AtomicInteger > pair = this .threadLocalPermissionCache .get ();
426- if (pair .second ().getAndDecrement () == 1 ) {
427- pair .first ().clear ();
428- }
429- }
430- }
395+ return this .threadLocalPermissionCache .withPermissionCache (() -> this .testPermission_ (sender , permission ));
431396 }
432397
433398 @ SuppressWarnings ("unchecked" )
434399 private @ NonNull PermissionResult testPermission_ (final @ NonNull C sender , final @ NonNull Permission permission ) {
435400 if (permission instanceof PredicatePermission ) {
436- return this .testPermissionCaching (sender , (PredicatePermission <C >) permission , pair -> {
401+ return this .threadLocalPermissionCache . testPermissionCaching (sender , (PredicatePermission <C >) permission , pair -> {
437402 return pair .second ().testPermission (pair .first ());
438403 });
439404 } else if (permission instanceof OrPermission ) {
@@ -453,7 +418,7 @@ public boolean hasCapability(final @NonNull CloudCapability capability) {
453418 }
454419 return PermissionResult .allowed (permission );
455420 }
456- return this .testPermissionCaching (sender , permission , pair -> {
421+ return this .threadLocalPermissionCache . testPermissionCaching (sender , permission , pair -> {
457422 return PermissionResult .of (
458423 pair .second ().isEmpty () || this .hasPermission (pair .first (), pair .second ().permissionString ()), pair .second ());
459424 });
0 commit comments