@@ -300,6 +300,11 @@ private static Properties readPropertiesFile() {
300300
301301 private final Collection <StatusListener > listeners ;
302302
303+ /**
304+ * Cache of the least-specific level available among {@link #listeners} to speed-up {@link #isEnabled(Level, Marker)}.
305+ */
306+ private volatile Level leastSpecificListenerLevel ;
307+
303308 private final transient ReadWriteLock listenerLock = new ReentrantReadWriteLock ();
304309
305310 private final transient Lock listenerReadLock = listenerLock .readLock ();
@@ -342,6 +347,7 @@ public StatusLogger(
342347 this .config = requireNonNull (config , "config" );
343348 this .defaultListener = requireNonNull (defaultListener , "defaultListener" );
344349 this .listeners = new ArrayList <>(Collections .singleton (defaultListener ));
350+ this .leastSpecificListenerLevel = defaultListener .getStatusLevel ();
345351 }
346352
347353 /**
@@ -409,6 +415,7 @@ public void registerListener(final StatusListener listener) {
409415 listenerWriteLock .lock ();
410416 try {
411417 listeners .add (listener );
418+ updateLeastSpecificListenerLevel ();
412419 } finally {
413420 listenerWriteLock .unlock ();
414421 }
@@ -425,11 +432,25 @@ public void removeListener(final StatusListener listener) {
425432 try {
426433 closeListenerSafely (listener );
427434 listeners .remove (listener );
435+ updateLeastSpecificListenerLevel ();
428436 } finally {
429437 listenerWriteLock .unlock ();
430438 }
431439 }
432440
441+ private void updateLeastSpecificListenerLevel () {
442+ Level localLeastSpecificListenerLevel = leastSpecificListenerLevel ;
443+ for (final StatusListener listener : listeners ) {
444+ final Level listenerLevel = listener .getStatusLevel ();
445+ if (listenerLevel .isLessSpecificThan (localLeastSpecificListenerLevel )) {
446+ localLeastSpecificListenerLevel = listener .getStatusLevel ();
447+ }
448+ }
449+ // We must update `leastSpecificListenerLevel` in a single instruction!
450+ // It is `volatile` and accessed by `getLevel()` and `isEnabled()` without listener locks for efficiency.
451+ leastSpecificListenerLevel = localLeastSpecificListenerLevel ;
452+ }
453+
433454 /**
434455 *
435456 * Sets the level of the default listener.
@@ -458,16 +479,18 @@ public Iterable<StatusListener> getListeners() {
458479 }
459480
460481 /**
461- * Clears the event buffer and listeners.
482+ * Clears the event buffer and removes the <em>registered</em> (not the default one!) listeners.
462483 */
463484 public void reset () {
464485 listenerWriteLock .lock ();
465486 try {
466- Iterator <StatusListener > listenerIterator = listeners .iterator ();
487+ final Iterator <StatusListener > listenerIterator = listeners .iterator ();
467488 while (listenerIterator .hasNext ()) {
468- StatusListener listener = listenerIterator .next ();
469- closeListenerSafely (listener );
470- listenerIterator .remove ();
489+ final StatusListener listener = listenerIterator .next ();
490+ if (listener != defaultListener ) {
491+ closeListenerSafely (listener );
492+ listenerIterator .remove ();
493+ }
471494 }
472495 } finally {
473496 listenerWriteLock .unlock ();
@@ -501,13 +524,13 @@ public void clear() {
501524 }
502525
503526 /**
504- * Returns the level of the default listener .
527+ * Returns the least specific level among listeners .
505528 *
506- * @return the default listener level
529+ * @return the least specific listener level
507530 */
508531 @ Override
509532 public Level getLevel () {
510- return defaultListener . getStatusLevel () ;
533+ return leastSpecificListenerLevel ;
511534 }
512535
513536 @ Override
@@ -736,12 +759,6 @@ public boolean isEnabled(final Level level, final Marker marker, final Message m
736759 @ Override
737760 public boolean isEnabled (final Level level , final Marker marker ) {
738761 requireNonNull (level , "level" );
739- listenerReadLock .lock ();
740- try {
741- return listeners .stream ()
742- .anyMatch (listener -> listener .getStatusLevel ().isLessSpecificThan (level ));
743- } finally {
744- listenerReadLock .unlock ();
745- }
762+ return leastSpecificListenerLevel .isLessSpecificThan (level );
746763 }
747764}
0 commit comments