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) |