Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

113
LINES

< > BotCompany Repo | #1025193 // FlexibleRateTimer

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (10945L/62K).

// only executes one action at once. Keeps track of
// optimal timestamps though, so actions may pile up.
// (call pileUp(false) to change.)
// Frequency may be set to 0 or even very close to zero
// (both values effectively stop the timer).
// persists frequency only
// TODO: Events stacked up after coming out of hibernation? (Windows)
sclass FlexibleRateTimer implements AutoCloseable {
  double hertz;
  transient Runnable action;
  transient double timestamp;
  transient DoLater doLater;
  transient new Flag started;
  transient volatile bool disposed;
  transient long delay; // how much are we currently delayed
  transient L<Runnable> onFrequencyChanged;
  transient bool verbose;
  
  settable ISleeper sleeper = defaultSleeper();
  
  settable bool pileUp = true;

  // below actualMinHertz, we stop the timer
  static double minHertz = 0, actualMinHertz = 1e-8, maxHertz = 1000;
  
  *() {}
  *(double *hertz) {}
  *(double *hertz, Runnable *action) {}
  
  void start {
    if (!started.raise()) ret;
    if (verbose) print("Starting timer with " + hertz + " Hz");
    vmBus_timerStarted(this);
    _kaboom();
  }
  
  // This method reschedules the next timer firing
  // (i.e. disposes of the internal timer and optionally
  // creates a new one).
  synchronized void _kaboom() pcall {
    if (verbose) print(disposed ? "Timer kaboom (disposed)" : "Timer kaboom");
    if (disposed) ret;
    dispose doLater;
    if (hertz <= actualMinHertz) ret with timestamp = 0;
    if (timestamp == 0) timestamp = sysNow();
    timestamp += 1000/getFrequency();
    if (!pileUp)
      timestamp = max(sysNow(), timestamp);
    long _timestamp = lround(timestamp);
    doLater = new DoLater(_timestamp, r {
      delay = sysNow()-_timestamp;
      if (verbose) print("Timer action");
      pcallF(action);
      _kaboom();
    });
    doLater.sleeper(sleeper);
    if (verbose) print("Timer scheduled for: " + (_timestamp-sysNow()));
    doLater.enable();
  }
  
  void cancel { close(); }
  
  public synchronized void close {
    set disposed;
    dispose doLater;
  }
  
  void setRunnableAndStart(Runnable action) {
    this.action = action;
    start();
  }
  
  // takes effect _after_ next trigger
  void setFrequency(double hertz) {
    synchronized(this) {
      if (disposed) ret;
      hertz = clamp(hertz, minHertz, maxHertz);
      if (hertz == this.hertz) ret;
      this.hertz = hertz;
    }
    pcallFAll(onFrequencyChanged);
  }
  
  // reschedule next action
  void setFrequencyImmediately(double hertz) {
    synchronized(this) {
      if (disposed) ret;
      hertz = clamp(hertz, minHertz, maxHertz);
      if (hertz == this.hertz) ret;
      double oldHertz = this.hertz;
      this.hertz = hertz;
      if (!started.isUp()) ret;
      if (verbose) print("Timer setFreq doLater=" + doLater);
      bool b = doLater == null || doLater.cancel();
      if (verbose) print("Timer cancel result: " + b + " (" + oldHertz + " -> " + hertz + ")");
      timestamp = sysNow();
      if (b) _kaboom();
    }
    pcallFAll(onFrequencyChanged);
  }
  
  synchronized double getFrequency() { ret hertz; }
  
  long currentDelay() { ret delay; }
  
  synchronized void onFrequencyChanged(Runnable r) {
    onFrequencyChanged = addOrCreate(onFrequencyChanged,  r);
  }
  
  void onFrequencyChangedAndNow(Runnable r) {
    onFrequencyChanged(runAndReturn(r));
  }
}

download  show line numbers  debug dex  old transpilations   

Travelled to 7 computer(s): bhatertpkbcr, ekrmjmnbrukm, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1025193
Snippet name: FlexibleRateTimer
Eternal ID of this version: #1025193/32
Text MD5: 386d9381848552d01bb333629cd72473
Transpilation MD5: 4d120ce7ca0886eebec5c5854be65252
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-11-28 20:55:58
Source code size: 3487 bytes / 113 lines
Pitched / IR pitched: No / No
Views / Downloads: 415 / 1042
Version history: 31 change(s)
Referenced in: #1034167 - Standard Classes + Interfaces (LIVE, continuation of #1003674)