ciorent 0.3.7 → 0.3.8
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/README.md +45 -61
- package/fiber.d.ts +7 -7
- package/lock.d.ts +4 -4
- package/package.json +6 -6
- package/queue.d.ts +8 -11
- package/semaphore.d.ts +3 -3
- package/stream.d.ts +45 -0
- package/stream.js +1 -0
- package/topic.d.ts +26 -37
- package/topic.js +1 -1
- package/channel.d.ts +0 -39
- package/channel.js +0 -1
package/README.md
CHANGED
@@ -32,7 +32,7 @@ Cross-runtime synchronous and asynchronous sleep functions.
|
|
32
32
|
```ts
|
33
33
|
import * as co from 'ciorent';
|
34
34
|
|
35
|
-
const logTime = (label: string) => console.log(`${label}: ${Math.floor(performance.now())}ms`)
|
35
|
+
const logTime = (label: string) => console.log(`${label}: ${Math.floor(performance.now())}ms`);
|
36
36
|
|
37
37
|
logTime('Start');
|
38
38
|
|
@@ -112,39 +112,33 @@ co.spawn(5, task2);
|
|
112
112
|
```
|
113
113
|
|
114
114
|
### Pubsub
|
115
|
-
|
115
|
+
Pubsub allows broadcasting messages to topics that can be recieved by subscribers.
|
116
116
|
|
117
117
|
```ts
|
118
118
|
import * as topic from 'ciorent/topic';
|
119
119
|
import * as co from 'ciorent';
|
120
120
|
|
121
|
-
const
|
122
|
-
|
123
|
-
// A task that publish messages
|
124
|
-
const publisher = async () => {
|
125
|
-
for (let i = 0; i < 3; i++) {
|
126
|
-
await co.sleep(100);
|
127
|
-
topic.publish(messages, i);
|
128
|
-
}
|
129
|
-
|
130
|
-
// Resolve all waiting promises
|
131
|
-
// And clear the value queue
|
132
|
-
topic.flush(messages);
|
133
|
-
}
|
121
|
+
const numbers = topic.init();
|
134
122
|
|
135
|
-
// Spawn 3 tasks that
|
136
|
-
co.spawn(3, async (id
|
137
|
-
const
|
123
|
+
// Spawn 3 tasks that subscribe to the topic
|
124
|
+
co.spawn(3, async (id) => {
|
125
|
+
const subscriber = topic.subscribe(numbers);
|
138
126
|
|
139
127
|
while (true) {
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
console.log(`Task ${id} recieved: ${x}`);
|
128
|
+
const msg = await topic.dispatch(subscriber);
|
129
|
+
if (msg == null) return;
|
130
|
+
console.log('Task', id, 'recieved:', msg);
|
144
131
|
}
|
145
132
|
});
|
146
133
|
|
147
|
-
|
134
|
+
// Publish messages to the topic
|
135
|
+
for (let i = 0; i < 3; i++) {
|
136
|
+
topic.publish(numbers, i);
|
137
|
+
await co.nextTick;
|
138
|
+
}
|
139
|
+
|
140
|
+
// Send undefined to every topic
|
141
|
+
topic.flush(numbers);
|
148
142
|
```
|
149
143
|
|
150
144
|
### Semaphore
|
@@ -176,6 +170,34 @@ const task = async (id: number) => {
|
|
176
170
|
co.spawn(5, task);
|
177
171
|
```
|
178
172
|
|
173
|
+
### Pubsub
|
174
|
+
Pubsub allows broadcasting messages to topics that can be recieved by subscribers.
|
175
|
+
|
176
|
+
```ts
|
177
|
+
import * as stream from 'ciorent/stream';
|
178
|
+
import * as co from 'ciorent';
|
179
|
+
|
180
|
+
const numbers = stream.init();
|
181
|
+
|
182
|
+
// Spawn 3 tasks that read from the stream
|
183
|
+
co.spawn(3, async (id) => {
|
184
|
+
while (true) {
|
185
|
+
const msg = await stream.read(numbers);
|
186
|
+
if (msg == null) return;
|
187
|
+
console.log('Task', id, 'recieved:', msg);
|
188
|
+
}
|
189
|
+
});
|
190
|
+
|
191
|
+
// Write messages to the stream
|
192
|
+
for (let i = 0; i < 3; i++) {
|
193
|
+
stream.write(numbers, i);
|
194
|
+
await co.nextTick;
|
195
|
+
}
|
196
|
+
|
197
|
+
// Send undefined to every stream
|
198
|
+
stream.flush(numbers);
|
199
|
+
```
|
200
|
+
|
179
201
|
### Defer
|
180
202
|
Wait for a value to be resolved.
|
181
203
|
|
@@ -205,44 +227,6 @@ task();
|
|
205
227
|
prepare();
|
206
228
|
```
|
207
229
|
|
208
|
-
### Channel
|
209
|
-
Channel is a synchronization primitive via message passing. A message may be sent over a channel, and another process is able to receive messages sent over a channel it has a reference to.
|
210
|
-
|
211
|
-
```ts
|
212
|
-
import * as channel from 'ciorent/channel';
|
213
|
-
import * as co from 'ciorent';
|
214
|
-
|
215
|
-
const chan = channel.init<number>();
|
216
|
-
|
217
|
-
const run = async () => {
|
218
|
-
for (let i = 0; i < 5; i++) {
|
219
|
-
await co.sleep(100);
|
220
|
-
channel.send(chan, i);
|
221
|
-
console.log('Sent', i);
|
222
|
-
}
|
223
|
-
|
224
|
-
// Resolve all waiting promises with `undefined`
|
225
|
-
// This is a way to tell the reciever to not listen to more data
|
226
|
-
channel.flush(chan);
|
227
|
-
};
|
228
|
-
|
229
|
-
const log = async () => {
|
230
|
-
while (true) {
|
231
|
-
// Wait until a value is sent to the channel
|
232
|
-
const x = await channel.recieve(chan);
|
233
|
-
if (x == null) break;
|
234
|
-
|
235
|
-
console.log('Recieved', x);
|
236
|
-
};
|
237
|
-
}
|
238
|
-
|
239
|
-
log();
|
240
|
-
run();
|
241
|
-
|
242
|
-
// This runs first
|
243
|
-
console.log('Starting...');
|
244
|
-
```
|
245
|
-
|
246
230
|
### Fibers
|
247
231
|
Virtual threads with more controlled execution.
|
248
232
|
|
package/fiber.d.ts
CHANGED
@@ -4,24 +4,24 @@
|
|
4
4
|
/**
|
5
5
|
* Describe a fiber process
|
6
6
|
*/
|
7
|
-
export
|
7
|
+
export type Process<TReturn = unknown> = [
|
8
8
|
/**
|
9
9
|
* The waiting promise
|
10
10
|
*/
|
11
|
-
|
11
|
+
proc: Promise<TReturn | undefined>,
|
12
12
|
/**
|
13
13
|
* Fiber status
|
14
14
|
*/
|
15
|
-
|
15
|
+
status: 0 | 1 | 2 | 3,
|
16
16
|
/**
|
17
|
-
* Callback to
|
17
|
+
* Callback to resume the fiber
|
18
18
|
*/
|
19
|
-
|
19
|
+
resume: null | ((state: 1 | 3) => void),
|
20
20
|
/**
|
21
21
|
* Bounded fibers
|
22
22
|
*/
|
23
|
-
|
24
|
-
|
23
|
+
children: Process[]
|
24
|
+
];
|
25
25
|
/**
|
26
26
|
* Describe a fiber runtime
|
27
27
|
*/
|
package/lock.d.ts
CHANGED
@@ -5,16 +5,16 @@ import type { Node as QueueNode } from './queue.js';
|
|
5
5
|
/**
|
6
6
|
* Describe a lock
|
7
7
|
*/
|
8
|
-
export
|
8
|
+
export type Lock<T = any> = [
|
9
9
|
/**
|
10
10
|
* The head of the Promise resolve queue
|
11
11
|
*/
|
12
|
-
|
12
|
+
head: QueueNode<(value?: T) => void>,
|
13
13
|
/**
|
14
14
|
* The tail of the Promise resolve queue
|
15
15
|
*/
|
16
|
-
|
17
|
-
|
16
|
+
tail: QueueNode<(value?: T) => void>
|
17
|
+
];
|
18
18
|
/**
|
19
19
|
* Release an item
|
20
20
|
* @param lock
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "ciorent",
|
3
|
-
"version": "0.3.
|
3
|
+
"version": "0.3.8",
|
4
4
|
"description": "A lightweight, low-overhead concurrency library",
|
5
5
|
"homepage": "https://ciorent.netlify.app",
|
6
6
|
"repository": {
|
@@ -19,14 +19,14 @@
|
|
19
19
|
"types": "./index.d.ts",
|
20
20
|
"exports": {
|
21
21
|
"./queue": "./queue.js",
|
22
|
-
"./channel": "./channel.js",
|
23
22
|
"./sliding-queue": "./sliding-queue.js",
|
24
|
-
"./
|
25
|
-
"./lock": "./lock.js",
|
26
|
-
".": "./index.js",
|
23
|
+
"./dropping-queue": "./dropping-queue.js",
|
27
24
|
"./semaphore": "./semaphore.js",
|
25
|
+
"./lock": "./lock.js",
|
28
26
|
"./defer": "./defer.js",
|
29
|
-
"
|
27
|
+
".": "./index.js",
|
28
|
+
"./stream": "./stream.js",
|
29
|
+
"./topic": "./topic.js",
|
30
30
|
"./fiber": "./fiber.js"
|
31
31
|
}
|
32
32
|
}
|
package/queue.d.ts
CHANGED
@@ -4,33 +4,30 @@
|
|
4
4
|
/**
|
5
5
|
* Describe a fixed-sized queue
|
6
6
|
*/
|
7
|
-
export
|
7
|
+
export type Fixed<T extends {} = {}> = [
|
8
8
|
/**
|
9
9
|
* Pre-allocated queue
|
10
10
|
*/
|
11
|
-
|
11
|
+
buffer: (T | undefined | null)[],
|
12
12
|
/**
|
13
13
|
* Queue capacity
|
14
14
|
*/
|
15
|
-
|
15
|
+
capacity: number,
|
16
16
|
/**
|
17
17
|
* Head pointer
|
18
18
|
*/
|
19
|
-
|
19
|
+
head: number,
|
20
20
|
/**
|
21
21
|
* Tail pointer
|
22
22
|
*/
|
23
|
-
|
24
|
-
|
23
|
+
tail: number
|
24
|
+
];
|
25
25
|
/**
|
26
26
|
* Describe a queue node (singly linked list node)
|
27
27
|
*/
|
28
|
-
export
|
29
|
-
0: Node<T> | null;
|
30
|
-
1: T;
|
31
|
-
}
|
28
|
+
export type Node<T> = [next: Node<T> | null, value: T];
|
32
29
|
/**
|
33
30
|
* Create a fixed queue
|
34
31
|
* @param n - The queue size
|
35
32
|
*/
|
36
|
-
export declare const fixed: <T extends {}>(n: number) => Fixed<T>;
|
33
|
+
export declare const fixed: <T extends {} = {}>(n: number) => Fixed<T>;
|
package/semaphore.d.ts
CHANGED
@@ -5,12 +5,12 @@ import { type Lock } from './lock.js';
|
|
5
5
|
/**
|
6
6
|
* Describe a semaphore
|
7
7
|
*/
|
8
|
-
export
|
8
|
+
export type Semaphore = Lock<void, [
|
9
9
|
/**
|
10
10
|
* Current remaining process allowed
|
11
11
|
*/
|
12
|
-
|
13
|
-
|
12
|
+
remain: number
|
13
|
+
]>;
|
14
14
|
/**
|
15
15
|
* Create a semaphore that allows n accesses
|
16
16
|
*/
|
package/stream.d.ts
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
/**
|
2
|
+
* @module Streams
|
3
|
+
*/
|
4
|
+
import type { Node as QueueNode } from './queue.js';
|
5
|
+
import type { AcquireCallback } from './lock.js';
|
6
|
+
/**
|
7
|
+
* Describe a stream
|
8
|
+
*/
|
9
|
+
export type Stream<T extends {} = {}> = [
|
10
|
+
/**
|
11
|
+
* Queue head
|
12
|
+
*/
|
13
|
+
head: QueueNode<T | ((val?: T) => void)>,
|
14
|
+
/**
|
15
|
+
* Queue tail
|
16
|
+
*/
|
17
|
+
tail: QueueNode<T | ((val?: T) => void)>,
|
18
|
+
/**
|
19
|
+
* Whether the queue is containing items
|
20
|
+
*/
|
21
|
+
queueing: boolean,
|
22
|
+
/**
|
23
|
+
* Cached callback
|
24
|
+
*/
|
25
|
+
callback: AcquireCallback<T>
|
26
|
+
];
|
27
|
+
/**
|
28
|
+
* Create a stream
|
29
|
+
*/
|
30
|
+
export declare const init: <T extends {} = {}>() => Stream<T>;
|
31
|
+
/**
|
32
|
+
* Write a value to the stream
|
33
|
+
* @param s
|
34
|
+
* @param v
|
35
|
+
*/
|
36
|
+
export declare const write: <T extends {} = {}>(s: Stream<T>, v: T) => void;
|
37
|
+
/**
|
38
|
+
* Read a value from the stream
|
39
|
+
* @param s
|
40
|
+
*/
|
41
|
+
export declare const read: <T extends {} = {}>(s: Stream<T>) => Promise<T | undefined>;
|
42
|
+
/**
|
43
|
+
* Release all pending read with undefined
|
44
|
+
*/
|
45
|
+
export declare const flush: (s: Stream) => void;
|
package/stream.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export let init=()=>{let queue=[null];let s=[queue,queue,false,(res)=>{s[0]=s[0][0]=[null,res]}];return s};export let write=(s,v)=>{if(!s[2]){if(s[1][0]!==null){(s[1]=s[1][0])[1](v);return}s[2]=true}s[0]=s[0][0]=[null,v]};export let read=(s)=>{if(s[2]){s[1]=s[1][0];if(s[1][0]===null)s[2]=false;return Promise.resolve(s[1][1])}return new Promise(s[3])};export let flush=(s)=>{if(!s[2])while(s[1][0]!==null)(s[1]=s[1][0])[1]()};
|
package/topic.d.ts
CHANGED
@@ -1,57 +1,46 @@
|
|
1
1
|
/**
|
2
2
|
* @module Pubsub
|
3
3
|
*/
|
4
|
-
import type {
|
4
|
+
import type { AcquireCallback } from "./lock.js";
|
5
|
+
import type { Node as QueueNode } from "./queue.js";
|
5
6
|
/**
|
6
7
|
* Describe a topic
|
7
8
|
*/
|
8
|
-
export
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
* The waiting subscriber resolves
|
15
|
-
*/
|
16
|
-
1: ((res: QueueNode<T>) => void)[];
|
17
|
-
}
|
9
|
+
export type Topic<T extends {} = {}> = [
|
10
|
+
head: QueueNode<T>,
|
11
|
+
callback: AcquireCallback<void>,
|
12
|
+
resolve: (() => void) | null,
|
13
|
+
pending: Promise<void> | null
|
14
|
+
];
|
18
15
|
/**
|
19
|
-
*
|
20
|
-
*/
|
21
|
-
export declare const init: <T extends {}>() => Topic<T>;
|
22
|
-
/**
|
23
|
-
* Describe a topic
|
16
|
+
* Describe a subscriber
|
24
17
|
*/
|
25
|
-
export
|
26
|
-
|
27
|
-
|
28
|
-
|
18
|
+
export type Subscriber<T extends {} = {}> = [
|
19
|
+
topic: Topic<T>,
|
20
|
+
tail: QueueNode<T>
|
21
|
+
];
|
29
22
|
/**
|
30
|
-
*
|
31
|
-
* @param t
|
23
|
+
* Create a topic
|
32
24
|
*/
|
33
|
-
export declare const
|
25
|
+
export declare const init: <T extends {} = {}>() => Topic<T>;
|
34
26
|
/**
|
35
|
-
* Publish to
|
36
|
-
* @param t
|
27
|
+
* Publish a message to the topic
|
28
|
+
* @param t - The topic
|
29
|
+
* @param m - The message to publish
|
37
30
|
*/
|
38
|
-
export declare const publish: <T extends {}>(t: Topic<T>,
|
31
|
+
export declare const publish: <T extends {} = {}>(t: Topic<T>, m: T) => void;
|
39
32
|
/**
|
40
|
-
* Resolve all
|
41
|
-
* @param t
|
33
|
+
* Resolve all pending dispatch
|
42
34
|
*/
|
43
|
-
export declare const flush:
|
35
|
+
export declare const flush: (t: Topic) => void;
|
44
36
|
/**
|
45
|
-
*
|
46
|
-
*
|
47
|
-
* Returns `undefined` if the message queue is empty
|
37
|
+
* Subscribe to a topic
|
48
38
|
* @param t
|
39
|
+
* @returns A subscriber object
|
49
40
|
*/
|
50
|
-
export declare const
|
41
|
+
export declare const subscribe: <T extends {}>(t: Topic<T>) => Subscriber<T>;
|
51
42
|
/**
|
52
|
-
*
|
53
|
-
*
|
54
|
-
* Returns a promise that resolves when the message queue is not empty
|
43
|
+
* Wait for messages from the topic
|
55
44
|
* @param t
|
56
45
|
*/
|
57
|
-
export declare const dispatch: <T extends {}>(
|
46
|
+
export declare const dispatch: <T extends {}>(s: Subscriber<T>) => Promise<T | undefined>;
|
package/topic.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export let init=()=>{let t=[[null],
|
1
|
+
export let init=()=>{let t=[[null],(res)=>{t[2]=res},null,null];return t};export let publish=(t,m)=>{t[0]=t[0][0]=[null,m];t[2]?.();t[2]=null};export let flush=publish;export let subscribe=(t)=>[t,t[0]];export let dispatch=async(s)=>{if(s[1][0]===null)await(s[0][2]!==null?s[0][3]:s[0][3]=new Promise(s[0][1]));return(s[1]=s[1][0])[1]};
|
package/channel.d.ts
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @module Channels
|
3
|
-
*/
|
4
|
-
import type { Node as QueueNode } from './queue.js';
|
5
|
-
import { type Lock } from './lock.js';
|
6
|
-
/**
|
7
|
-
* Describe a channel
|
8
|
-
*/
|
9
|
-
export interface Channel<T = any> extends Lock<T> {
|
10
|
-
/**
|
11
|
-
* The head of the value queue
|
12
|
-
*/
|
13
|
-
3: QueueNode<T>;
|
14
|
-
/**
|
15
|
-
* The tail of the value queue
|
16
|
-
*/
|
17
|
-
4: QueueNode<T>;
|
18
|
-
}
|
19
|
-
/**
|
20
|
-
* Create a channel
|
21
|
-
*/
|
22
|
-
export declare const init: <T extends {}>() => Channel<T>;
|
23
|
-
/**
|
24
|
-
* Send a message to a channel
|
25
|
-
* @param c - The channel to send to
|
26
|
-
* @param t - The message to send
|
27
|
-
*/
|
28
|
-
export declare const send: <T>(c: Channel<T>, t: T) => void;
|
29
|
-
/**
|
30
|
-
* Recieve a message from a channel, return null if the channel is closed
|
31
|
-
* @param c
|
32
|
-
*/
|
33
|
-
export declare const recieve: <T>(c: Channel<T>) => Promise<T | undefined>;
|
34
|
-
/**
|
35
|
-
* Recieve a message from a channel, return undefined if no message is currently in queue
|
36
|
-
* @param c
|
37
|
-
*/
|
38
|
-
export declare const poll: <T>(c: Channel<T>) => T | undefined;
|
39
|
-
export { flush } from './lock.js';
|
package/channel.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
import{release as lockRelease,released as lockReleased}from"./lock.js";export let init=()=>{let resolveQu=[null];let qu=[null];let chan=[resolveQu,resolveQu,(res)=>{chan[0]=chan[0][0]=[null,res]},qu,qu];return chan};export let send=(c,t)=>{if(lockReleased(c))c[3]=c[3][0]=[null,t];else lockRelease(c,t)};export let recieve=(c)=>c[4][0]!==null?Promise.resolve((c[4]=c[4][0])[1]):new Promise(c[2]);export let poll=(c)=>c[4][0]!==null?(c[4]=c[4][0])[1]:undefined;export{flush}from"./lock.js";
|