• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ben-manes / caffeine / #5707

02 Aug 2026 12:45AM UTC coverage: 0.106% (-99.9%) from 100.0%
#5707

push

github

ben-manes
fix wikibench trace reader after overly strict audit fixes

0 of 4235 branches covered (0.0%)

9 of 8528 relevant lines covered (0.11%)

0.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/caffeine/src/main/java/com/github/benmanes/caffeine/cache/Pacer.java
1
/*
2
 * Copyright 2019 Ben Manes. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package com.github.benmanes.caffeine.cache;
17

18
import static com.github.benmanes.caffeine.cache.Caffeine.ceilingPowerOfTwo;
19
import static java.lang.invoke.ConstantBootstraps.fieldVarHandle;
20
import static java.util.Objects.requireNonNull;
21

22
import java.lang.invoke.MethodHandles;
23
import java.lang.invoke.VarHandle;
24
import java.util.concurrent.Executor;
25
import java.util.concurrent.Future;
26
import java.util.concurrent.TimeUnit;
27

28
import org.jspecify.annotations.Nullable;
29

30
/**
31
 * A pacing scheduler that prevents executions from happening too frequently. Only one task may be
32
 * scheduled at any given time, the earliest pending task takes precedence, and the delay may be
33
 * increased if it is less than a tolerance threshold.
34
 *
35
 * @author ben.manes@gmail.com (Ben Manes)
36
 */
37
final class Pacer {
38
  static final long TOLERANCE = ceilingPowerOfTwo(TimeUnit.SECONDS.toNanos(1)); // 1.07s
×
39
  static final VarHandle FUTURE = fieldVarHandle(MethodHandles.lookup(),
×
40
      "future", VarHandle.class, Pacer.class, Future.class);
41

42
  final Scheduler scheduler;
43

44
  long nextFireTime;
45
  @Nullable Future<?> future;
46

47
  Pacer(Scheduler scheduler) {
×
48
    this.scheduler = requireNonNull(scheduler);
×
49
  }
×
50

51
  /** Schedules the task, pacing the execution if occurring too often. */
52
  public void schedule(Executor executor, Runnable command, long now, long delay) {
53
    long scheduleAt = (now + delay);
×
54

55
    if (future == null) {
×
56
      // short-circuit an immediate scheduler causing an infinite loop during initialization
57
      if (nextFireTime != 0L) {
×
58
        return;
×
59
      }
60
    } else {
61
      // Skip if a pending fire is still soon enough; otherwise cancel the future being replaced
62
      if (((nextFireTime - now) > 0L) && !future.isDone() && maySkip(scheduleAt)) {
×
63
        return;
×
64
      }
65
      future.cancel(/* mayInterruptIfRunning= */ false);
×
66
    }
67
    long actualDelay = calculateSchedule(now, delay, scheduleAt);
×
68
    var f = scheduler.schedule(executor, command, actualDelay, TimeUnit.NANOSECONDS);
×
69
    FUTURE.setRelease(this, f);
×
70
  }
×
71

72
  /** Attempts to cancel execution of the scheduled task, if present. */
73
  public void cancel() {
74
    if (future != null) {
×
75
      future.cancel(/* mayInterruptIfRunning= */ false);
×
76
      nextFireTime = 0L;
×
77
      FUTURE.setRelease(this, null);
×
78
    }
79
  }
×
80

81
  /** Returns if a task is scheduled to run. */
82
  public boolean isScheduled() {
83
    var f = (Future<?>) FUTURE.getAcquire(this);
×
84
    return (f != null) && !f.isDone();
×
85
  }
86

87
  /**
88
   * Returns if the current fire time is sooner, or if it is later and within the tolerance limit.
89
   */
90
  boolean maySkip(long scheduleAt) {
91
    long delta = (scheduleAt - nextFireTime);
×
92
    return (delta >= -TOLERANCE);
×
93
  }
94

95
  /** Returns the delay and sets the next fire time, avoiding the 0L unscheduled sentinel. */
96
  long calculateSchedule(long now, long delay, long scheduleAt) {
97
    if (delay <= TOLERANCE) {
×
98
      // Use a minimum delay if close to now
99
      nextFireTime = (now + TOLERANCE);
×
100
      if (nextFireTime == 0L) {
×
101
        nextFireTime = 1L;
×
102
      }
103
      return TOLERANCE;
×
104
    }
105
    nextFireTime = (scheduleAt == 0L) ? 1L : scheduleAt;
×
106
    return delay;
×
107
  }
108
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc