123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- MODULE Services;
- (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 System/Mod/Services.odc *)
- (* DO NOT EDIT *)
- IMPORT SYSTEM, Kernel;
- CONST
- now* = 0; immediately* = -1; (** DoLater notBefore **)
- resolution* = 1000;
- scale = resolution DIV Kernel.timeResolution;
- corr = resolution MOD Kernel.timeResolution;
- TYPE
- Action* = POINTER TO ABSTRACT RECORD
- notBefore: LONGINT;
- next: Action (* next element in linear list *)
- END;
- ActionHook* = POINTER TO ABSTRACT RECORD (Kernel.Hook) END;
- StdHook = POINTER TO RECORD (ActionHook) END;
- VAR
- actionHook-: ActionHook;
- actions: Action; (* list of actions *)
- candidates: Action; (* list of action candidates in IterateOverActions,
- NIL during normal execution of commands *)
- hasImmediates: BOOLEAN; (* this is a hint: one or more actions in some ring may be immediate actions *)
- trapCnt: INTEGER;
- PROCEDURE Ticks* (): LONGINT;
- VAR t: LONGINT;
- BEGIN
- t := Kernel.Time();
- RETURN t * scale + t * corr DIV Kernel.timeResolution
- END Ticks;
- (** Action **)
- PROCEDURE (a: Action) Do- (), NEW, ABSTRACT;
- PROCEDURE In (l, a: Action): BOOLEAN;
- BEGIN
- WHILE (l # NIL) & (l # a) DO l := l.next END;
- RETURN l # NIL
- END In;
- PROCEDURE Incl (VAR l: Action; a: Action);
- BEGIN
- IF l # NIL THEN a.next := l END;
- l := a
- END Incl;
- PROCEDURE Excl (VAR l: Action; a: Action);
- VAR p0, p1: Action;
- BEGIN
- IF l = a THEN
- l := a.next; a.next := NIL
- ELSIF l # NIL THEN
- p0 := l; p1 := p0.next;
- (* (p0 # NIL) & (p0 # a) *)
- WHILE (p1 # NIL) & (p1 # a) DO p0 := p1; p1 := p0.next END;
- IF p1 = a THEN p0.next := a.next; a.next := NIL END
- END
- END Excl;
- PROCEDURE Exec (a: Action);
- VAR t: Kernel.Type;
- BEGIN
- t := Kernel.TypeOf(a);
- IF t.mod.refcnt >= 0 THEN (* execute action if its module is not unloaded *)
- a.Do (* warning: here the actions and candidates lists may be modified, or a trap may occur! *)
- END
- END Exec;
- PROCEDURE Cleanup;
- VAR p: Action;
- BEGIN
- IF candidates # NIL THEN (* trap handling *)
- p := candidates; WHILE p.next # NIL DO p := p.next END; (* find last element of candidates list *)
- p.next := actions; actions := candidates; candidates := NIL (* prepend candidates list to actions list *)
- END;
- trapCnt := Kernel.trapCount (* all traps are handled now *)
- END Cleanup;
- PROCEDURE DoLater* (a: Action; notBefore: LONGINT);
- (** Register action a. If a is already registered, its notBefore value is updated instead. **)
- BEGIN
- ASSERT(a # NIL, 20);
- IF ~In(actions, a) & ~In(candidates, a) THEN
- Incl(actions, a)
- END;
- a.notBefore := notBefore; (* if a was already in a list, this statement updates the notBefore value *)
- IF notBefore = immediately THEN hasImmediates := TRUE END
- END DoLater;
- PROCEDURE RemoveAction* (a: Action);
- (** Unregister action a. If a is not registered, nothing happens **)
- BEGIN
- IF a # NIL THEN
- Excl(actions, a);
- Excl(candidates, a)
- END
- END RemoveAction;
- PROCEDURE IterateOverActions (time: LONGINT);
- VAR p: Action;
- BEGIN
- Cleanup; (* trap handling, if necessary *)
- (* candidates = NIL *)
- candidates := actions; actions := NIL; (* move action list to candidates list *)
- WHILE candidates # NIL DO (* for every candidate: execute it or put it back into actions list *)
- p := candidates; candidates := p.next; (* remove head element from candidates list *)
- IF (0 <= p.notBefore) & (p.notBefore <= time) OR (p.notBefore <= time) & (time < 0) THEN
- p.next := NIL; Exec(p) (* warning: p may call DoLater or RemoveAction,
- which change the lists! *)
- ELSE
- p.next := actions; actions := p (* move to actions list for later processing *)
- END
- END
- END IterateOverActions;
- PROCEDURE (h: ActionHook) Step*, NEW, ABSTRACT;
- PROCEDURE (h: ActionHook) Loop*, NEW, ABSTRACT;
- PROCEDURE (h: StdHook) Step;
- BEGIN
- IF (candidates = NIL) OR (trapCnt < Kernel.trapCount) THEN
- IterateOverActions(Ticks())
- END
- END Step;
- PROCEDURE (h: StdHook) Loop;
- BEGIN
- IF hasImmediates THEN
- ASSERT((candidates = NIL) OR (trapCnt < Kernel.trapCount), 100);
- IterateOverActions(immediately);
- hasImmediates := FALSE
- END
- END Loop;
- (* type handling functions *)
- PROCEDURE ThisDesc (IN type: ARRAY OF CHAR; load: BOOLEAN): Kernel.Type;
- CONST record = 1; pointer = 3;
- VAR m: Kernel.Module; t: Kernel.Type; i, j: INTEGER; ch: CHAR;
- typ: Kernel.Name; mod: ARRAY 256 OF CHAR;
- BEGIN
- ASSERT(type # "", 20);
- i := 0; ch := type[0];
- WHILE (ch # ".") & (ch # 0X) DO mod[i] := ch; INC(i); ch := type[i] END;
- ASSERT(ch = ".", 21);
- mod[i] := 0X; INC(i); t := NIL;
- IF load THEN
- m := Kernel.ThisMod(mod)
- ELSE typ := SHORT(mod$); m := Kernel.ThisLoadedMod(typ)
- END;
-
- IF m # NIL THEN
- j := 0; REPEAT ch := type[i]; typ[j] := SHORT(ch); INC(i); INC(j) UNTIL ch = 0X;
- t := Kernel.ThisType(m, typ);
- IF t = NIL THEN typ[j - 1] := "^"; typ[j] := 0X; t := Kernel.ThisType(m, typ) END
- END;
- IF t # NIL THEN
- IF t.id MOD 4 = pointer THEN t := t.base[0] END;
- IF t.id MOD 4 # record THEN t := NIL END
- END;
- RETURN t
- END ThisDesc;
- PROCEDURE GetTypeName* (IN rec: ANYREC; OUT type: ARRAY OF CHAR);
- VAR i, j: INTEGER; ch: CHAR; t: Kernel.Type; name: Kernel.Name;
- BEGIN
- t := Kernel.TypeOf(rec);
- Kernel.GetTypeName(t, name); type := t.mod.name$;
- i := 0; ch := type[0]; WHILE ch # 0X DO INC(i); ch := type[i] END;
- type[i] := "."; INC(i);
- j := 0; REPEAT ch := name[j]; type[i] := ch; INC(i); INC(j) UNTIL ch = 0X;
- IF type[i - 2] = "^" THEN type[i - 2] := 0X END
- END GetTypeName;
- PROCEDURE SameType* (IN ra, rb: ANYREC): BOOLEAN;
- BEGIN
- RETURN Kernel.TypeOf(ra) = Kernel.TypeOf(rb)
- END SameType;
- PROCEDURE IsExtensionOf* (IN ra, rb: ANYREC): BOOLEAN;
- VAR ta, tb: Kernel.Type;
- BEGIN
- ta := Kernel.TypeOf(ra); tb := Kernel.TypeOf(rb);
- RETURN ta.base[tb.id DIV 16 MOD 16] = tb
- END IsExtensionOf;
- PROCEDURE Is* (IN rec: ANYREC; IN type: ARRAY OF CHAR): BOOLEAN;
- VAR ta, tb: Kernel.Type;
- BEGIN
- ta := Kernel.TypeOf(rec); tb := ThisDesc(type, FALSE);
- IF tb # NIL THEN RETURN ta.base[tb.id DIV 16 MOD 16] = tb
- ELSE RETURN FALSE
- END
- END Is;
- PROCEDURE Extends* (IN type, base: ARRAY OF CHAR): BOOLEAN;
- VAR ta, tb: Kernel.Type;
- BEGIN
- ASSERT((type # "") & (base # ""), 20);
- ta := ThisDesc(type, TRUE); tb := ThisDesc(base, FALSE);
- IF (ta # NIL) & (tb # NIL) THEN RETURN ta.base[tb.id DIV 16 MOD 16] = tb
- ELSE RETURN FALSE
- END
- END Extends;
- PROCEDURE Level* (IN type: ARRAY OF CHAR): INTEGER;
- VAR t: Kernel.Type;
- BEGIN
- t := ThisDesc(type, TRUE);
- RETURN t.id DIV 16 MOD 16
- END Level;
- PROCEDURE TypeLevel* (IN rec: ANYREC): INTEGER;
- VAR t: Kernel.Type;
- BEGIN
- t := Kernel.TypeOf(rec);
- IF t = NIL THEN RETURN -1
- ELSE RETURN t.id DIV 16 MOD 16
- END
- END TypeLevel;
- PROCEDURE AdrOf* (IN rec: ANYREC): INTEGER;
- BEGIN
- RETURN SYSTEM.ADR(rec)
- END AdrOf;
- PROCEDURE Collect*;
- BEGIN
- Kernel.FastCollect
- END Collect;
- PROCEDURE Init;
- VAR h: StdHook;
- BEGIN
- NEW(h); actionHook := h
- END Init;
- BEGIN
- Init
- END Services.
|