ScheduleImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Christian LeCocq January 28, 1987 6:00:12 pm PST
DIRECTORY
Schedule;
ScheduleImpl: CEDAR MONITOR LOCKS agenda USING agenda: Agenda
EXPORTS Schedule ~ BEGIN OPEN Schedule;
History management package
CreateHistory: PUBLIC PROC [t: ps, v: REAL] RETURNS [newHistory: History] ~ {
newHistory ← LIST[[t, v]];
};
KillHistory: PUBLIC PROC [history: History] ~ {
h: History;
UNTIL history=NIL DO
h ← history;
history ← history.rest;
h.rest ← NIL;
ENDLOOP;
};
AddToHistory: PUBLIC PROC [oldHistory: History, t: ps, v: REAL] RETURNS [newHistory: History] ~ {
last, prev: History;
historyPt: HistoryPt ← [t, v];
newHistory ← oldHistory;
FOR ih: History ← oldHistory, ih.rest UNTIL ih=NIL DO
IF ih.first.t>=t THEN { --if t occurs before the end of the current history then
ih.first ← historyPt; -- change the present and delete the "old future".
ih.rest ← NIL;
IF prev#NIL THEN IF prev.first.v=last.first.v AND prev.first.v=v THEN prev.rest ← last.rest;
RETURN;
};
prev ← last;
last ← ih;
ENDLOOP;
last.rest ← LIST[historyPt];
IF prev#NIL THEN IF prev.first.v=last.first.v AND prev.first.v=v THEN prev.rest ← last.rest;
};
ForgetBeginings: PUBLIC PROC [oldHistory: History, t: ps] RETURNS [newHistory: History] ~ {
newHistory ← oldHistory;
FOR ih: History ← oldHistory, ih.rest UNTIL ih.rest=NIL DO
IF ih.rest.first.t>t THEN {
newHistory ← ih;
RETURN;
};
ENDLOOP;
};
ForgetBeginings: PUBLIC PROC [oldHistory: History, t: ps] RETURNS [newHistory: History] ~ {
newHistory ← oldHistory;
FOR ih: History ← oldHistory, ih.rest UNTIL ih.rest=NIL DO
newHistory ← ih;
IF ih.rest.first.t>t THEN {
v: REAL ← VFromHistory[ih, t];
ih.first.v ← v;
ih.first.t ← t;
RETURN;
};
ENDLOOP;
};
FirstTimeOfHistory: PUBLIC PROC [history: History] RETURNS [t: ps] ~ {
t ← history.first.t
};
NextTimeOfHistory: PUBLIC PROC [history: History, t: ps] RETURNS [tnext: ps ← -1e30] ~ {
FOR ih: History ← history, ih.rest UNTIL ih=NIL DO
IF ih.first.t>=t THEN RETURN[ih.first.t];
ENDLOOP;
};
LastTimeOfHistory: PUBLIC PROC [history: History] RETURNS [t: ps] ~ {
FOR ih: History ← history, ih.rest UNTIL ih.rest=NIL DO REPEAT
FINISHED => t ← ih.first.t;
ENDLOOP;
};
LastValueOfHistory: PUBLIC PROC [history: History] RETURNS [v: REAL] ~ {
FOR ih: History ← history, ih.rest UNTIL ih.rest=NIL DO REPEAT
FINISHED => v ← ih.first.v;
ENDLOOP;
};
VFromHistory: PUBLIC PROC [history: History, t: ps] RETURNS [v: REAL] ~ {
t0: ps;
v0: REAL;
IF t < history.first.t THEN ERROR; -- Why should you return to the past ?
IF t=history.first.t THEN RETURN[history.first.v];
FOR ih: History ← history, ih.rest UNTIL ih=NIL DO
IF t<=ih.first.t THEN {
v ← v0 + (ih.first.v - v0)*(t-t0) /(ih.first.t - t0);
RETURN;
};
v0 ← ih.first.v;
t0 ← ih.first.t;
REPEAT
FINISHED => v ← v0;
ENDLOOP;
};
EnumerateHistory: PUBLIC PROC [history: History, from, to: ps, action: HistoryProc] RETURNS [invalidEnumeration: BOOLFALSE] ~ {
quit: BOOLEANFALSE;
FOR ih: History ← history, ih.rest UNTIL ih=NIL OR quit OR ih.first.t>to DO
IF ih.first.t>=from THEN quit ← action[ih.first.t, ih.first.v];
ENDLOOP;
};
Schedule: PUBLIC PROC [hList: LIST OF History] RETURNS [lt: LIST OF ps] ~ {
t: ps;
h: LIST OF History;
endlt: LIST OF ps;
finished: BOOLEANFALSE;
endlt ← lt ← LIST[-1e30];
UNTIL finished DO
finished ← TRUE;
t ← 1e30;
FOR ih: LIST OF History ← hList, ih.rest UNTIL ih=NIL DO
IF ih.first#NIL THEN {
finished ← FALSE;
IF t>=ih.first.first.t THEN {
t ← ih.first.first.t;
h ← ih;
};
};
ENDLOOP;
IF ~finished THEN {
IF endlt.first#t THEN {
endlt.rest ← LIST[t];
endlt ← endlt.rest;
};
h.first ← h.first.rest;
};
ENDLOOP;
lt ← lt.rest;
};
Agenda Gestion
CreateAgenda: PUBLIC PROC [execute: ExecuteProc, data: REF ANY] RETURNS [newAgenda: Agenda] ~ {
newAgenda ← NEW[AgendaRec ← [execute: execute, data: data]];
};
KillAgenda: PUBLIC PROC [agenda: Agenda] ~ {
aList: LIST OF Event;
UNTIL agenda.list=NIL DO
agenda.list.first.ref ← NIL;
aList ← agenda.list;
agenda.list ← agenda.list.rest;
aList.rest ← NIL;
ENDLOOP;
agenda.data ← NIL;
};
InsertInAgenda: PUBLIC ENTRY PROC [agenda: Agenda, ref: REF ANY, t: ps] ~ {
ENABLE UNWIND => NULL;
cal: LIST OF Event;
IF t=-1e30 THEN RETURN;
IF agenda=NIL THEN ERROR; --don't try to insert in an empty ref
IF agenda.list=NIL THEN {
agenda.list ← LIST[[t, ref]];
agenda.nbOfEvents ← 1;
RETURN
};
IF t<agenda.list.first.t THEN ERROR; -- you try to add something to the past...
FOR ical: LIST OF Event ← agenda.list, ical.rest UNTIL ical=NIL DO
IF t=ical.first.t THEN IF ref=ical.first.ref THEN RETURN;
IF t<ical.first.t THEN {
ical.rest ← CONS[ical.first, ical.rest];
ical.first.t ← t;
ical.first.ref ← ref;
agenda.nbOfEvents ← agenda.nbOfEvents+1;
RETURN;
};
calical;
ENDLOOP;
cal.rest ← LIST[[t, ref]];
agenda.nbOfEvents ← agenda.nbOfEvents+1;
};
DeleteEvent: ENTRY PROC [agenda: Agenda] ~ {
ENABLE UNWIND => NULL;
aList: LIST OF Event ← agenda.list;
aList.first.ref ← NIL;
agenda.list ← agenda.list.rest;
aList.rest ← NIL;
agenda.nbOfEvents ← agenda.nbOfEvents-1;
};
ExecuteAgenda: PUBLIC PROC [agenda: Agenda] RETURNS [lastTime: ps] ~ {
ENABLE UNWIND => NULL;
WHILE agenda.list#NIL DO
agenda.execute[agenda.list.first.ref, agenda.list.first.t, agenda.data];
lastTime ← agenda.list.first.t;
DeleteEvent[agenda];
ENDLOOP;
};
END.