PreemptablePaintProcs.mesa
Copyright Ó 1992 by Xerox Corporation. All rights reserved.
-- Greene, May 22, 1990 5:08 pm PDT
-- Chauser, June 4, 1992 9:57 am PDT
DIRECTORY
Draw2d,
Imager,
ViewerClasses;
PreemptablePaintProcs: CEDAR DEFINITIONS =
BEGIN
*** Imager Contexts ***
A locked context is used to guard imager operations from context changes in the viewers world.
LockedContext: TYPE = REF LockedContextRec;
LockedContextRec:
TYPE =
MONITORED
RECORD[
stateHasChanged: CONDITION,
suspend: BOOL ¬ FALSE,
abort: BOOL ¬ FALSE,
context: Imager.Context, -- cannot be used directly, only through DoUnderLock below.
zip: Draw2d.Zip, -- extra accelerator (logically part of context)
pauseWhileIdle: PauseProc,
viewer: ViewerClasses.Viewer
];
NilLockedContext: PROC [] RETURNS [LockedContext];
DoUnderLock:
PROC [lc: LockedContext,
Action: LockedContextActionProc];
If the locked context has not been aborted then the imager actions defined by "Action" are applied to the context inside of "lc" If the locked context has been suspended then DoUnderLock will wait until the suspension is lifted. If the locked context has been aborted then DoUnderLock will raise ERROR ABORTED.
LockedContextActionProc: TYPE = PROC [context: Imager.Context, zip: Draw2d.Zip];
AbortContext:
PROC [lc: LockedContext];
Set abort = TRUE and suspend = FALSE in the locked context, in order to abort all running and suspended processes using the locked context.
*** Paint Procs ***
The client writes a UnlockedPaintProc that is identical to an ordinary paint proc except that it paints through a locked context using DoUnderLock. The procedure below is used (inside a traditional Paint Proc) to invoke the UnlockedPaintProc. The first four parameters are passed directly through from the traditional Paint Proc, the next parameter, UnlockedPaint, is the new paint proc using a locked context, and the last two parameters determine an on-off cycle that will be described shortly.
Painting, of course, does not really happen without locks. The illusion is created by forking the UnlockedPaint proc, delaying for the "on" portion of the cycle (so that PaintWithoutLocks holds the viewers locks while UnlockedPaint is painting), suspending the locked context, forking a processes that will paint the viewer again after the "off" portion of the duty cycle, and then returning (releasing the viewers locks for the "off" portion of the cycle). The whatChanged field is used to rendezvous with the suspended UnlockedPaint proc. Because it frequently releases the locks PaintWithoutLocks is easy to preempt.
PaintWithoutLocks:
PROC [
self: ViewerClasses.Viewer,
context: Imager.Context,
whatChanged: REF,
clear: BOOL,
UnlockedPaint: UnlockedPaintProc,
PauseWhilePaint: PauseProc ¬ DefaultPauseWhilePaint,
PauseWhileIdle: PauseProc ¬ DefaultPauseWhileIdle
] RETURNS [lc: LockedContext];
UnlockedPaintProc: TYPE = PROC [self: ViewerClasses.Viewer, lc: LockedContext, whatChanged: REF, clear: BOOL];
PauseProc: TYPE = PROC[];
DefaultPauseWhilePaint: PauseProc;
~ {Process.PauseMsec[2000]}; --2 seconds of paint
DefaultPauseWhileIdle: PauseProc;
~ {Process.PauseMsec[100]}; --1/10 second idle
*** For Advanced Use ***
SuspendContext: PROC [lc: LockedContext];
RestartContext: PROC [lc: LockedContext];
END.