I've got a nice clocking package built into Typhon (
http://typhon.egrsoftware.com/) that will be released when Auriga3D hits the net in December.
The clocking mechanism I created allows you to decouple scheduling on a single thread. In effect it is like psuedo-multitasking. If the clock is running at 60hz subdivisions of 30hz, 20hz, 15hz, 12hz, 10hz, and 5hz are available, etc. The clock is callback oriented so any "clockable" can be switched to a different subdivision dynamically.
Here are some notes and commentary from past presentations on it...
---------------------------------
Why have a scheduler at all?
Clock classification:
"Subdivided do while thread yield"
-Cycle of 12 due to common factors
and equal prime number spread.
-Other subdivision patterns are possible.
A scheduler is necessary for three main reasons. It is required for active rendering for graphics display, to run reoccurring events in Typhon, & to execute code off of the AWT Event Queue that is used by the AWT and Swing graphics APIs.
A scheduler or some way to execute code from GUI events off of the AWT queue is absolutely necessary for high performance Java applications. Most APIs that perform this task work with threads including Foxtrot and SwingWorker.
However, most real time applications (games/simulations) are designed for a single thread of execution.
With Typhon I take a different approach by having one main thread of execution that is driven by a subdivided do while thread yield scheduler.
Now, the "do while thread yield" part sounds a little suspicious as isn't that a spin wait? Well.. Yes and no... If no other processes need to CPU then Typhon will consume all of the CPU resources, but if any other threads or applications require some CPU time Typhon applications will immediately yield.
This way it is possible to find a balance between scheduling events in Typhon and giving enough CPU time to other applications without being greedy. In fact this system works great while running a respectably high load in other software while Typhon applications are running.
The following slide will present some pseudo-code for the subdivided scheduler I am currently using.
Next slide:
--------------------------------------
Method clockLoop:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| do { ticks += tickSleep; while (System.nanoTime() < ticks) Thread.yield(); switch(++subdivideTicks) { case SUB1: <handle add and remove> <handle pending clockable move events> <handle Subset 1 clockables> case SUB2: <handle Subset 2 clockables> case SUB3: <handle Subset 3 clockables> case SUB4: <handle Subset 4 clockables> case SUB5: <handle Subset 5 clockables> <handle abstract clockables 1> case SUB6: <handle Subset 6 clockables> case SUB7: <handle Subset 7 clockables> <handle pending clockable move events> <handle one time clockables> case SUB8: <handle Subset 8 clockables> case SUB9: <handle Subset 9 clockables> case SUB10: <handle Subset 10 clockables> case SUB11: <handle Subset 11 clockables> case SUB12: <handle Subset 12 clockables> subdivideTicks = -1 } while (clockLoopRunning) |