DIRECTORY CD USING [Rect, Design], CDBasics, CDDrawQueue; CDDrawQueueImpl: CEDAR MONITOR IMPORTS CDBasics EXPORTS CDDrawQueue SHARES CD = BEGIN DrawQueue: TYPE = REF DrawQueueRep; Request: TYPE = CDDrawQueue.Request; maxC: CARDINAL = 50; DrawQueueRep: PUBLIC TYPE = RECORD [ cnt, in, out: CARDINAL, commandAvail: CONDITION, desgn: CD.Design, deviceClip: CD.Rect, comm: ARRAY [0..maxC) OF Request, stopFlag: REF BOOL, -- must be monitored inlist: BOOL _ FALSE, deleted: BOOL _ FALSE, alldoneToBeReported: BOOL _ FALSE ]; TableList: TYPE = LIST OF DrawQueue; queueEmpty: PUBLIC REF _ NEW[INT]; finishedForEver: PUBLIC REF _ NEW[INT]; InsertList: INTERNAL PROC [dq: DrawQueue] = BEGIN IF NOT dq.inlist THEN { list: TableList _ NARROW[dq.desgn.cdDrawQueuePriv]; list _ CONS[dq, list]; dq.desgn.cdDrawQueuePriv _ list; dq.inlist _ TRUE; }; END; RemoveList: INTERNAL PROC [dq: DrawQueue] = BEGIN IF dq.inlist THEN { list: TableList _ NARROW[dq.desgn.cdDrawQueuePriv]; IF list=NIL THEN RETURN; -- list#NIL; otherwise nothing too delete! not dq.inlist; but don't be picky IF list.first=dq THEN dq.desgn.cdDrawQueuePriv _ list.rest ELSE FOR l: TableList _ list, l.rest WHILE l.rest#NIL DO IF l.rest.first=dq THEN {l.rest _ l.rest.rest; EXIT} ENDLOOP; dq.inlist _ FALSE; }; END; Create: PUBLIC ENTRY PROC [design: CD.Design, stopFlag: REF BOOL, clip: CD.Rect_[1,1,0,0]] RETURNS [DrawQueue] = BEGIN ENABLE UNWIND => NULL; --catches eg on stopFlag=NIL dq: DrawQueue = NEW[DrawQueueRep]; IF stopFlag=NIL THEN stopFlag _ NEW[BOOL_FALSE]; dq.cnt _ dq.in _ dq.out _ 0; dq.deviceClip _ CDBasics.empty; dq.desgn _ design; dq.stopFlag _ stopFlag; -- assigns addresses dq.deleted _ dq.inlist _ dq.alldoneToBeReported _ dq.stopFlag^ _ FALSE; InternalChangeClipArea[dq, clip]; RETURN [dq] END; ChangeClipArea: PUBLIC ENTRY PROC [dq: DrawQueue, clip: CD.Rect] = BEGIN ENABLE UNWIND => NULL; InternalChangeClipArea[dq, clip]; END; InternalChangeClipArea: INTERNAL PROC [dq: DrawQueue, clip: CD.Rect] = BEGIN InternalFlush[dq]; dq.deviceClip _ clip; IF CDBasics.NonEmpty[clip] THEN InsertList[dq] ELSE RemoveList[dq] END; Destroy: PUBLIC ENTRY PROC [dq: DrawQueue] = BEGIN ENABLE UNWIND => NULL; IF dq#NIL THEN { dq.deleted _ TRUE; InternalFlush[dq]; RemoveList[dq]; dq.desgn _ NIL; } END; QueueInsertDrawCommand: PUBLIC ENTRY PROC [dq: DrawQueue, req: Request] = BEGIN ENABLE UNWIND => NULL; IF dq.inlist THEN InternalInsertCommand[dq, req] END; InternalInsertCommand: INTERNAL PROC [dq: DrawQueue, req: Request] = BEGIN IF dq.cnt>=maxC THEN { InternalFlush[dq]; InternalInsertCommand[dq, Request[$flushed, dq.deviceClip]]; InternalInsertCommand[dq, Request[$redraw, dq.deviceClip]]; RETURN; }; dq.alldoneToBeReported _ TRUE; IF req.key=$redraw THEN { IF CDBasics.Intersect[req.rect, dq.deviceClip] THEN { j: CARDINAL _ dq.out; req.rect _ CDBasics.Intersection[req.rect, dq.deviceClip]; THROUGH [0..dq.cnt) DO IF dq.comm[j].key=$redraw OR dq.comm[j].key=$overdraw THEN { IF CDBasics.Inside[req.rect, dq.comm[j].rect] THEN { dq.comm[j].key _ $redraw; RETURN }; IF CDBasics.Inside[dq.comm[j].rect, req.rect] THEN { dq.comm[j].key _ $redraw; dq.comm[j].rect _ req.rect; RETURN }; }; j _ (j+1) MOD maxC; ENDLOOP } ELSE RETURN; } ELSE IF req.key=$overdraw THEN { IF CDBasics.Intersect[req.rect, dq.deviceClip] THEN { j: CARDINAL _ dq.out; req.rect _ CDBasics.Intersection[req.rect, dq.deviceClip]; THROUGH [0..dq.cnt) DO IF dq.comm[j].key=$redraw OR dq.comm[j].key=$overdraw THEN { IF CDBasics.Inside[req.rect, dq.comm[j].rect] THEN RETURN; IF CDBasics.Inside[dq.comm[j].rect, req.rect] THEN { dq.comm[j].rect _ req.rect; RETURN }; }; j _ (j+1) MOD maxC; ENDLOOP } ELSE RETURN; }; dq.cnt _ dq.cnt+1; dq.comm[dq.in] _ req; dq.in _ (dq.in+1) MOD maxC; NOTIFY dq.commandAvail; END; InsertDrawCommand: PUBLIC ENTRY PROC [design: CD.Design, req: Request] = BEGIN ENABLE UNWIND => NULL; FOR lst: TableList _ NARROW[design.cdDrawQueuePriv], lst.rest WHILE lst#NIL DO InternalInsertCommand[lst.first, req]; ENDLOOP END; FetchCommand: PUBLIC ENTRY PROC [dq: DrawQueue] RETURNS [req: Request] = BEGIN ENABLE UNWIND => NULL; dq.stopFlag^ _ FALSE; WHILE dq.cnt<=0 DO IF dq.deleted THEN InsertDisappear[dq] ELSE IF dq.alldoneToBeReported THEN InsertAlldone[dq] ELSE WAIT dq.commandAvail; dq.stopFlag^ _ FALSE; ENDLOOP; dq.cnt _ dq.cnt-1; req _ dq.comm[dq.out]; dq.out _ (dq.out+1) MOD maxC; END; Flush: PUBLIC ENTRY PROC [dq: DrawQueue]= BEGIN ENABLE UNWIND => NULL; IF dq#NIL THEN InternalFlush[dq] END; InternalFlush: INTERNAL PROC [dq: DrawQueue] = BEGIN dq.cnt _ dq.in _ dq.out _ 0; dq.stopFlag^ _ TRUE; dq.alldoneToBeReported _ FALSE; NOTIFY dq.commandAvail; END; InsertDisappear: INTERNAL PROC [dq: DrawQueue] = BEGIN dq.out _ 0; dq.cnt _ 1; dq.comm[0] _ Request[finishedForEver, [1,1,0,0]]; dq.in _ (1 MOD maxC); END; InsertAlldone: INTERNAL PROC [dq: DrawQueue] = BEGIN dq.alldoneToBeReported _ FALSE; dq.out _ 0; dq.cnt _ 1; dq.comm[0] _ Request[queueEmpty, [1,1,0,0]]; dq.in _ (1 MOD maxC); END; END. ~CDDrawQueueImpl.mesa (part of ChipNDale) Copyright c 1983, 1986 by Xerox Corporation. All rights reserved. by Christian Jacobi July 6, 1983 5:09 pm last edited Christian Jacobi March 13, 1986 3:01:06 pm PST -- request to stop the execution of (only!) the current command --stopFlag^ tells any drawing process to stop volunterly and to fetch the next --command. --stopFlag^ must not be modified any more outside this monitor!! --until DeleteCommandTable is called --Users may request a stop by calling Flush. --changes the clipping aera --changes the clipping aera --no more insertion calls on dq allowed!! --redraw process must disapear from itself, --when redraw process dispears and contains nomore --reference of dq, it is subject for garbage collection --The stopFlag is immediately set to TRUE and later --reset to FALSE when the redraw --process stopped the current command, if it then fetches another --command it gets the disapearforever command. --this procedure introduces redraw all if table is full --and in removes certain rectangles contained by others --this implies that the module knows some commands --this search for similar commands could be made much better --this search for similar commands could be made much better --waits till command is available or DrawQueue deleted -- the drawing may stop after some time only, -- and NOT immediately with procedure return Κ h˜codešœ,™,Kšœ Οmœ7™BKšœ+™+Kšœ<™