<commit_before>package coconut.ui.tools;

import tink.state.*;
import tink.state.Observable;

using tink.CoreApi;

class Slot<T> implements ObservableObject<T> {
  
  var data:Observable<T>;
  var last:Pair<T, FutureTrigger<Noise>>;
  var link:CallbackLink;
  var owner:{};
  var compare:T->T->Bool;
  var cache = new ViewCache();//TODO: maybe having every slot cached is a bit overkill

  public var value(get, never):T;
    inline function get_value()
      return observe().value;

  public function new(owner, ?compare) {
    this.owner = owner;
    this.compare = switch compare {
      case null: function (a, b) return a == b;
      case v: v;
    }
  }
  
  public function poll() {
    if (last == null) {
      if (data == null) {
        last = new Pair(null, Future.trigger());
      }
      else {
        var m = measure();
        last = new Pair(m.value, Future.trigger());
        link = m.becameInvalid.handle(last.b.trigger);
      }
      last.b.handle(function () last = null);
    }
    return new Measurement(last.a, last.b);
  }

  function measure()
    return cache.cached(data.measure);

  public function observe():Observable<T>
    return this;

  public function setData(data:Observable<T>) {
    this.data = data;
    if (last != null) {
      link.dissolve();
      if (data != null) {
        var m = Observable.untracked(measure);
        
        if (compare(m.value, last.a))<commit_msg>Fix cache schizophrenia.<commit_after>package coconut.ui.tools;

import tink.state.*;
import tink.state.Observable;

using tink.CoreApi;

class Slot<T> implements ObservableObject<T> {
  
  var data:Observable<T>;
  var last:Pair<T, FutureTrigger<Noise>>;
  var link:CallbackLink;
  var owner:{};
  var compare:T->T->Bool;
  var cache = new ViewCache();//TODO: maybe having every slot cached is a bit overkill

  public var value(get, never):T;
    inline function get_value()
      return observe().value;

  public function new(owner, ?compare) {
    this.owner = owner;
    this.compare = switch compare {
      case null: function (a, b) return a == b;
      case v: v;
    }
  }

  public function isValid()
    return data != null && (data:ObservableObject<T>).isValid();
  
  public function poll() {
    if (last == null) {
      if (data == null) {
        last = new Pair(null, Future.trigger());
      }
      else {
        var m = measure();
        last = new Pair(m.value, Future.trigger());
        link = m.becameInvalid.handle(last.b.trigger);
      }
      last.b.handle(function () last = null);
    }
    return new Measurement(last.a, last.b);
  }

  function measure()
    return 
      if (isValid()) data.measure();
      else cache.cached(data.measure);

  public function observe():Observable<T>
    return this;

  public function setData(data:Observable<T>) {
    this.data = data;
    if (last != null) {
      link.dissolve();
      if (data != null) {
        var m = Observable.untracked(measure);
        
        if (compare(m.value, last.a))
{'fraction_non_alphanumeric': 0.136, 'fraction_numerical': 0.0, 'mean_word_length': 2.6822085889570553, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4376417', 'n_tokens_mistral': 974, 'n_tokens_neox': 944, 'n_words': 256}