package org.kne.concurrent;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;

/**
 * 惰性计算器：只在输入变化且输出被需要时重算。
 * 
 * 使用场景：路由表重算、统计信息聚合、UI 数据更新等
 * 
 * @param <T> 输出类型
 */
public class LazyEvaluator<T> {

    private final Supplier<T> recomputeFn;       // 重算函数（可能较重）
    private final AtomicBoolean dirty = new AtomicBoolean(true); // true表示需要重算
    private volatile T cachedResult;            // 缓存结果（volatile保证可见性）

    /**
     * @param recomputeFn 当真正需要重算时，调用此函数生成新值
     */
    public LazyEvaluator(Supplier<T> recomputeFn) {
        this.recomputeFn = recomputeFn;
    }

    /**
     * 标记输入已变化（每次变化都调用）
     * CAS 保证多线程下只有一个线程真正置脏，避免无谓的竞争
     */
    public boolean  markDirty() {
        return dirty.compareAndSet(false, true);
    }

    /**
     * 获取当前值（如果 dirty 且被需要，则触发重算）
     * 这个方法由需要输出的地方（如 UI 线程、路由引擎）调用
     */
    public T get() {
        if (dirty.get()) {
            synchronized (this) {
                // double-check：防止多个线程同时进入重算
                if (dirty.get()) {
                    cachedResult = recomputeFn.get();
                    dirty.set(false);
                }
            }
        }
        return cachedResult;
    }

    /**
     * 获取当前缓存的值（不触发重算）
     * 适合那些“如果已经算好就直接用，否则也不强求”的场景
     */
    public T getCached() {
        return cachedResult;
    }

    /**
     * 当前是否需要重算
     */
    public boolean isDirty() {
        return dirty.get();
    }
}