<> <> <> <> 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.