Libraryless. Click here for Pure Java version (10945L/62K).
1 | // only executes one action at once. Keeps track of |
2 | // optimal timestamps though, so actions may pile up. |
3 | // (call pileUp(false) to change.) |
4 | // Frequency may be set to 0 or even very close to zero |
5 | // (both values effectively stop the timer). |
6 | // persists frequency only |
7 | // TODO: Events stacked up after coming out of hibernation? (Windows) |
8 | sclass FlexibleRateTimer implements AutoCloseable { |
9 | double hertz; |
10 | transient Runnable action; |
11 | transient double timestamp; |
12 | transient DoLater doLater; |
13 | transient new Flag started; |
14 | transient volatile bool disposed; |
15 | transient long delay; // how much are we currently delayed |
16 | transient L<Runnable> onFrequencyChanged; |
17 | transient bool verbose; |
18 | |
19 | settable ISleeper sleeper = defaultSleeper(); |
20 | |
21 | settable bool pileUp = true; |
22 | |
23 | // below actualMinHertz, we stop the timer |
24 | static double minHertz = 0, actualMinHertz = 1e-8, maxHertz = 1000; |
25 | |
26 | *() {} |
27 | *(double *hertz) {} |
28 | *(double *hertz, Runnable *action) {} |
29 | |
30 | void start { |
31 | if (!started.raise()) ret; |
32 | if (verbose) print("Starting timer with " + hertz + " Hz"); |
33 | vmBus_timerStarted(this); |
34 | _kaboom(); |
35 | } |
36 | |
37 | // This method reschedules the next timer firing |
38 | // (i.e. disposes of the internal timer and optionally |
39 | // creates a new one). |
40 | synchronized void _kaboom() pcall { |
41 | if (verbose) print(disposed ? "Timer kaboom (disposed)" : "Timer kaboom"); |
42 | if (disposed) ret; |
43 | dispose doLater; |
44 | if (hertz <= actualMinHertz) ret with timestamp = 0; |
45 | if (timestamp == 0) timestamp = sysNow(); |
46 | timestamp += 1000/getFrequency(); |
47 | if (!pileUp) |
48 | timestamp = max(sysNow(), timestamp); |
49 | long _timestamp = lround(timestamp); |
50 | doLater = new DoLater(_timestamp, r { |
51 | delay = sysNow()-_timestamp; |
52 | if (verbose) print("Timer action"); |
53 | pcallF(action); |
54 | _kaboom(); |
55 | }); |
56 | doLater.sleeper(sleeper); |
57 | if (verbose) print("Timer scheduled for: " + (_timestamp-sysNow())); |
58 | doLater.enable(); |
59 | } |
60 | |
61 | void cancel { close(); } |
62 | |
63 | public synchronized void close { |
64 | set disposed; |
65 | dispose doLater; |
66 | } |
67 | |
68 | void setRunnableAndStart(Runnable action) { |
69 | this.action = action; |
70 | start(); |
71 | } |
72 | |
73 | // takes effect _after_ next trigger |
74 | void setFrequency(double hertz) { |
75 | synchronized(this) { |
76 | if (disposed) ret; |
77 | hertz = clamp(hertz, minHertz, maxHertz); |
78 | if (hertz == this.hertz) ret; |
79 | this.hertz = hertz; |
80 | } |
81 | pcallFAll(onFrequencyChanged); |
82 | } |
83 | |
84 | // reschedule next action |
85 | void setFrequencyImmediately(double hertz) { |
86 | synchronized(this) { |
87 | if (disposed) ret; |
88 | hertz = clamp(hertz, minHertz, maxHertz); |
89 | if (hertz == this.hertz) ret; |
90 | double oldHertz = this.hertz; |
91 | this.hertz = hertz; |
92 | if (!started.isUp()) ret; |
93 | if (verbose) print("Timer setFreq doLater=" + doLater); |
94 | bool b = doLater == null || doLater.cancel(); |
95 | if (verbose) print("Timer cancel result: " + b + " (" + oldHertz + " -> " + hertz + ")"); |
96 | timestamp = sysNow(); |
97 | if (b) _kaboom(); |
98 | } |
99 | pcallFAll(onFrequencyChanged); |
100 | } |
101 | |
102 | synchronized double getFrequency() { ret hertz; } |
103 | |
104 | long currentDelay() { ret delay; } |
105 | |
106 | synchronized void onFrequencyChanged(Runnable r) { |
107 | onFrequencyChanged = addOrCreate(onFrequencyChanged, r); |
108 | } |
109 | |
110 | void onFrequencyChangedAndNow(Runnable r) { |
111 | onFrequencyChanged(runAndReturn(r)); |
112 | } |
113 | } |
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: | 414 / 1042 |
Version history: | 31 change(s) |
Referenced in: | [show references] |