XlTimeEvents.mesa
Copyright Ó 1991 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, September 26, 1991 4:33:22 pm PDT
Christian Jacobi, May 28, 1993 12:53 pm PDT
The X server does not generate events when nothing happens...
This package offers a solution to this problem which suites applications like tip tables without introducing additional network traffic.
This module is inline-happy and sensitive to correct usage because it is used for speed critical clients. (However, incorrect usage by a particular client does not affect other clients)
DIRECTORY
Xl USING [currentTime, EventProcType, TimeStamp, TQ];
XlTimeEvents: CEDAR DEFINITIONS ~
BEGIN
Public features
TEHandle: TYPE = REF TEHandleRec;
The package-handle type.
Create: PROC [reportTQ: Xl.TQ, reportProc: Xl.EventProcType, reportData: REF ¬ NIL] RETURNS [teh: TEHandle];
Creates a handle. This handle supports generation of fake events reporting time passed.
Fake events are reported in few millisecond interval, but only for few seconds after a call of Windup. The clock for such fake events runs slightly slower then server clock to increase probability of monoticity. Letting the fake clock wind down limits the damage if our clock would be too fast nevertheless. We try hard not to pass the server clock, but nothing can protect from network delays.
Notice that those events are reported on exactly one TQ.
GetFakeTime: PROC [teh: TEHandle] RETURNS [Xl.TimeStamp] = INLINE {
Returns a fake time if appropriate past the last server time reported with SetCorrectTime.
Must be used from teh.reportTQ to be accurate. (Typically used from teh.reportProc).
--
<<Arithmetic mod 2**32>>
deltaTicks: CARD32 ~ actualTicks-teh.lastActualTicks;
xTime: CARD32 ~ deltaTicks*mSecPerFastTick + LOOPHOLE[teh.lastActualTime, CARD32];
RETURN [LOOPHOLE[xTime]];
};
SetCorrectTime: PROC [teh: TEHandle, actualTime: Xl.TimeStamp] = INLINE {
SetCorrectTime the reference time; use only a time known by the server.
Must be used from teh.reportTQ because it is not otherwise monitored.
--
IF (actualTime-teh.lastActualTime<<mod 2**32>>)>0 THEN teh.baseValid ¬ FALSE;
teh.lastActualTime ¬ actualTime;
};
Windup: PROC [teh: TEHandle] = INLINE {
Winds up the fake clock for a few seconds.
Must be used from teh.reportTQ because it is not otherwise monitored.
--
teh.lastWound ¬ actualTicks;
IF ~teh.active THEN RealActivate[teh];
};
Private features
TEHandleRec: PRIVATE TYPE = PRIVATE RECORD [
lastActualTime: Xl.TimeStamp ¬ Xl.currentTime, --base server-time reference
lastActualTicks: CARD32 ¬ 0,  --base tick-time reference (advanced by timer)
lastWound: CARD32 ¬ 0, --
tq: Xl.TQ ¬ NIL,  --client specified 
proc: Xl.EventProcType,   --client specified
data: REF ¬ NIL,  --client specified
active: BOOL ¬ FALSE,  --event generation active
baseValid: BOOL ¬ FALSE,  --request to reset base tick-time reference
enqueued: PRIVATE BOOL ¬ FALSE, --in queue considered on timer wakeup
next: PRIVATE TEHandle ¬ NIL--list of queued TEHandles
];
actualTicks: PRIVATE READONLY CARD32; --slightly slow
mSecPerFastTick: PRIVATE READONLY CARD32;
RealActivate: PRIVATE PROC [teh: TEHandle];
END.