DIRECTORY DFOperations USING [BringOver, SModel, Verify], DFOperationsQueue USING [NotifierProc, OpTerminationInteraction, Request, RequestRecord], List USING [PutAssoc], Process USING [Detach, Priority, priorityBackground, SetPriority], ProcessProps USING [PushPropList]; OpsQueueImpl: CEDAR MONITOR LOCKS queue.LOCK USING queue: Queue IMPORTS DFOperations, List, Process, ProcessProps EXPORTS DFOperationsQueue = BEGIN Queue: TYPE = REF QueueObject; QueueObject: PUBLIC TYPE = MONITORED RECORD [ pending: LIST OF DFOperationsQueue.Request _ NIL, pendingTail: LIST OF DFOperationsQueue.Request _ NIL, priority: Process.Priority, abortPending: BOOL _ FALSE, idleNotifier: DFOperationsQueue.NotifierProc, clientData: REF ANY ]; Create: PUBLIC PROC [priority: Process.Priority _ Process.priorityBackground, idleNotifier: DFOperationsQueue.NotifierProc _ NIL, clientData: REF ANY _ NIL] RETURNS [Queue] = { RETURN[NEW[QueueObject _ [ priority: priority, idleNotifier: idleNotifier, clientData: clientData ]]]; }; Empty: PUBLIC ENTRY PROC [queue: Queue] RETURNS [BOOL] = { RETURN[queue.pending = NIL] }; Abort: PUBLIC ENTRY PROC [queue: Queue] = { IF queue.pending ~= NIL THEN { queue.abortPending _ TRUE; }; }; Enqueue: PUBLIC ENTRY PROC [queue: Queue, request: DFOperationsQueue.Request] = { rL: LIST OF DFOperationsQueue.Request = CONS[request, NIL]; IF queue.pending ~= NIL THEN { queue.pendingTail.rest _ rL; queue.pendingTail _ rL; } ELSE { queue.pending _ queue.pendingTail _ rL; TRUSTED{Process.Detach[FORK Worker[queue]]}; }; }; Worker: PROC [queue: Queue] = { remaining: LIST OF DFOperationsQueue.Request; Process.SetPriority[queue.priority]; DO request: DFOperationsQueue.Request = queue.pending.first; WorkerInner: PROC = { errors, warnings, filesActedUpon: INT _ 0; ReportTermination: PROC = { [] _ request.interact[ NEW[DFOperationsQueue.OpTerminationInteraction _ [ op: request.op, dfFile: request.dfFile, filesActedUpon: filesActedUpon, errors: errors, warnings: warnings ]], request.clientData ]; }; WITH request^ SELECT FROM req: bringOver DFOperationsQueue.RequestRecord => { [errors: errors, warnings: warnings, filesActedUpon: filesActedUpon] _ DFOperations.BringOver[ dfFile: req.dfFile, filter: req.filter, action: req.action, interact: req.interact, clientData: req.clientData, log: req.log ]; ReportTermination[]; }; req: sModel DFOperationsQueue.RequestRecord => { [errors: errors, warnings: warnings, filesActedUpon: filesActedUpon] _ DFOperations.SModel[ dfFile: req.dfFile, action: req.action, interact: req.interact, clientData: req.clientData, log: req.log ]; ReportTermination[]; }; req: verify DFOperationsQueue.RequestRecord => { [errors: errors, warnings: warnings, filesActedUpon: filesActedUpon] _ DFOperations.Verify[ dfFile: req.dfFile, interact: req.interact, clientData: req.clientData, log: req.log ]; ReportTermination[]; }; ENDCASE => ERROR; }; ProcessProps.PushPropList[ List.PutAssoc[key: $WorkingDirectory, val: request.wDir, aList: NIL], WorkerInner]; IF ([remaining: remaining] _ Done[queue]).done THEN EXIT; ENDLOOP; queue.idleNotifier[queue, remaining, queue.clientData]; }; Done: ENTRY PROC [queue: Queue] RETURNS [done: BOOL, remaining: LIST OF DFOperationsQueue.Request _ NIL] = { IF queue.abortPending THEN { remaining _ queue.pending; queue.pending _ NIL; queue.abortPending _ FALSE; } ELSE queue.pending _ queue.pending.rest; done _ queue.pending = NIL; }; END. ‚OpsQueueImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Levin on December 6, 1983 1:09 pm Russ Atkinson (RRA) February 13, 1985 11:50:51 am PST Exports to DFOperationsQueue We don't try to abort the executing operation, since, in practice, our client will worry about that. Invariant (while outside the monitor): queue.pending = NIL iff no worker process exists Internal Procedures Assert: queue.pending ~= NIL. To preserve the monitor invariant (see Enqueue), the request is left on the queue while it is being executed. Invariant (while outside the monitor): queue.pending = NIL iff no worker process exists Κς˜codešœ™Kšœ Οmœ1™