<> <> <> <> <<>> DIRECTORY LazyEvaluation; LazyEvaluationImpl: CEDAR MONITOR EXPORTS LazyEvaluation ~ BEGIN OPEN LazyEvaluation; check: CONDITION; Failed: PUBLIC ERROR = CODE; ProcType: TYPE = PROC [REF] RETURNS [REF]; <<>> Ok: ProcType = {ERROR}; Crashed: ProcType = {ERROR}; WaitForOtherEvaluation: ProcType = {ERROR}; State: TYPE = {doit, waitForOtherEvaluation, done, crashed}; Test: ENTRY PROC [h: Handle] RETURNS [proc: ProcType, s: State] = { IF h.evaluate=Ok THEN RETURN [NIL, done]; IF h.evaluate=WaitForOtherEvaluation THEN RETURN [NIL, waitForOtherEvaluation]; IF h.evaluate=Crashed THEN RETURN [NIL, crashed]; proc ¬ h.evaluate; h.evaluate ¬ WaitForOtherEvaluation; RETURN [proc, doit] }; Notify: ENTRY PROC [] = { BROADCAST check }; Wait: ENTRY PROC [h: Handle] = { IF h.evaluate=WaitForOtherEvaluation THEN WAIT check }; Evaluate: PUBLIC PROC [h: Handle] RETURNS [REF] = { proc: ProcType; s: State; DO IF h.evaluate=Ok THEN RETURN [h.data]; [proc, s] ¬ Test[h]; SELECT s FROM done => RETURN [h.data]; doit => { data: REF; data ¬ proc[h.data ! UNWIND => {h.evaluate ¬ Crashed; Notify[]}]; SetResult[h, data]; }; waitForOtherEvaluation => Wait[h]; crashed => ERROR Failed; ENDCASE; ENDLOOP }; SetResult: PUBLIC ENTRY PROC [h: Handle, result: REF] = { IF h#NIL THEN { h.data ¬ result; h.evaluate ¬ Ok; BROADCAST check }; }; New: PUBLIC PROC [evaluate: PROC [data: REF] RETURNS [REF], data: REF ¬ NIL] RETURNS [Handle] = { RETURN [ NEW[HandleRec ¬ [evaluate: evaluate, data: data]] ]; }; END.