The problem with R/S sometimes being ignored is pretty frustrating, but it goes back to poor design of the iPhone's event handling API. Some background:
The Free42 core was designed to be single-threaded; it has to be, in order to work on operating systems without thread support, like PalmOS.
In a single-threaded calculator simulator, you have to somehow be able to execute programs, while still keeping the UI responsive -- it should still respond to mouse and keyboard events, repaint requests, etc. Most environments support this by providing a function that lets a program poll the event queue without actually invoking any event handlers: PeekMessage() in Win32, XtAppPending() in the X toolkit, g_main_context_pending() in GTK, EvtEventAvail() in PalmOS.
While executing a program, Free42 simply calls the appropriate event queue polling function after finishing each program line; polling the event queue is a very cheap operation, so programs can run with little overhead, and still respond very quickly to events.
When Free42 detects that an event is pending, it returns control to the application framework. In order to be able to resume program execution once the application framework is done handling events, Free42 needs some way to schedule a function call to take place when the framework is otherwise idle; in Win32 and PalmOS, this is easy because the main event loop is part of the application itself, so it is a simple matter of inserting the call to run the program there; in more modern, callback-based environments like the X toolkit and GTK, you can use XtAppAddWorkProc() and g_idle_add(), respectively.
The iPhone makes this type of programming style difficult to impossible. First, there is no facility for peeking ahead in the event queue, so a single-threaded program has no choice but to drop out of the program execution loop at regular intervals and return to the application framework.
But it gets worse: in order for program execution to resume once the application framework has finished handling events, Free42 again needs some mechanism to schedule execution, but the only available mechanism is performSelectorOnMainThread, which will execute its target at the earliest opportunity, instead of being deferred until the event queue is empty. There is no mechanism for scheduling any activity to take place if and only if there are no pending events.
Byron has so far tried to work around the iPhone API limitations using straightforward hacks like inserting small delays in which the event queue can be emptied; in the latest code, this is working pretty well; you really have to try hard to get it into a state where the keyboard becomes unresponsive, and even when that does happen, it is easier to get out of that state than it was before. Still, the situation is not ideal, and stupid programs like LBL 00 BEEP GTO 00 can still cause the problem to occur fairly easily.
In my version, I chose a different approach, using a secondary thread for running programs, while the main thread stays in control of the UI and thus never becomes unresponsive. This has proven to be robust, but the code is very hairy, and the overhead from thread-to-thread context switching is considerable.
Byron has indicated to me that iPhone OS 3.0 has an improved event handling API, and that he thinks we'll be able to do Free42 "right" with it. I haven't studied the 3.0 APIs yet myself, so I can't confirm this, but, assuming the shortcomings of the existing API have indeed been remedied, I'd expect a point release to take advantage very quickly.
Of course "very quickly" can mean "one day for us to make the code changes, then two weeks or more of being stuck in the iTunes App Store submission queue". Such is life in iPhone developer land.
- Thomas