DataFetcher.java

com.mojang.realmsclient.gui.task.DataFetcher

信息

  • 全限定名:com.mojang.realmsclient.gui.task.DataFetcher
  • 类型:public class
  • 包:com.mojang.realmsclient.gui.task
  • 源码路径:src/main/java/com/mojang/realmsclient/gui/task/DataFetcher.java
  • 起始行号:L21
  • 职责:

    TODO

字段/常量

  • LOGGER

    • 类型: Logger
    • 修饰符: private static final
    • 源码定位: L22
    • 说明:

      TODO

  • executor

    • 类型: Executor
    • 修饰符: private final
    • 源码定位: L23
    • 说明:

      TODO

  • resolution

    • 类型: TimeUnit
    • 修饰符: private final
    • 源码定位: L24
    • 说明:

      TODO

  • timeSource

    • 类型: TimeSource
    • 修饰符: private final
    • 源码定位: L25
    • 说明:

      TODO

内部类/嵌套类型

  • com.mojang.realmsclient.gui.task.DataFetcher.ComputationResult

    • 类型: record
    • 修饰符: private
    • 源码定位: L47
    • 说明:

      TODO

  • com.mojang.realmsclient.gui.task.DataFetcher.SubscribedTask

    • 类型: class
    • 修饰符: private
    • 源码定位: L51
    • 说明:

      TODO

  • com.mojang.realmsclient.gui.task.DataFetcher.Subscription

    • 类型: class
    • 修饰符: public
    • 源码定位: L92
    • 说明:

      TODO

  • com.mojang.realmsclient.gui.task.DataFetcher.SuccessfulComputationResult

    • 类型: record
    • 修饰符: private
    • 源码定位: L127
    • 说明:

      TODO

  • com.mojang.realmsclient.gui.task.DataFetcher.Task

    • 类型: class
    • 修饰符: public
    • 源码定位: L131
    • 说明:

      TODO

构造器

public DataFetcher(Executor executor, TimeUnit resolution, TimeSource timeSource) @ L27

  • 构造器名:DataFetcher
  • 源码定位:L27
  • 修饰符:public

参数:

  • executor: Executor
  • resolution: TimeUnit
  • timeSource: TimeSource

说明:

TODO

方法

下面的方法块按源码顺序生成。

public <T> DataFetcher.Task<T> createTask(String id, Callable<T> updater, Duration period, RepeatedDelayStrategy repeatStrategy) @ L33

  • 方法名:createTask
  • 源码定位:L33
  • 返回类型: DataFetcher.Task
  • 修饰符:public

参数:

  • id: String
  • updater: Callable
  • period: Duration
  • repeatStrategy: RepeatedDelayStrategy

说明:

TODO

public DataFetcher.Subscription createSubscription() @ L42

  • 方法名:createSubscription
  • 源码定位:L42
  • 返回类型:DataFetcher.Subscription
  • 修饰符:public

参数:

说明:

TODO

代码

@OnlyIn(Dist.CLIENT)
public class DataFetcher {
    private static final Logger LOGGER = LogUtils.getLogger();
    private final Executor executor;
    private final TimeUnit resolution;
    private final TimeSource timeSource;
 
    public DataFetcher(Executor executor, TimeUnit resolution, TimeSource timeSource) {
        this.executor = executor;
        this.resolution = resolution;
        this.timeSource = timeSource;
    }
 
    public <T> DataFetcher.Task<T> createTask(String id, Callable<T> updater, Duration period, RepeatedDelayStrategy repeatStrategy) {
        long periodInUnit = this.resolution.convert(period);
        if (periodInUnit == 0L) {
            throw new IllegalArgumentException("Period of " + period + " too short for selected resolution of " + this.resolution);
        } else {
            return new DataFetcher.Task<>(id, updater, periodInUnit, repeatStrategy);
        }
    }
 
    public DataFetcher.Subscription createSubscription() {
        return new DataFetcher.Subscription();
    }
 
    @OnlyIn(Dist.CLIENT)
    private record ComputationResult<T>(Either<T, Exception> value, long time) {
    }
 
    @OnlyIn(Dist.CLIENT)
    private class SubscribedTask<T> {
        private final DataFetcher.Task<T> task;
        private final Consumer<T> output;
        private long lastCheckTime;
 
        private SubscribedTask(DataFetcher.Task<T> task, Consumer<T> output) {
            Objects.requireNonNull(DataFetcher.this);
            super();
            this.lastCheckTime = -1L;
            this.task = task;
            this.output = output;
        }
 
        private void update(long currentTime) {
            this.task.updateIfNeeded(currentTime);
            this.runCallbackIfNeeded();
        }
 
        private void runCallbackIfNeeded() {
            DataFetcher.SuccessfulComputationResult<T> lastResult = this.task.lastResult;
            if (lastResult != null && this.lastCheckTime < lastResult.time) {
                this.output.accept(lastResult.value);
                this.lastCheckTime = lastResult.time;
            }
        }
 
        private void runCallback() {
            DataFetcher.SuccessfulComputationResult<T> lastResult = this.task.lastResult;
            if (lastResult != null) {
                this.output.accept(lastResult.value);
                this.lastCheckTime = lastResult.time;
            }
        }
 
        private void reset() {
            this.task.reset();
            this.lastCheckTime = -1L;
        }
    }
 
    @OnlyIn(Dist.CLIENT)
    public class Subscription {
        private final List<DataFetcher.SubscribedTask<?>> subscriptions;
 
        public Subscription() {
            Objects.requireNonNull(DataFetcher.this);
            super();
            this.subscriptions = new ArrayList<>();
        }
 
        public <T> void subscribe(DataFetcher.Task<T> task, Consumer<T> output) {
            DataFetcher.SubscribedTask<T> subscription = DataFetcher.this.new SubscribedTask<>(task, output);
            this.subscriptions.add(subscription);
            subscription.runCallbackIfNeeded();
        }
 
        public void forceUpdate() {
            for (DataFetcher.SubscribedTask<?> subscription : this.subscriptions) {
                subscription.runCallback();
            }
        }
 
        public void tick() {
            for (DataFetcher.SubscribedTask<?> subscription : this.subscriptions) {
                subscription.update(DataFetcher.this.timeSource.get(DataFetcher.this.resolution));
            }
        }
 
        public void reset() {
            for (DataFetcher.SubscribedTask<?> subscription : this.subscriptions) {
                subscription.reset();
            }
        }
    }
 
    @OnlyIn(Dist.CLIENT)
    private record SuccessfulComputationResult<T>(T value, long time) {
    }
 
    @OnlyIn(Dist.CLIENT)
    public class Task<T> {
        private final String id;
        private final Callable<T> updater;
        private final long period;
        private final RepeatedDelayStrategy repeatStrategy;
        private @Nullable CompletableFuture<DataFetcher.ComputationResult<T>> pendingTask;
        private DataFetcher.@Nullable SuccessfulComputationResult<T> lastResult;
        private long nextUpdate;
 
        private Task(String id, Callable<T> updater, long period, RepeatedDelayStrategy repeatStrategy) {
            Objects.requireNonNull(DataFetcher.this);
            super();
            this.nextUpdate = -1L;
            this.id = id;
            this.updater = updater;
            this.period = period;
            this.repeatStrategy = repeatStrategy;
        }
 
        private void updateIfNeeded(long currentTime) {
            if (this.pendingTask != null) {
                DataFetcher.ComputationResult<T> result = this.pendingTask.getNow(null);
                if (result == null) {
                    return;
                }
 
                this.pendingTask = null;
                long completionTime = result.time;
                result.value().ifLeft(value -> {
                    this.lastResult = new DataFetcher.SuccessfulComputationResult<>((T)value, completionTime);
                    this.nextUpdate = completionTime + this.period * this.repeatStrategy.delayCyclesAfterSuccess();
                }).ifRight(e -> {
                    long cycles = this.repeatStrategy.delayCyclesAfterFailure();
                    DataFetcher.LOGGER.warn("Failed to process task {}, will repeat after {} cycles", this.id, cycles, e);
                    this.nextUpdate = completionTime + this.period * cycles;
                });
            }
 
            if (this.nextUpdate <= currentTime) {
                this.pendingTask = CompletableFuture.supplyAsync(() -> {
                    try {
                        T resultx = this.updater.call();
                        long completionTimex = DataFetcher.this.timeSource.get(DataFetcher.this.resolution);
                        return new DataFetcher.ComputationResult<>(Either.left(resultx), completionTimex);
                    } catch (Exception var4x) {
                        long completionTimex = DataFetcher.this.timeSource.get(DataFetcher.this.resolution);
                        return new DataFetcher.ComputationResult<>(Either.right(var4x), completionTimex);
                    }
                }, DataFetcher.this.executor);
            }
        }
 
        public void reset() {
            this.pendingTask = null;
            this.lastResult = null;
            this.nextUpdate = -1L;
        }
    }
}

引用的其他类