1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | Object.defineProperty(exports, "__esModule", { value: true });
|
9 | const list_1 = require("./list");
|
10 | const cancellation_1 = require("./cancellation");
|
11 | const utils_1 = require("./utils");
|
12 | const adapter_1 = require("./adapter");
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | class Barrier {
|
18 | |
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | constructor(participantCount, postPhaseAction) {
|
25 | this._isExecutingPostPhaseAction = false;
|
26 | this._phaseNumber = 0;
|
27 | this._waiters = new list_1.LinkedList();
|
28 | if (!utils_1.isNumber(participantCount))
|
29 | throw new TypeError("Number expected: participantCount.");
|
30 | if ((participantCount |= 0) < 0)
|
31 | throw new RangeError("Argument out of range: participantCount.");
|
32 | if (!utils_1.isFunction(postPhaseAction, true))
|
33 | throw new TypeError("Function expected: postPhaseAction.");
|
34 | this._participantCount = participantCount;
|
35 | this._remainingParticipants = participantCount;
|
36 | this._postPhaseAction = postPhaseAction;
|
37 | }
|
38 | |
39 |
|
40 |
|
41 | get currentPhaseNumber() {
|
42 | return this._phaseNumber;
|
43 | }
|
44 | |
45 |
|
46 |
|
47 | get participantCount() {
|
48 | return this._participantCount;
|
49 | }
|
50 | |
51 |
|
52 |
|
53 | get remainingParticipants() {
|
54 | return this._remainingParticipants;
|
55 | }
|
56 | |
57 |
|
58 |
|
59 |
|
60 |
|
61 | add(participantCount) {
|
62 | if (utils_1.isMissing(participantCount))
|
63 | participantCount = 1;
|
64 | if (!utils_1.isNumber(participantCount))
|
65 | throw new TypeError("Number expected: participantCount.");
|
66 | if ((participantCount |= 0) <= 0)
|
67 | throw new RangeError("Argument out of range: participantCount.");
|
68 | if (this._isExecutingPostPhaseAction)
|
69 | throw new Error("This method may not be called from within the postPhaseAction.");
|
70 | this._participantCount += participantCount;
|
71 | this._remainingParticipants += participantCount;
|
72 | }
|
73 | |
74 |
|
75 |
|
76 |
|
77 |
|
78 | remove(participantCount) {
|
79 | if (utils_1.isMissing(participantCount))
|
80 | participantCount = 1;
|
81 | if (!utils_1.isNumber(participantCount))
|
82 | throw new TypeError("Number expected: participantCount.");
|
83 | if ((participantCount |= 0) <= 0)
|
84 | throw new RangeError("Argument out of range: participantCount.");
|
85 | if (this._participantCount < participantCount)
|
86 | throw new RangeError("Argument out of range: participantCount.");
|
87 | if (this._isExecutingPostPhaseAction)
|
88 | throw new Error("This method may not be called from within the postPhaseAction.");
|
89 | this._participantCount -= participantCount;
|
90 | this._remainingParticipants -= participantCount;
|
91 | if (this._participantCount === 0) {
|
92 | this._finishPhase();
|
93 | }
|
94 | }
|
95 | |
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 | signalAndWait(token) {
|
102 | return new Promise((resolve, reject) => {
|
103 | const _token = adapter_1.getToken(token);
|
104 | _token.throwIfCancellationRequested();
|
105 | if (this._isExecutingPostPhaseAction)
|
106 | throw new Error("This method may not be called from within the postPhaseAction.");
|
107 | if (this._participantCount === 0)
|
108 | throw new Error("The barrier has no registered participants.");
|
109 | if (this._remainingParticipants === 0)
|
110 | throw new Error("The number of operations using the barrier exceeded the number of registered participants.");
|
111 | const node = this._waiters.push({
|
112 | resolve: () => {
|
113 | registration.unregister();
|
114 | if (_token.cancellationRequested) {
|
115 | reject(new cancellation_1.CancelError());
|
116 | }
|
117 | else {
|
118 | resolve();
|
119 | }
|
120 | },
|
121 | reject: reason => {
|
122 | registration.unregister();
|
123 | if (_token.cancellationRequested) {
|
124 | reject(new cancellation_1.CancelError());
|
125 | }
|
126 | else {
|
127 | reject(reason);
|
128 | }
|
129 | }
|
130 | });
|
131 | const registration = _token.register(() => {
|
132 | if (node.list) {
|
133 | node.list.deleteNode(node);
|
134 | reject(new cancellation_1.CancelError());
|
135 | }
|
136 | });
|
137 | this._remainingParticipants--;
|
138 | if (this._remainingParticipants === 0) {
|
139 | this._finishPhase();
|
140 | }
|
141 | });
|
142 | }
|
143 | _finishPhase() {
|
144 | const postPhaseAction = this._postPhaseAction;
|
145 | if (postPhaseAction) {
|
146 | this._isExecutingPostPhaseAction = true;
|
147 | Promise
|
148 | .resolve()
|
149 | .then(() => postPhaseAction(this))
|
150 | .then(() => this._resolveNextPhase(), error => this._rejectNextPhase(error));
|
151 | }
|
152 | else {
|
153 | Promise
|
154 | .resolve()
|
155 | .then(() => this._resolveNextPhase());
|
156 | }
|
157 | }
|
158 | _nextPhase() {
|
159 | this._isExecutingPostPhaseAction = false;
|
160 | this._remainingParticipants = this._participantCount;
|
161 | this._phaseNumber++;
|
162 | }
|
163 | _resolveNextPhase() {
|
164 | this._nextPhase();
|
165 | for (const deferred of this._waiters.drain()) {
|
166 | if (deferred)
|
167 | deferred.resolve();
|
168 | }
|
169 | }
|
170 | _rejectNextPhase(error) {
|
171 | this._nextPhase();
|
172 | for (const deferred of this._waiters.drain()) {
|
173 | if (deferred)
|
174 | deferred.reject(error);
|
175 | }
|
176 | }
|
177 | }
|
178 | exports.Barrier = Barrier;
|