The AutoRepeat
interface provides support for calling a procedure
repetitively. Auto-repeating typically takes place while a key or
mouse button is held down, although there is no direct relation
between AutoRepeat
and VBT
s.
When an auto-repeat object ar
is activated, it forks a {\it timer
thread\/} that calls ar.repeat()
after firstWait
milliseconds,
and every period
milliseconds thereafter. However, there is a
flow-control mechanism: if the call to ar.repeat()
has not
returned by the time the next repetition is scheduled to take
place, the timer thread will wait. That is, repetitions cannot
queue up more than one deep.
An auto-repeat object ar
is activated by a call to Start(ar)
,
terminated by a call to Stop(ar)
, and resumed by a call to
Continue(ar)
.
All locking is handled within AutoRepeat
; calls to Start(ar)
,
Stop(ar)
, and Continue(ar)
are serialized on a per-ar
basis.
These procedures may be called by a repeat
method. Clients must
not call the repeat
method directly; it is called by the timer
thread subject to client-calls to Start
, Stop
, and Continue
.
The AutoRepeat
interface will never call a repeat
method
re-entrantly.
INTERFACEThe callAutoRepeat ; TYPE Milliseconds = CARDINAL; CONST DefaultFirstWait: Milliseconds = 500; DefaultPeriod : Milliseconds = 66; TYPE T <: Public; Public = Private OBJECT METHODS init (firstWait: Milliseconds := DefaultFirstWait; period : Milliseconds := DefaultPeriod): T; repeat (); canRepeat(): BOOLEAN; END; Private <: ROOT;
ar.init(firstWait, period)
initializes ar
as an
AutoRepeat.T
, and it returns ar
. The firstWait
and
period
parameters are stored internally for use by the
Start
and Continue
procedures.
The call ar.canRepeat
should return FALSE
whenever there's
reason to suspect that a client might want to call Stop
in
the near future. The next call to ar.repeat
will be
suspended for period
milliseconds. The default for
this method always returns TRUE
.
The canRepeat
method is intended for situations when a
repeat
method takes more time than period
milliseconds to complete. The problem with slow repeat
methods is that the scheduler might decide to always run the
timer thread (since it will want to call the repeat
method
as soon as the slow repeat
method completes), thereby
blocking another thread from being able to call Stop
.
The default repeat
method is a no-op.
PROCEDURE Start (ar: T);
Initiate auto-repeating for ar
.
Start(ar)
forks a timer thread that will wait ar.firstWait
milliseconds before calling ar.repeat()
the first time, then
ar.period
milliseconds between subsequent calls to ar.repeat()
.
This procedure is a no-op if ar
is already running.
PROCEDURE Stop (ar: T);
Stop auto-repeating as soon as possible.
After calling
Stop(ar)
, the implementation will not call
ar.repeat()
again until a call to Start(ar)
or Continue(ar)
restarts auto-repeating. This procedure is a no-op if ar
is not
already running.
It is possible (but unlikely) that ar.repeat()
is called one more
time after a call to Stop(ar)
returns. This can happen because
calls to ar.repeat
are not serialized with respect to the call to
Stop(ar)
. They are not serialized in order to allow a repeat
method to call Stop
.
PROCEDURE Continue (ar: T);
Resume auto-repeating immediately.
Continue(ar)
is like Start(ar)
, except rather than waiting
ar.firstWait
milliseconds as in the call to Start(ar)
, the
timer thread calls ar.repeat
without waiting at all. Subsequent
calls to ar.repeat()
happen every period
milliseconds, as
usual. This procedure is a no-op if ar
is already running.
END AutoRepeat.