@thi.ng/fibers 0.6.4 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/README.md +1 -1
- package/api.js +18 -19
- package/csp.js +200 -279
- package/fiber.js +396 -393
- package/ops.js +137 -325
- package/package.json +14 -11
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
package/api.js
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
export const EVENT_FIBER_ERROR = "fiber-error";
|
|
1
|
+
const STATE_NEW = 0;
|
|
2
|
+
const STATE_ACTIVE = 1;
|
|
3
|
+
const STATE_DONE = 2;
|
|
4
|
+
const STATE_CANCELED = 3;
|
|
5
|
+
const STATE_ERROR = 4;
|
|
6
|
+
const EVENT_FIBER_DONE = "fiber-done";
|
|
7
|
+
const EVENT_FIBER_CANCELED = "fiber-canceled";
|
|
8
|
+
const EVENT_FIBER_ERROR = "fiber-error";
|
|
9
|
+
export {
|
|
10
|
+
EVENT_FIBER_CANCELED,
|
|
11
|
+
EVENT_FIBER_DONE,
|
|
12
|
+
EVENT_FIBER_ERROR,
|
|
13
|
+
STATE_ACTIVE,
|
|
14
|
+
STATE_CANCELED,
|
|
15
|
+
STATE_DONE,
|
|
16
|
+
STATE_ERROR,
|
|
17
|
+
STATE_NEW
|
|
18
|
+
};
|
package/csp.js
CHANGED
|
@@ -4,287 +4,208 @@ import { Fiber, fiber } from "./fiber.js";
|
|
|
4
4
|
const STATE_OPEN = 0;
|
|
5
5
|
const STATE_CLOSING = 1;
|
|
6
6
|
const STATE_CLOSED = 2;
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return this.state === STATE_OPEN;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Returns true if the channel is fully closed and no further reads or
|
|
124
|
-
* writes are possible.
|
|
125
|
-
*/
|
|
126
|
-
closed() {
|
|
127
|
-
return this.state === STATE_CLOSED;
|
|
128
|
-
}
|
|
7
|
+
class Channel {
|
|
8
|
+
constructor(buffer = 1, opts) {
|
|
9
|
+
this.opts = opts;
|
|
10
|
+
this.buffer = isNumber(buffer) ? new FIFOBuffer(buffer) : buffer;
|
|
11
|
+
}
|
|
12
|
+
buffer;
|
|
13
|
+
state = STATE_OPEN;
|
|
14
|
+
/**
|
|
15
|
+
* Returns a new fiber which attempts to read a value from the channel and
|
|
16
|
+
* "blocks" until that value is available. Unless the channel has meanwhile
|
|
17
|
+
* been closed, the fiber returns the read value (otherwise: `undefined`).
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* Depending on chosen back buffer behavior/implementation and
|
|
21
|
+
* {@link Channel.close}, read requests might still be successful whilst the
|
|
22
|
+
* channel is closing and there're still buffered values.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const val = yield* chan.read();
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
read() {
|
|
30
|
+
const $this = this;
|
|
31
|
+
return fiber(function* (ctx) {
|
|
32
|
+
while ($this.readable()) {
|
|
33
|
+
if ($this.buffer.readable()) {
|
|
34
|
+
const val = $this.buffer.read();
|
|
35
|
+
ctx.logger?.debug("read", val);
|
|
36
|
+
return val;
|
|
37
|
+
} else if ($this.state === STATE_CLOSING) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
yield;
|
|
41
|
+
}
|
|
42
|
+
}, this.opts);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Returns a new fiber which attempts to write the given `value` to the
|
|
46
|
+
* channel and "blocks" until channel is writable (which depends on the
|
|
47
|
+
* channel's buffer implementation).
|
|
48
|
+
*
|
|
49
|
+
* @remarks
|
|
50
|
+
* Once the channel has been closed (or still is closing, see
|
|
51
|
+
* {@link Channel.close}), all write requests will be silently ignored.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* yield* chan.write(23);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
write(val) {
|
|
59
|
+
const $this = this;
|
|
60
|
+
return fiber(function* (ctx) {
|
|
61
|
+
while ($this.writable()) {
|
|
62
|
+
if ($this.buffer.writable()) {
|
|
63
|
+
ctx.logger?.debug("write", val);
|
|
64
|
+
$this.buffer.write(val);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
yield;
|
|
68
|
+
}
|
|
69
|
+
}, this.opts);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Returns new fiber which closes the channel. By default this op will defer
|
|
73
|
+
* the full closing until all buffered values have been read (by another
|
|
74
|
+
* fiber), however any writes will already become unavailable/ignored even
|
|
75
|
+
* at this stage (also see {@link Channel.write}). If `wait=false`, the
|
|
76
|
+
* channel will be closed immediately, the backing buffered cleared and any
|
|
77
|
+
* in-flight reads or writes will be canceled.
|
|
78
|
+
*
|
|
79
|
+
* @param wait
|
|
80
|
+
*/
|
|
81
|
+
close(wait = true) {
|
|
82
|
+
const $this = this;
|
|
83
|
+
return fiber(function* (ctx) {
|
|
84
|
+
if ($this.state >= STATE_CLOSING)
|
|
85
|
+
return;
|
|
86
|
+
if (wait) {
|
|
87
|
+
ctx.logger?.debug("waiting to close...");
|
|
88
|
+
$this.state = STATE_CLOSING;
|
|
89
|
+
while ($this.buffer.readable())
|
|
90
|
+
yield;
|
|
91
|
+
}
|
|
92
|
+
$this.state = STATE_CLOSED;
|
|
93
|
+
$this.buffer.clear();
|
|
94
|
+
ctx.logger?.debug("channel closed");
|
|
95
|
+
}, this.opts);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Returns true if the channel is principally readable (i.e. not yet
|
|
99
|
+
* closed), however there might not be any values available yet and reads
|
|
100
|
+
* might block.
|
|
101
|
+
*/
|
|
102
|
+
readable() {
|
|
103
|
+
return this.state <= STATE_CLOSING;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Returns true if the channel is principally writable (i.e. not closing or
|
|
107
|
+
* closed), however depending on buffer behavior the channel might not yet
|
|
108
|
+
* accept new values and writes might block.
|
|
109
|
+
*/
|
|
110
|
+
writable() {
|
|
111
|
+
return this.state === STATE_OPEN;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Returns true if the channel is fully closed and no further reads or
|
|
115
|
+
* writes are possible.
|
|
116
|
+
*/
|
|
117
|
+
closed() {
|
|
118
|
+
return this.state === STATE_CLOSED;
|
|
119
|
+
}
|
|
129
120
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
*/
|
|
161
|
-
export class FIFOBuffer {
|
|
162
|
-
buf;
|
|
163
|
-
rpos = 0;
|
|
164
|
-
wpos = 0;
|
|
165
|
-
constructor(cap = 1) {
|
|
166
|
-
assert(cap >= 1, `capacity must be >= 1`);
|
|
167
|
-
this.buf = new Array(cap + 1);
|
|
168
|
-
}
|
|
169
|
-
clear() {
|
|
170
|
-
this.buf.fill(undefined);
|
|
171
|
-
}
|
|
172
|
-
readable() {
|
|
173
|
-
return this.rpos !== this.wpos;
|
|
174
|
-
}
|
|
175
|
-
read() {
|
|
176
|
-
const { buf, rpos } = this;
|
|
177
|
-
const val = buf[rpos];
|
|
178
|
-
buf[rpos] = undefined;
|
|
179
|
-
this.rpos = (rpos + 1) % buf.length;
|
|
180
|
-
return val;
|
|
181
|
-
}
|
|
182
|
-
writable() {
|
|
183
|
-
return (this.wpos + 1) % this.buf.length !== this.rpos;
|
|
184
|
-
}
|
|
185
|
-
write(x) {
|
|
186
|
-
const { buf, wpos } = this;
|
|
187
|
-
buf[wpos] = x;
|
|
188
|
-
this.wpos = (wpos + 1) % buf.length;
|
|
189
|
-
}
|
|
121
|
+
const channel = (buffer, opts) => new Channel(buffer, opts);
|
|
122
|
+
class FIFOBuffer {
|
|
123
|
+
buf;
|
|
124
|
+
rpos = 0;
|
|
125
|
+
wpos = 0;
|
|
126
|
+
constructor(cap = 1) {
|
|
127
|
+
assert(cap >= 1, `capacity must be >= 1`);
|
|
128
|
+
this.buf = new Array(cap + 1);
|
|
129
|
+
}
|
|
130
|
+
clear() {
|
|
131
|
+
this.buf.fill(void 0);
|
|
132
|
+
}
|
|
133
|
+
readable() {
|
|
134
|
+
return this.rpos !== this.wpos;
|
|
135
|
+
}
|
|
136
|
+
read() {
|
|
137
|
+
const { buf, rpos } = this;
|
|
138
|
+
const val = buf[rpos];
|
|
139
|
+
buf[rpos] = void 0;
|
|
140
|
+
this.rpos = (rpos + 1) % buf.length;
|
|
141
|
+
return val;
|
|
142
|
+
}
|
|
143
|
+
writable() {
|
|
144
|
+
return (this.wpos + 1) % this.buf.length !== this.rpos;
|
|
145
|
+
}
|
|
146
|
+
write(x) {
|
|
147
|
+
const { buf, wpos } = this;
|
|
148
|
+
buf[wpos] = x;
|
|
149
|
+
this.wpos = (wpos + 1) % buf.length;
|
|
150
|
+
}
|
|
190
151
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
buf
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
clear() {
|
|
214
|
-
this.buf.length = 0;
|
|
215
|
-
}
|
|
216
|
-
readable() {
|
|
217
|
-
return this.buf.length > 0;
|
|
218
|
-
}
|
|
219
|
-
read() {
|
|
220
|
-
return this.buf.pop();
|
|
221
|
-
}
|
|
222
|
-
writable() {
|
|
223
|
-
return this.buf.length < this.cap;
|
|
224
|
-
}
|
|
225
|
-
write(x) {
|
|
226
|
-
this.buf.push(x);
|
|
227
|
-
}
|
|
152
|
+
const fifo = (cap) => new FIFOBuffer(cap);
|
|
153
|
+
class LIFOBuffer {
|
|
154
|
+
constructor(cap = 1) {
|
|
155
|
+
this.cap = cap;
|
|
156
|
+
assert(cap >= 1, `capacity must be >= 1`);
|
|
157
|
+
}
|
|
158
|
+
buf = [];
|
|
159
|
+
clear() {
|
|
160
|
+
this.buf.length = 0;
|
|
161
|
+
}
|
|
162
|
+
readable() {
|
|
163
|
+
return this.buf.length > 0;
|
|
164
|
+
}
|
|
165
|
+
read() {
|
|
166
|
+
return this.buf.pop();
|
|
167
|
+
}
|
|
168
|
+
writable() {
|
|
169
|
+
return this.buf.length < this.cap;
|
|
170
|
+
}
|
|
171
|
+
write(x) {
|
|
172
|
+
this.buf.push(x);
|
|
173
|
+
}
|
|
228
174
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
writable() {
|
|
243
|
-
return true;
|
|
244
|
-
}
|
|
245
|
-
write(x) {
|
|
246
|
-
if (!super.writable()) {
|
|
247
|
-
const { buf, rpos } = this;
|
|
248
|
-
buf[rpos] = undefined;
|
|
249
|
-
this.rpos = (rpos + 1) % buf.length;
|
|
250
|
-
}
|
|
251
|
-
super.write(x);
|
|
252
|
-
}
|
|
175
|
+
const lifo = (cap) => new LIFOBuffer(cap);
|
|
176
|
+
class SlidingBuffer extends FIFOBuffer {
|
|
177
|
+
writable() {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
write(x) {
|
|
181
|
+
if (!super.writable()) {
|
|
182
|
+
const { buf, rpos } = this;
|
|
183
|
+
buf[rpos] = void 0;
|
|
184
|
+
this.rpos = (rpos + 1) % buf.length;
|
|
185
|
+
}
|
|
186
|
+
super.write(x);
|
|
187
|
+
}
|
|
253
188
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
* Also see {@link dropping} for alternative behavior.
|
|
264
|
-
*
|
|
265
|
-
* @param cap
|
|
266
|
-
*/
|
|
267
|
-
export const sliding = (cap) => new SlidingBuffer(cap);
|
|
268
|
-
export class DroppingBuffer extends FIFOBuffer {
|
|
269
|
-
writable() {
|
|
270
|
-
return true;
|
|
271
|
-
}
|
|
272
|
-
write(x) {
|
|
273
|
-
if (super.writable())
|
|
274
|
-
super.write(x);
|
|
275
|
-
}
|
|
189
|
+
const sliding = (cap) => new SlidingBuffer(cap);
|
|
190
|
+
class DroppingBuffer extends FIFOBuffer {
|
|
191
|
+
writable() {
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
write(x) {
|
|
195
|
+
if (super.writable())
|
|
196
|
+
super.write(x);
|
|
197
|
+
}
|
|
276
198
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
export const dropping = (cap) => new DroppingBuffer(cap);
|
|
199
|
+
const dropping = (cap) => new DroppingBuffer(cap);
|
|
200
|
+
export {
|
|
201
|
+
Channel,
|
|
202
|
+
DroppingBuffer,
|
|
203
|
+
FIFOBuffer,
|
|
204
|
+
LIFOBuffer,
|
|
205
|
+
SlidingBuffer,
|
|
206
|
+
channel,
|
|
207
|
+
dropping,
|
|
208
|
+
fifo,
|
|
209
|
+
lifo,
|
|
210
|
+
sliding
|
|
211
|
+
};
|