<> <> <> DIRECTORY HostNumbers USING [ProcessorID], Process USING [SecondsToTicks, SetTimeout], ProcessorFace USING [GetGreenwichMeanTime, gmtEpoch, processorID], System; SystemImpl: CEDAR MONITOR IMPORTS Process, ProcessorFace EXPORTS System = BEGIN UniversalID: PUBLIC TYPE = MACHINE DEPENDENT RECORD [processor(0): HostNumbers.ProcessorID, sequence(3): LONG CARDINAL]; <> <<~~~~~~~~~~ Universal identifiers: ~~~~~~~~~~>> <> <> <> oneSecond: CONDITION; uidCounter: LONG CARDINAL _ 0; -- always <= SecondsSinceEpoch[GetGreenwichMeanTime[]] uidCounterValid: BOOLEAN _ FALSE; GetUniversalID: PUBLIC ENTRY PROC RETURNS [UniversalID] = { ENABLE UNWIND => NULL; secondsSinceEpoch: LONG CARDINAL; nextUID: UniversalID; <> DO secondsSinceEpoch _ ProcessorFace.GetGreenwichMeanTime[] - ProcessorFace.gmtEpoch; IF secondsSinceEpoch = 0 THEN ERROR; IF ~uidCounterValid THEN { -- clock set after initialization uidCounter _ secondsSinceEpoch; uidCounterValid _ TRUE}; IF uidCounter < secondsSinceEpoch THEN EXIT; WAIT oneSecond; ENDLOOP; nextUID _ [processor: LOOPHOLE[ProcessorFace.processorID], sequence: uidCounter]; uidCounter _ uidCounter + 1; RETURN[nextUID]}; Init: PROC [] = TRUSTED BEGIN Process.SetTimeout[@oneSecond, Process.SecondsToTicks[1]]; END; Init[]; END.