On Thu, Aug 25, 2011 at 01:01:10PM -0400, Dimitry Golubovsky wrote:
Hi,
[this is not really about VM alone, but rather how image and VM interact - hence posting to multiple lists]
Dimitry, Thank you for this detailed and helpful explanation. I hope it generates some follow up discussion. Dave
In the process of porting Cog to Android, I observed the following pattern. If a scrollbar's "up" or "down" button is held pressed (prolonged tap on a button) for few seconds, the VM freezes, and gets killed by Android. Digging down the code got me to the WorldState>>interCyclePause: method. When there are morphs requesting stepping by shorter than certain time interval, the process responsibke for running step methods keeps looping without giving up to lower priority processes (and the host OS). ScrollBar seems to decrease the stepping interval over time to simulate accelerated scrolling.
In order to port Cog to Android, I turned it into an event-driven VM based on ideas found in [1]. The same was done by Andreas for his earlier Classic VM port. My approach is a bit different such as the longjmp call is made as part of the relinquishProcessor primitive. Such primitive is called only from the lowest priority (idle) process which only can run when there are no external events to deal with. The event-driven VM needs to exit from the interpreter to the host process in order to obtain any input events. Thus, non-interrupted polling just deadlocks the interpreter as it cannot exit to the host process to get more events, yet keeps polling for them.
The serverMode flag [2] (aka Mantis #6581) came to rescue. With such flag set to true, polling for events always yields CPU for 50ms (which in the Android case is meaningless anyway: I would not give the VM idle timer more often than 10 times per sec, so 50ms granularity is just not handleable). Anyway this does the trick as the lowest priority process gets its CPU time, and exits the interpreter to the host process. With serverMode = true I can tap a scroller button as long as I want, and even the text cursor in a workspace keeps blinking which means that stepping works and VM is alive. BTW in Android, the interpreter will be called as soon as any user action is intercepted, so responsiveness is not degraded regardless of the delay introduced by serverMode.
I have found at least one place (this is in PharoCore) where serverMode is not honored: PolygonMorph class >> fromHand: (this method creates a polygon drawn by the mouse)
This method has code pieces (repeating multiple times btw - why is it not a separate method?)
[Sensor anyButtonPressed] whileFalse: [self currentWorld displayWorldSafely; runStepMethods].
which is clearly grabbing the event sensor to the polygon morph while keeping other morphs stepped, so the VM does not seem dead entirely. In my case though executing PolygonMorph fromHand: defaultHand freezes the VM immediately as this is uninterrupted polling again.
While I'll try to experiment with inserting interCyclePause somewhere in these loops, there are broader questions on how event polling is done these days:
1. Are there other morphs in packages not included in PharoCore where event grabbing is done such way?
1a. Is this possible in general to have such functionality properly embedded in WorldState instead of having it in a morph itself, if event grabbing is needed?
2. Are there images in active development (other than PharoCore, and Squeak) where event polling is done without an option to relinquish processor?
In fact, this VM freezing on stepping morphs was a big issue, and it mainly kept me from moving towards the public release. Now that it seems to be solved (unless there is a flaw in my logic above) it takes me closer to finishing the Cog for Android port.
Thanks.
------------------------------------------ [1] http://lists.squeakfoundation.org/pipermail/vm-dev/2009-November/003385.html [2] http://bugs.squeak.org/view.php?id=6581
-- Dimitry Golubovsky
Anywhere on the Web