sclass ReliableSingleThread_Multi<A> {
  IVF1<A> processObject;
  int delay; // delay before changes are processed
  
  *(IVF1<A> *processObject) {}
  *(int *delay, IVF1<A> *processObject) {}
  *(int *delay, IVF1<A> *processObject, F0<AutoCloseable> enter) { setEnter(enter); }
  
  // internal
  Set<A> changedObjects = synchroSet();
  ReliableSingleThread rst = new(r process);

  // notify of change in object
  void add(A a) {
    if (changedObjects.add(a))
      rst.trigger();
  }
  
  void addAll(Iterable<A> l) {
    fOr ping (A a : l) add(a);
  }
  
  private void process {
    sleep(delay);
    for ping (A object : syncCloneAndClearList(changedObjects))
      pcallF(processObject, object);
  }
  
  void setEnter(F0<AutoCloseable> enter) {
    rst.enter = enter;
  }
}