September 4th, 2014, 11:14 am
Thanks for the post. I have avoided a virtual clock up to this point - thinking that I might be able to get away with it as I am not trying to emulate another system. After reading this I am not sure I can. At the moment the interrupt would be raised and then processed, and hence might lead to a condition of no processing possible due to holding down a key. I think I do need to write an Interrupt queue (FIFO) as the interrupts raised will be asynchronous from when they are processed.Mmm - food for thought....QuoteOriginally posted by: outrunI once wrote a realistic even simulator using a "priority queue". A priority queue is a list of {timestamp, action/event} pairs, sorted on timestamp. The action is eg a function pointer. The simulator pops the first action from the front of the queue and executes that action. It's extremely powerful, e.g. we implemented an virtual internal clock (which the simulator could use to time itself in virtual time!) by simply have an action that would insert a clock event 1 second further in the queue.before processing the clock_event():1: 0:00:20.402, clock_event()2: 0:00:20.802, do_somethingX()3: 0:00:21.356, do_somethingY()4: 0:00:21.913, do_somethingZ()after processing the clock_event():2: 0:00:20.802, do_somethingX()3: 0:00:21.356, do_somethingY()1: 0:00:21.402, clock_event() <-- newly inserted clock event4: 0:00:21.913, do_somethingZ()Another thing you can do is to measure the duration of tasks in the main event handler loop and let various hardware components run in a simulated parallel. Every task you pop of the queue get's timed, and when finished you compute the virtual time that would finish and insert a future event back into the queue (just like with the clock). After completion the next event with highest time priority in the queue might be moved to a simulated io bufferSuppose the event queue looks like this at 0:00:20.402 (virtual time)1: 0:00:20.402, draw_sceen()2: 0:00:20.800, key_press_Q()3: 0:00:20.900, key_press_W()4: 0:00:21.000, key_press_E()5: 0:00:21.100, key_press_R()6: 0:00:21.200, key_press_T()7: 0:00:21.300, key_press_Y()..now suppose you measure with a real clock that draw_screen takes 0.5 seconds. You could insert a draw_complete() event at 0:00:20.902 into the queue which might pop the instruction pointer. You will then know that you first have to process the Q and W keypress events (move then to a keyboard buffer?) before you can pop the instruction pointer from the stack.