System>>whenIdleSend:to:args: – Blessing or Curse?
Microsoft Windows has one thing in common with Smalltalk: It works by sending messages. A Windows message can also be “posted,” i.e., it is put at the end of the Windows message queue, and the sender doesn’t wait for a synchronous response. The idle queue in Cincom® ObjectStudio® classic was designed in part to mirror this activity in Windows. While the design as a whole is very useful and sometimes plain necessary, it can be overused.
In ObjectStudio classic, it was pretty standard to delay some action using System>>whenIdleSend:to:args:. The VM made sure that the message was executed after the current code was executed, but before ObjectStudio became “idle” It was also assumed that those messages were to be executed in the same order in which they were added to the queue. Since most applications never used multiple, native threads, the assumption was correct. Unfortunately with ObjectStudio 8 and the so called “Multi-Proc-UI,” these assumptions are not 100% correct any more.
ObjectStudio Forms that do not have any parents now run in their own process. Sub-forms and other forms that are related run in the same process context as their owner or parent. This allows us to update forms, even when other forms are blocked on primitives or longer-running SQL statements. To achieve that, each top-level form owns its own Window Manager and Event Queue. This design allows for better debugger support. The debugger stays inside its own process, controlling the debugee from the “outside”―not interfering with events as they happen. As soon as a form receives the WM_IDLE event, the code inside the queue is executed―one after the other. We will make sure that events are executed in the order in which they were put into the queue.
Alas, there is one big problem! Let’s assume, you want to send an asynch message to a ControllerItem or FormItem. In which Smalltalk process should the method be executed? Is it the calling process or the process that “owns” the specific item? For the next release, we’re looking at a change to GlobalDictionary>>whenIdleSend:to:withArguments: to make sure that when the receiver is a UI element with a window manager, the message is executed in that window manager’s process.
Since several processes now post to the same queue, there could be problems with the order of events. A process switch could happen at the “wrong” time, and code that was intended to run now is executed at a later point in time, where at other times, the process switch does not occur, which results in messages being posted too early. Now the events are literally “out of order.” Messages that were sent asynchronously to avoid one problem now cause another problem because the event is too early or too late.
The best way to deal with this kind of situation is to review the code and decide (on an individual basis) which process needs to execute this event.