
Description of non-blocking operations under the Wimp.
------------------------------------------------------


Requirement:

Hardware limited operations should not block Wimp activity.

When an application performs an operation which requires the interaction
between the computer and a slow piece of physical hardware, the desktop
should remain active. Such operations include file access and printing, but
may encompass other operations. Furthermore, it would be desirable that any
application would benefit from this, as opposed to applications written
specially to take advantage of this feature.


Method:

In outline, device drivers would have to be adjusted so that the device
interaction happened asynchronously, in 'background', whilst, in the
foreground a sleep vector was called. Calling the sleep vector would
indicate that a background process was happening which might take some time
and as parameters to the sleep vector routines would be sufficient
information to detect the completion of the background process. The default
action (outside the desktop) for this sleep vector would be to block,
waiting for the operation to complete. This would result in the same
characteristics as currently. Inside the desktop, on the other hand, the
Wimp would have replaced default sleep handler and placed the blocked task
into a special state until the operation completed. Modules shall be assumed
non-reenterant until proved otherwise, so that the operating system will
sleep attempts to perform SWIs to modules which have slept directly or
indirectly. This means that the operating system must maintain a chain of
SWIing to block all those modules if the bottom one sleeps.

Details:

i) For the UpCalling module

The sleeping module must have ensured that all data required for the
background operation is going to be available to it at all times whilst the
operation is taking place. In particular, this means that large data
transfers must transfer from RMA or a similar permanently resident area -
the SVC stack is not a permantently resident area. Sleep-reenterant modules
must declare themselves so, otherwise they will be blocked from reentering.

ii) For the OS

The OS must maintain a calling chain of SWIs so that on a sleep vector call
it can block entry to those modules which are not reenterant on that chain.
All SWIs which are all UpCall reenterant don't get blocked. Here are some
examples:

        DTP (application), rendering some text
SWI       Font_Paint (FontManager, non-reenterant)
SWI         OS_GBPB (FileSwitch, reenterant)
BL            FSEntry_GBPB (FileCore%ADFS, non-reenterant)
BL              ADFS low level disc op (ADFS, non-reenterant)   Sleep

Here, ADFS goes to sleep which causes the font manager to block and
FileSwitch to remain unblocked. Of course, FileSwitch must detect the sleep
and take appropriate blocking action on that filing system (indicated by a
bit in the filing system information word being clear indicating
non-reentrant). The Wimp would also receive the sleep and would place DTP in
the blocked state, having saved the SVC stack for restoration when the
operation has completed.

        DTP (application), printing
SWI       PDriver_GetRectangle (PDriver, non-reentrant)
SWI         OS_BPut (FileSwitch, reenterant)
BL            FSEntry_BPut (SystemDevs, reenterant)
SWI             OS_PrintChar (OS, non-reenterant)               Sleep

Here, the OS does the sleep call which causes PDriver and OS_PrintChar to
block, but leaves fileswitch and systemdevs unblocked.

The sleep vector will, like other vectors, have a series of routines
installed on it which are called in turn, and a handler which is called
after all the routines. It is expected that permanently resident objects
(modules) which just need to be informed of sleeping objects will claim
themselves onto the vector, whereas applications, which get swapped out,
will install themselves as the sleep handler. Also, applications which
install themselves as the sleep handler are expected to be well behaved and
to not block.

iii) For the Wimp.

The Wimp needs to install itself as the initial sleep handler for all tasks.
This gives it the opportunity to swap out idle tasks, giving other tasks the
desktop. Sophisticated applications could replace the Wimp as the sleep
handler in order to remain mostly active whilst one part of it waits. This
would enable, for example, a multi-document editor to edit documents whilst
printing other documents.

When the Wimp intercepts a sleep call the task being slept could be in one
of two states: Processing internally; Processing for redraws. Tasks not
redrawing are the easier of the two cases to handle, here is how they are
handled:
*  Their windows may be moved and resized - an open request for any such
        moved or resized window will be given to the task when it is ready.
*  Auto-redraw windows are auto-redrawn.
*  Non-auto-redraw windows are redrawn in the window's background colour.
        Transparent windows get redrawn in white. Whatever sort of window
        icons will be drawn in it. These windows will be redrawn by the
        application when it is ready.
*  Clicking on such a task's close window box will queue a close request for
        when it's ready.
*  A pointer leaving or entering event will be generated as appropriate when
        the task is ready.
*  Mouse clicks are queued to a small extent for that task.
*  User_drag_box is queued.
*  Key presses are queued for a short time, after which the input focus is
        forcibly removed from the suspended task's window. WF_grabkeys 
        windows on hung tasks do not get key presses queued.
*  Menu_selection gets queued.
*  Scroll requests get discarded.
*  Lose caret/gain caret gets returned if appropriate when the task is
        ready.
*  PollWord_Nonzero gets returned when the task is ready.
*  User_Messages get queued
*  User_Message_Recordeds get discarded (and acked back to the sender).
*  User_Message_Acknowledges get queued.
Tasks which sleep whilst doing redraws are more complex.

*  A window owned by a sleeping task will have the following information
stored with it:
    *   An update list. This indicates which sections of the window have
        been updated in this update sequence. This list will only be present
        if the task slept whilst updating.
    *   An invalid rectangle list. This will be added to the Wimp's invalid
        rectangle list when the task unsleeps. This list gets accumulated
        whilst the task sleeps as bits of the window get obliterated. If a
        task slept whilst redrawing, the task won't be given any more
        rectangles in that redraw sequence.
    *   A flag indicating close requested. This will be set when the user
        clicks on the close box.
    *   A flag indicating 'caret was here', and associated caret
        information. This enables the Wimp to return lose_caret events when
        the application unsleeps.
    *   A flag indicating 'has been opened'.
    *   A flag indicating 'The pointer was here'. This enables a suitable
        pointer leaving event to be generated when the task wakes up. If
        such an event is generated, then the window the pointer is now over
        will be given a pointer entering event. This is to ensure the
        pointer's shape remains consistent.

*  A sleeping task will have the following information stored with it:
    *   A queue of pending messages
    *   

Broadcast messages:
User_Messages are queued for slept tasks. User_Message_Recordeds are NAKed
for slept tasks.

Directed messages (messages sent to one task only):
All User_Messages except Message_DataSaveAck


A task which has an unprocessed ackable message sent to a slept task will
sleep. A task started by a slept task which hasn't Wimp_Polled or
Wimp_ShutDowned or terminated since starting the new task will sleep when it
Wimp_Polls, waiting for its parent to do one of the given things.

 The OS needs two new SWIs - OS_SaveSVCStack;OS_RestoreSVCStack -
which will save and restore the SVC stack to a caller specified area.



Messages:

Protocols:
Filer starting FilerAct:
Filer:          Wimp_StartTask *Filer_Action
FilerAct:       Starts, gets to Wimp_Poll which returns to Filer
Filer:          Check FilerAct is going by result from Wimp_StartTask
                Send messages indicating what FilerAct is to do.
                Wimp_Poll
FilerAct:       Receives messages then starts. If not got something to
                do at first Wimp_Poll the FilerAct dies.

PreQuit;Quit sequence paused for saving data:
Quiter:         SendAck Message_PreQuit
Quitee:         Ack message to stop prequit
Quiter:         Doesn't receive message nac does nothing
Quitee:         Eventually restarts sequence by faking ctl/shft/f12 to quiter

PreQuit;Quit sequence going through unblocked:
Quiter:         SendAck Message_PreQuit
Quitee:         Checks and doesn't ack the message.
Quiter:         Receives ack for PreQuit and sends Quit
Quitee:         doesn't ack quit
Quiter:         Receives quit nak and quits.

Slotsize sequence:
Changer:        SendAck Message_SetSlot
Changee:        Ack if knows about slot size changing
Changer:        If nac received note task as not changing its slot

