PreemptablePaintProcsDoc.tioga
Greene, August 11, 1989 5:14:55 pm PDT
Chauser, June 2, 1992 2:17 pm PDT
PreemptablePaintProcsDoc
CEDAR 10.1 — FOR INTERNAL XEROX USE ONLY
Preemptable Paint Procs
Dan Greene
© Copyright 1988, 1992 Xerox Corporation. All rights reserved.
Abstract: This package fixes the locking in Cedar to allow paint procs to be interrupted by procedures that would otherwise conflict with the locks held by the running paint proc. It is a good technique for implementing a long-running paint procedure, because it basically shifts the locking from the paint proc level to the level of individual imager operations. The client writes an UnlockedPaintProc that is almost identical to a ViewerClasses.PaintProc except that it takes a LockedContext rather than a Imager.Context. The operations that would otherwise paint directly into the Imager.Context must use the DoUnderLock procedure to paint into the Locked context. Since this is an attempt to retrofit viewers with a better locking scheme the client is cautioned that there are several ugly aspects and shortcomings (i.e. this is a hack awaiting proper redesign). See the documentation for details.
Created by: Dan Greene
Maintained by: Dan Greene <Greene.pa>
Keywords: preemption, paint procs
XEROX  Xerox Corporation
   Palo Alto Research Center
   3333 Coyote Hill Road
   Palo Alto, California 94304

For Internal Xerox Use Only
1. Introduction
PreemptablePaintProcs is an attempt to create an ideal world in which viewers locking is at the level of individual imager operations rather than at the level of entire paint procs. However, because this package does not change Viewers or the Imager, the client has to worry about more details than is ideal. This document is organized to take you through the changes necessary to convert a ViewerClasses.PaintProc into a PreemptablePaintProcs.UnlockedPaintProc and to invoke the unlocked paint proc.
2. Rewriting the Paint Proc
The types of a ViewerClasses.PaintProc and a PreemptablePaintProcs.UnlockedPaintProc are identical except for 1) the "quit" return and 2) the imager "context." The quit return argument (to suppress painting of children) is not supported by PreemptablePaintProcs. The imager context is replaced by a locked context called "lc." In the body of the paint proc, every imager call should be replaced as follows:

BEFORE:

Imager.MaskSrokeTrajectory[. . .];

AFTER:

ImagerMaskSrokeTrajectory: PreemptablePaintProcs.LockedContextActionProc ~ {
Imager.MaskSrokeTrajectory[. . .];
};
.
.
.

PreemptablePaintProcs.DoUnderLock[lc, ImagerMaskSrokeTrajectory];
2. Calling the Paint Proc
Storing the locked context in the viewer state.
The client must reserve space in the viewers state to store a locked context. How viewers state is stored is flexible, but a standard pattern is to have a record structure for viewer's state that is NARROWed by various button, notify, and paint procs. The locked context can be added to this data structure:


ViewerStateHandle: REF ViewerStateHandleRec;
ViewerStateHandleRec: TYPE = RECORD[
.
.
.
lc: PreemptablePaintProcs.LockedContext ← PreemptablePaintProcs.NilLockedContext[]
]

Paint: ViewerClasses.PaintProc = {
myState: ViewerStateHandle ← NARROW[self.data];
--or in the case of BiSrollers . . .
myState: ViewerStateHandle ← NARROW[bSstyle.ClientDataOf[NARROW[self.data]]]
.
.
.
};

Writing a Veneer Paint Proc
The task of the paint proc is to invoke the unlocked paint proc that was constructed in the section above. The below pattern should be copied and renamed as necessary:

Paint: ViewerClasses.PaintProc = {
myState: ViewerStateHandle ← NARROW[self.data];

--or in the case of BiSrollers . . .

myState: ViewerStateHandle ← NARROW[bSstyle.ClientDataOf[NARROW[self.data]]];

WITH whatChanged SELECT FROM
lockedContext: PreemptablePaintProcs.LockedContext => {
IF myState.lc # lockedContext THEN {
PreemptablePaintProcs.AbortContext[lockedContext]; -- clean up a very old context
RETURN;
};
-- restart suspended context
[] ← PreemptablePaintProcs.PaintWithoutLocks[
self, context, whatChanged, clear, UnlockedPainter];
};
ENDCASE => {
-- start a new context
PreemptablePaintProcs.AbortContext[myState.lc];
myState.lc ← PreemptablePaintProcs.PaintWithoutLocks[
self, context, whatChanged, clear, UnlockedPainter];
};
};