1515package ch .qos .logback .core .util ;
1616
1717import java .util .concurrent .atomic .AtomicLong ;
18- import java .util .function .LongBinaryOperator ;
19- import java .util .function .LongUnaryOperator ;
20- import java .util .function .UnaryOperator ;
2118
2219/**
23- * An invocation gate using very simple logic.
20+ * A time-based {@link InvocationGate} with simple, fixed-interval logic.
21+ * <p>
22+ * Callers on a hot path use {@link #isTooSoon(long)} to decide whether to skip
23+ * a costly operation. At most one thread per {@linkplain #increment increment}
24+ * interval is allowed to proceed (i.e. receives {@code false}); other threads
25+ * in the same window receive {@code true} and should skip the work.
26+ * </p>
27+ * <p>
28+ * Compared to {@link DefaultInvocationGate}, this implementation does not adapt
29+ * a sampling mask. It only advances an atomic next-allowed timestamp by a fixed
30+ * {@link Duration}.
31+ * </p>
32+ * <p>
33+ * Typical use is size checks in rolling policies where file length is expensive
34+ * relative to the logging call.
35+ * </p>
2436 *
37+ * @author Ceki Gülcü
2538 * @since 1.3.6/1.4.6
39+ * @see InvocationGate
40+ * @see DefaultInvocationGate
41+ * @see ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy
2642 */
2743public class SimpleInvocationGate implements InvocationGate {
2844
29- //volatile long next = 0;
30-
45+ /**
46+ * Next time (milliseconds since the epoch) at or after which a caller may be
47+ * allowed to proceed. Updated with compare-and-set so that only one thread
48+ * wins per interval.
49+ */
3150 AtomicLong atomicNext = new AtomicLong (0 );
51+
52+ /**
53+ * Minimum time between allowed invocations.
54+ */
3255 final Duration increment ;
3356
34- // 60 seconds by default
57+ /**
58+ * Default increment: 60 seconds.
59+ */
3560 final public static Duration DEFAULT_INCREMENT = Duration .buildBySeconds (60 );
3661
62+ /**
63+ * Creates a gate with {@link #DEFAULT_INCREMENT}.
64+ */
3765 public SimpleInvocationGate () {
3866 this (DEFAULT_INCREMENT );
3967 }
4068
69+ /**
70+ * Creates a gate that allows at most one successful passage per
71+ * {@code anIncrement} period.
72+ *
73+ * @param anIncrement duration between allowed invocations; must not be
74+ * {@code null}
75+ */
4176 public SimpleInvocationGate (Duration anIncrement ) {
4277 this .increment = anIncrement ;
4378 }
4479
80+ /**
81+ * Returns {@code true} if the caller should skip further work; {@code false}
82+ * if this call is allowed to proceed.
83+ * <p>
84+ * If {@code currentTime} is {@link InvocationGate#TIME_UNAVAILABLE}
85+ * ({@code -1}), this method returns {@code false} so the caller can still
86+ * perform the work when the clock is unavailable.
87+ * </p>
88+ * <p>
89+ * Otherwise, when {@code currentTime} is strictly before the next allowed
90+ * time, the method returns {@code true} (too soon). When
91+ * {@code currentTime} has reached the next allowed time, this thread tries
92+ * to advance that time by {@link #increment}. On success it returns
93+ * {@code false} (proceed); if another thread already advanced it, this
94+ * thread returns {@code true} so that only one passage per interval is
95+ * granted.
96+ * </p>
97+ *
98+ * @param currentTime current time in milliseconds, or
99+ * {@link InvocationGate#TIME_UNAVAILABLE} if unknown
100+ * @return {@code true} if further work should be skipped; {@code false} if
101+ * the caller may proceed
102+ */
45103 @ Override
46104 public boolean isTooSoon (long currentTime ) {
47105 if (currentTime == -1 )
@@ -60,20 +118,4 @@ public boolean isTooSoon(long currentTime) {
60118 }
61119
62120 }
63-
64-
65121}
66-
67- // private final boolean isTooSoonSynchronized(long currentTime) {
68- // if (currentTime == -1)
69- // return false;
70- //
71- // synchronized (this) {
72- // if (currentTime >= next) {
73- // next = currentTime + increment;
74- // return false;
75- // }
76- // }
77- // return true;
78- // }
79-
0 commit comments