-
Notifications
You must be signed in to change notification settings - Fork 0
/
queues.mod
70 lines (63 loc) · 1.66 KB
/
queues.mod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
IMPLEMENTATION MODULE Queues;
FROM STORAGE IMPORT ALLOCATE;
FROM SYSTEM IMPORT ADDRESS;
IMPORT Processes;
TYPE Queue = POINTER TO
RECORD
start, end, putPtr, getPtr, last : ADDRESS;
dataReady : Processes.SIGNAL;
elemSize, nbSent : CARDINAL;
END;
PROCEDURE Enqueue(queue : Queue; VAR elem : ARRAY OF WORD);
VAR i : CARDINAL;
BEGIN
WITH queue^ DO
last := putPtr;
FOR i:=0 TO elemSize-1 DO putPtr^ := elem[i]; INC(putPtr,2) END;
IF putPtr = end THEN putPtr := start END;
IF putPtr = getPtr THEN RAISE QueueOverflow END;
INC(nbSent);
Processes.SEND(dataReady);
END;
END Enqueue;
PROCEDURE Dequeue(queue : Queue; VAR elem : ARRAY OF WORD);
VAR i : CARDINAL;
BEGIN
WITH queue^ DO
IF putPtr = getPtr THEN Processes.WAIT(dataReady) END;
FOR i:=0 TO elemSize-1 DO elem[i]:=getPtr^ ; INC(getPtr,2) END;
IF getPtr = end THEN getPtr := start END;
END;
END Dequeue;
PROCEDURE Last(queue : Queue; VAR elem : ARRAY OF WORD);
VAR i : CARDINAL;
lastPtr : ADDRESS;
BEGIN
WITH queue^ DO
IF getPtr = putPtr THEN RAISE EmptyQueue END;
lastPtr := last;
FOR i:=0 TO elemSize-1 DO elem[i]:=lastPtr^ ; INC(lastPtr,2) END
END
END Last;
PROCEDURE Count(queue : Queue) : CARDINAL;
BEGIN
RETURN queue^.nbSent;
END Count;
PROCEDURE New(queueLength, nbWords : CARDINAL) : Queue;
VAR queue : Queue;
totalSize : CARDINAL;
BEGIN
NEW(queue);
WITH queue^ DO
elemSize := nbWords;
totalSize := queueLength*nbWords*2;
ALLOCATE(start,totalSize);
end := start + totalSize;
putPtr := start;
getPtr := start;
nbSent := 0;
Processes.Init(dataReady);
END;
RETURN queue;
END New;
END Queues.