Services.txt 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. MODULE Services;
  2. (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 System/Mod/Services.odc *)
  3. (* DO NOT EDIT *)
  4. IMPORT SYSTEM, Kernel;
  5. CONST
  6. now* = 0; immediately* = -1; (** DoLater notBefore **)
  7. resolution* = 1000;
  8. scale = resolution DIV Kernel.timeResolution;
  9. corr = resolution MOD Kernel.timeResolution;
  10. TYPE
  11. Action* = POINTER TO ABSTRACT RECORD
  12. notBefore: LONGINT;
  13. next: Action (* next element in linear list *)
  14. END;
  15. ActionHook* = POINTER TO ABSTRACT RECORD (Kernel.Hook) END;
  16. StdHook = POINTER TO RECORD (ActionHook) END;
  17. VAR
  18. actionHook-: ActionHook;
  19. actions: Action; (* list of actions *)
  20. candidates: Action; (* list of action candidates in IterateOverActions,
  21. NIL during normal execution of commands *)
  22. hasImmediates: BOOLEAN; (* this is a hint: one or more actions in some ring may be immediate actions *)
  23. trapCnt: INTEGER;
  24. PROCEDURE Ticks* (): LONGINT;
  25. VAR t: LONGINT;
  26. BEGIN
  27. t := Kernel.Time();
  28. RETURN t * scale + t * corr DIV Kernel.timeResolution
  29. END Ticks;
  30. (** Action **)
  31. PROCEDURE (a: Action) Do- (), NEW, ABSTRACT;
  32. PROCEDURE In (l, a: Action): BOOLEAN;
  33. BEGIN
  34. WHILE (l # NIL) & (l # a) DO l := l.next END;
  35. RETURN l # NIL
  36. END In;
  37. PROCEDURE Incl (VAR l: Action; a: Action);
  38. BEGIN
  39. IF l # NIL THEN a.next := l END;
  40. l := a
  41. END Incl;
  42. PROCEDURE Excl (VAR l: Action; a: Action);
  43. VAR p0, p1: Action;
  44. BEGIN
  45. IF l = a THEN
  46. l := a.next; a.next := NIL
  47. ELSIF l # NIL THEN
  48. p0 := l; p1 := p0.next;
  49. (* (p0 # NIL) & (p0 # a) *)
  50. WHILE (p1 # NIL) & (p1 # a) DO p0 := p1; p1 := p0.next END;
  51. IF p1 = a THEN p0.next := a.next; a.next := NIL END
  52. END
  53. END Excl;
  54. PROCEDURE Exec (a: Action);
  55. VAR t: Kernel.Type;
  56. BEGIN
  57. t := Kernel.TypeOf(a);
  58. IF t.mod.refcnt >= 0 THEN (* execute action if its module is not unloaded *)
  59. a.Do (* warning: here the actions and candidates lists may be modified, or a trap may occur! *)
  60. END
  61. END Exec;
  62. PROCEDURE Cleanup;
  63. VAR p: Action;
  64. BEGIN
  65. IF candidates # NIL THEN (* trap handling *)
  66. p := candidates; WHILE p.next # NIL DO p := p.next END; (* find last element of candidates list *)
  67. p.next := actions; actions := candidates; candidates := NIL (* prepend candidates list to actions list *)
  68. END;
  69. trapCnt := Kernel.trapCount (* all traps are handled now *)
  70. END Cleanup;
  71. PROCEDURE DoLater* (a: Action; notBefore: LONGINT);
  72. (** Register action a. If a is already registered, its notBefore value is updated instead. **)
  73. BEGIN
  74. ASSERT(a # NIL, 20);
  75. IF ~In(actions, a) & ~In(candidates, a) THEN
  76. Incl(actions, a)
  77. END;
  78. a.notBefore := notBefore; (* if a was already in a list, this statement updates the notBefore value *)
  79. IF notBefore = immediately THEN hasImmediates := TRUE END
  80. END DoLater;
  81. PROCEDURE RemoveAction* (a: Action);
  82. (** Unregister action a. If a is not registered, nothing happens **)
  83. BEGIN
  84. IF a # NIL THEN
  85. Excl(actions, a);
  86. Excl(candidates, a)
  87. END
  88. END RemoveAction;
  89. PROCEDURE IterateOverActions (time: LONGINT);
  90. VAR p: Action;
  91. BEGIN
  92. Cleanup; (* trap handling, if necessary *)
  93. (* candidates = NIL *)
  94. candidates := actions; actions := NIL; (* move action list to candidates list *)
  95. WHILE candidates # NIL DO (* for every candidate: execute it or put it back into actions list *)
  96. p := candidates; candidates := p.next; (* remove head element from candidates list *)
  97. IF (0 <= p.notBefore) & (p.notBefore <= time) OR (p.notBefore <= time) & (time < 0) THEN
  98. p.next := NIL; Exec(p) (* warning: p may call DoLater or RemoveAction,
  99. which change the lists! *)
  100. ELSE
  101. p.next := actions; actions := p (* move to actions list for later processing *)
  102. END
  103. END
  104. END IterateOverActions;
  105. PROCEDURE (h: ActionHook) Step*, NEW, ABSTRACT;
  106. PROCEDURE (h: ActionHook) Loop*, NEW, ABSTRACT;
  107. PROCEDURE (h: StdHook) Step;
  108. BEGIN
  109. IF (candidates = NIL) OR (trapCnt < Kernel.trapCount) THEN
  110. IterateOverActions(Ticks())
  111. END
  112. END Step;
  113. PROCEDURE (h: StdHook) Loop;
  114. BEGIN
  115. IF hasImmediates THEN
  116. ASSERT((candidates = NIL) OR (trapCnt < Kernel.trapCount), 100);
  117. IterateOverActions(immediately);
  118. hasImmediates := FALSE
  119. END
  120. END Loop;
  121. (* type handling functions *)
  122. PROCEDURE ThisDesc (IN type: ARRAY OF CHAR; load: BOOLEAN): Kernel.Type;
  123. CONST record = 1; pointer = 3;
  124. VAR m: Kernel.Module; t: Kernel.Type; i, j: INTEGER; ch: CHAR;
  125. typ: Kernel.Name; mod: ARRAY 256 OF CHAR;
  126. BEGIN
  127. ASSERT(type # "", 20);
  128. i := 0; ch := type[0];
  129. WHILE (ch # ".") & (ch # 0X) DO mod[i] := ch; INC(i); ch := type[i] END;
  130. ASSERT(ch = ".", 21);
  131. mod[i] := 0X; INC(i); t := NIL;
  132. IF load THEN
  133. m := Kernel.ThisMod(mod)
  134. ELSE typ := SHORT(mod$); m := Kernel.ThisLoadedMod(typ)
  135. END;
  136. IF m # NIL THEN
  137. j := 0; REPEAT ch := type[i]; typ[j] := SHORT(ch); INC(i); INC(j) UNTIL ch = 0X;
  138. t := Kernel.ThisType(m, typ);
  139. IF t = NIL THEN typ[j - 1] := "^"; typ[j] := 0X; t := Kernel.ThisType(m, typ) END
  140. END;
  141. IF t # NIL THEN
  142. IF t.id MOD 4 = pointer THEN t := t.base[0] END;
  143. IF t.id MOD 4 # record THEN t := NIL END
  144. END;
  145. RETURN t
  146. END ThisDesc;
  147. PROCEDURE GetTypeName* (IN rec: ANYREC; OUT type: ARRAY OF CHAR);
  148. VAR i, j: INTEGER; ch: CHAR; t: Kernel.Type; name: Kernel.Name;
  149. BEGIN
  150. t := Kernel.TypeOf(rec);
  151. Kernel.GetTypeName(t, name); type := t.mod.name$;
  152. i := 0; ch := type[0]; WHILE ch # 0X DO INC(i); ch := type[i] END;
  153. type[i] := "."; INC(i);
  154. j := 0; REPEAT ch := name[j]; type[i] := ch; INC(i); INC(j) UNTIL ch = 0X;
  155. IF type[i - 2] = "^" THEN type[i - 2] := 0X END
  156. END GetTypeName;
  157. PROCEDURE SameType* (IN ra, rb: ANYREC): BOOLEAN;
  158. BEGIN
  159. RETURN Kernel.TypeOf(ra) = Kernel.TypeOf(rb)
  160. END SameType;
  161. PROCEDURE IsExtensionOf* (IN ra, rb: ANYREC): BOOLEAN;
  162. VAR ta, tb: Kernel.Type;
  163. BEGIN
  164. ta := Kernel.TypeOf(ra); tb := Kernel.TypeOf(rb);
  165. RETURN ta.base[tb.id DIV 16 MOD 16] = tb
  166. END IsExtensionOf;
  167. PROCEDURE Is* (IN rec: ANYREC; IN type: ARRAY OF CHAR): BOOLEAN;
  168. VAR ta, tb: Kernel.Type;
  169. BEGIN
  170. ta := Kernel.TypeOf(rec); tb := ThisDesc(type, FALSE);
  171. IF tb # NIL THEN RETURN ta.base[tb.id DIV 16 MOD 16] = tb
  172. ELSE RETURN FALSE
  173. END
  174. END Is;
  175. PROCEDURE Extends* (IN type, base: ARRAY OF CHAR): BOOLEAN;
  176. VAR ta, tb: Kernel.Type;
  177. BEGIN
  178. ASSERT((type # "") & (base # ""), 20);
  179. ta := ThisDesc(type, TRUE); tb := ThisDesc(base, FALSE);
  180. IF (ta # NIL) & (tb # NIL) THEN RETURN ta.base[tb.id DIV 16 MOD 16] = tb
  181. ELSE RETURN FALSE
  182. END
  183. END Extends;
  184. PROCEDURE Level* (IN type: ARRAY OF CHAR): INTEGER;
  185. VAR t: Kernel.Type;
  186. BEGIN
  187. t := ThisDesc(type, TRUE);
  188. RETURN t.id DIV 16 MOD 16
  189. END Level;
  190. PROCEDURE TypeLevel* (IN rec: ANYREC): INTEGER;
  191. VAR t: Kernel.Type;
  192. BEGIN
  193. t := Kernel.TypeOf(rec);
  194. IF t = NIL THEN RETURN -1
  195. ELSE RETURN t.id DIV 16 MOD 16
  196. END
  197. END TypeLevel;
  198. PROCEDURE AdrOf* (IN rec: ANYREC): INTEGER;
  199. BEGIN
  200. RETURN SYSTEM.ADR(rec)
  201. END AdrOf;
  202. PROCEDURE Collect*;
  203. BEGIN
  204. Kernel.FastCollect
  205. END Collect;
  206. PROCEDURE Init;
  207. VAR h: StdHook;
  208. BEGIN
  209. NEW(h); actionHook := h
  210. END Init;
  211. BEGIN
  212. Init
  213. END Services.