ciorent 0.0.18 → 0.0.21
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 +71 -70
- package/fiber.d.ts +91 -0
- package/fiber.js +1 -0
- package/package.json +7 -8
- package/concurrent.d.ts +0 -11
- package/fiber/index.d.ts +0 -74
- package/fiber/index.js +0 -1
package/README.md
CHANGED
@@ -30,70 +30,74 @@ Virtual threads with more controlled execution.
|
|
30
30
|
import * as cio from 'ciorent';
|
31
31
|
import * as fiber from 'ciorent/fiber';
|
32
32
|
|
33
|
-
function*
|
33
|
+
const thread1 = fiber.fn(function* () {
|
34
34
|
console.log('Fiber 1 started');
|
35
|
-
|
35
|
+
|
36
|
+
// Thread1 will be interrupted by thread2
|
37
|
+
// As thread2 will end first
|
38
|
+
yield cio.sleep(1000);
|
39
|
+
|
36
40
|
console.log('Fiber 1 done');
|
37
|
-
}
|
41
|
+
});
|
38
42
|
|
39
|
-
function*
|
43
|
+
const thread2 = fiber.fn(function* (thread) {
|
40
44
|
console.log('Fiber 2 started');
|
41
45
|
|
42
46
|
yield;
|
43
47
|
console.log('Fiber 2 resumed');
|
44
48
|
|
45
|
-
//
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
// Start task 1 and wait for it to be done
|
50
|
-
yield* fiber.join(
|
51
|
-
fiber.start(thread1())
|
52
|
-
);
|
49
|
+
// Start thread 1 and make thread1
|
50
|
+
// lifetime depends on thread2
|
51
|
+
fiber.mount(fiber.start(thread1), thread);
|
53
52
|
|
54
53
|
console.log('Fiber 2 done');
|
55
|
-
}
|
54
|
+
});
|
56
55
|
|
57
56
|
// Start running the thread
|
58
|
-
fiber.start(thread2
|
57
|
+
fiber.start(thread2);
|
59
58
|
```
|
60
59
|
|
61
|
-
##
|
62
|
-
|
60
|
+
## Latch
|
61
|
+
Latch is a synchronization primitive that allows one process to wait until another completes an operation before continuing execution.
|
63
62
|
|
64
63
|
```ts
|
65
|
-
import * as
|
64
|
+
import * as latch from 'ciorent/latch';
|
66
65
|
import * as cio from 'ciorent';
|
67
66
|
|
68
|
-
const
|
67
|
+
const fetchLatch = latch.init();
|
69
68
|
|
70
|
-
const
|
71
|
-
|
72
|
-
|
73
|
-
channel.send(c, i);
|
74
|
-
console.log('Sent', i);
|
75
|
-
}
|
69
|
+
const task = async () => {
|
70
|
+
// Blocks until the latch is open
|
71
|
+
await latch.pause(fetchLatch);
|
76
72
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
};
|
73
|
+
const res = await fetch('http://example.com');
|
74
|
+
console.log('Fetch status:', res.status);
|
75
|
+
}
|
81
76
|
|
82
|
-
const
|
83
|
-
|
84
|
-
|
85
|
-
const x = await channel.recieve(c);
|
86
|
-
if (x == null) break;
|
77
|
+
const prepare = () => {
|
78
|
+
console.log('Run before fetch:', performance.now().toFixed(2));
|
79
|
+
}
|
87
80
|
|
88
|
-
|
89
|
-
|
81
|
+
const main = async () => {
|
82
|
+
const p = task();
|
83
|
+
await cio.sleep(500);
|
84
|
+
prepare();
|
85
|
+
|
86
|
+
// Allows all previously blocked tasks to run
|
87
|
+
latch.open(fetchLatch);
|
88
|
+
|
89
|
+
// Reclose the latch
|
90
|
+
// Tasks that aren't blocked yet will be blocked
|
91
|
+
latch.reset(fetchLatch);
|
92
|
+
|
93
|
+
return p;
|
90
94
|
}
|
91
95
|
|
92
|
-
|
93
|
-
|
96
|
+
// Run fetch after 500ms
|
97
|
+
await main();
|
94
98
|
|
95
|
-
//
|
96
|
-
|
99
|
+
// Run fetch after another 500ms
|
100
|
+
await main();
|
97
101
|
```
|
98
102
|
|
99
103
|
## Pubsub
|
@@ -132,47 +136,42 @@ cio.concurrent(5, async (id: number) => {
|
|
132
136
|
publisher();
|
133
137
|
```
|
134
138
|
|
135
|
-
##
|
136
|
-
|
139
|
+
## Channel
|
140
|
+
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.
|
137
141
|
|
138
142
|
```ts
|
139
|
-
import * as
|
143
|
+
import * as channel from 'ciorent/channel';
|
140
144
|
import * as cio from 'ciorent';
|
141
145
|
|
142
|
-
const
|
143
|
-
|
144
|
-
const task = async () => {
|
145
|
-
// Blocks until the latch is open
|
146
|
-
await latch.pause(fetchLatch);
|
147
|
-
|
148
|
-
const res = await fetch('http://example.com');
|
149
|
-
console.log('Fetch status:', res.status);
|
150
|
-
}
|
151
|
-
|
152
|
-
const prepare = () => {
|
153
|
-
console.log('Run before fetch:', performance.now().toFixed(2));
|
154
|
-
}
|
146
|
+
const c = channel.init<number>();
|
155
147
|
|
156
|
-
const
|
157
|
-
|
158
|
-
|
159
|
-
|
148
|
+
const run = async () => {
|
149
|
+
for (let i = 0; i < 10; i++) {
|
150
|
+
await cio.sleep(10);
|
151
|
+
channel.send(c, i);
|
152
|
+
console.log('Sent', i);
|
153
|
+
}
|
160
154
|
|
161
|
-
//
|
162
|
-
|
155
|
+
// Resolve all waiting promises with `undefined`
|
156
|
+
// This is a way to tell the reciever to not listen to more data
|
157
|
+
channel.flush(c);
|
158
|
+
};
|
163
159
|
|
164
|
-
|
165
|
-
|
166
|
-
|
160
|
+
const log = async () => {
|
161
|
+
while (true) {
|
162
|
+
// Wait until a value is sent
|
163
|
+
const x = await channel.recieve(c);
|
164
|
+
if (x == null) break;
|
167
165
|
|
168
|
-
|
166
|
+
console.log('Recieved', x);
|
167
|
+
};
|
169
168
|
}
|
170
169
|
|
171
|
-
|
172
|
-
|
170
|
+
run();
|
171
|
+
log();
|
173
172
|
|
174
|
-
//
|
175
|
-
|
173
|
+
// This runs first
|
174
|
+
console.log('Starting...');
|
176
175
|
```
|
177
176
|
|
178
177
|
## Utilities
|
@@ -207,13 +206,15 @@ task2();
|
|
207
206
|
```
|
208
207
|
|
209
208
|
### Sleep
|
210
|
-
|
209
|
+
Cross-runtime synchronous and asynchronous sleep functions.
|
211
210
|
```ts
|
212
211
|
import { sleep, sleepSync } from 'ciorent';
|
213
212
|
|
214
213
|
await sleep(500);
|
215
214
|
console.log('Hi');
|
216
215
|
|
216
|
+
// This blocks the current thread
|
217
|
+
// On the browser this only works in workers
|
217
218
|
sleepSync(500);
|
218
219
|
console.log('Hi');
|
219
220
|
```
|
package/fiber.d.ts
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
/**
|
2
|
+
* @module Fibers
|
3
|
+
*/
|
4
|
+
/**
|
5
|
+
* Check whether the fiber is paused
|
6
|
+
*/
|
7
|
+
export declare const paused: (t: Thread) => boolean;
|
8
|
+
/**
|
9
|
+
* Check whether the fiber is running
|
10
|
+
*/
|
11
|
+
export declare const running: (t: Thread) => boolean;
|
12
|
+
/**
|
13
|
+
* Check whether the fiber is done
|
14
|
+
*/
|
15
|
+
export declare const done: (t: Thread) => boolean;
|
16
|
+
/**
|
17
|
+
* Describe a fiber
|
18
|
+
*/
|
19
|
+
export interface Thread<T = unknown, TReturn = unknown> {
|
20
|
+
/**
|
21
|
+
* The waiting promise
|
22
|
+
*/
|
23
|
+
0: Promise<T | TReturn>;
|
24
|
+
/**
|
25
|
+
* Fiber status
|
26
|
+
*/
|
27
|
+
1: 0 | 1 | 2;
|
28
|
+
/**
|
29
|
+
* Callback to continue running the fiber
|
30
|
+
*/
|
31
|
+
2: null | (() => void);
|
32
|
+
/**
|
33
|
+
* Bounded threads
|
34
|
+
*/
|
35
|
+
3: Thread[];
|
36
|
+
}
|
37
|
+
/**
|
38
|
+
* Describe a fiber runtime
|
39
|
+
*/
|
40
|
+
export type Runtime = <const T, const TReturn, const Args extends any[]>(gen: (thread: Thread<T, TReturn>, ...args: Args) => Generator<T, TReturn>, ...args: Args) => Thread<T, TReturn>;
|
41
|
+
/**
|
42
|
+
* Create a fiber function
|
43
|
+
* @param f
|
44
|
+
*/
|
45
|
+
export declare const fn: <const Fn extends (thread: Thread, ...args: any[]) => Generator>(f: Fn) => Fn;
|
46
|
+
/**
|
47
|
+
* A basic fiber runtime
|
48
|
+
* @param g
|
49
|
+
*/
|
50
|
+
export declare const start: Runtime;
|
51
|
+
/**
|
52
|
+
* Pause the execution of a fiber
|
53
|
+
* @param t
|
54
|
+
*/
|
55
|
+
export declare const pause: (t: Thread) => void;
|
56
|
+
/**
|
57
|
+
* Resume the execution of a fiber
|
58
|
+
* @param t
|
59
|
+
*/
|
60
|
+
export declare const resume: (t: Thread) => void;
|
61
|
+
/**
|
62
|
+
* Stop the execution of a fiber
|
63
|
+
* @param t
|
64
|
+
*/
|
65
|
+
export declare const stop: (t: Thread) => void;
|
66
|
+
/**
|
67
|
+
* Wait for a fiber and retrieve its result
|
68
|
+
* @param t
|
69
|
+
*/
|
70
|
+
export declare function join<T extends Thread>(t: T): Generator<Awaited<T[1]>, Awaited<T[1]>>;
|
71
|
+
/**
|
72
|
+
* Wait for a fiber to finish and retrieve its result
|
73
|
+
* @param t
|
74
|
+
*/
|
75
|
+
export declare const finish: <T extends Thread>(t: T) => T[1];
|
76
|
+
/**
|
77
|
+
* Mount child fiber lifetime to parent lifetime
|
78
|
+
* @param child
|
79
|
+
* @param parent
|
80
|
+
*/
|
81
|
+
export declare const mount: (child: Thread, parent: Thread) => void;
|
82
|
+
/**
|
83
|
+
* Control the fiber with an abort signal
|
84
|
+
* @param t
|
85
|
+
* @param signal
|
86
|
+
*/
|
87
|
+
export declare const control: (t: Thread, signal: AbortSignal) => void;
|
88
|
+
/**
|
89
|
+
* Unwrap a promise result
|
90
|
+
*/
|
91
|
+
export declare function unwrap<T extends Promise<any>>(t: T): Generator<Awaited<T>, Awaited<T>>;
|
package/fiber.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export let paused=(t)=>t[1]===0;export let running=(t)=>t[1]===1;export let done=(t)=>t[1]===2;let invoke=async(g,thread)=>{let t=g.next();while(!t.done){let v=await t.value;if(thread[1]===0){let r;let p=new Promise((res)=>{r=res});thread[2]=r;await p}if(thread[1]===2){thread[3].forEach(stop);return v}t=g.next(v)}thread[1]=2;thread[3].forEach(stop);return t.value};export let fn=(f)=>f;export let start=(f,...args)=>{let thread=[null,1,null,[]];thread[0]=invoke(f(thread,...args),thread);return thread};export let pause=(t)=>{if(t[1]===1)t[1]=0};export let resume=(t)=>{if(t[1]===0){t[1]=1;t[2]?.()}};export let stop=(t)=>{if(t[1]===0){t[1]=2;t[2]()}else t[1]=2};export function*join(t){return yield t[1]}export let finish=(t)=>t[1];export let mount=(child,parent)=>{parent[3].push(child)};export let control=(t,signal)=>{signal.addEventListener("abort",()=>{stop(t)})};export function*unwrap(t){return yield t}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "ciorent",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.21",
|
4
4
|
"description": "A lightweight, low-overhead concurrency library",
|
5
5
|
"homepage": "https://ciorent.netlify.app",
|
6
6
|
"repository": {
|
@@ -18,15 +18,14 @@
|
|
18
18
|
"main": "./index.js",
|
19
19
|
"types": "./index.d.ts",
|
20
20
|
"exports": {
|
21
|
-
"./fixed-queue": "./fixed-queue.js",
|
22
21
|
"./sliding-queue": "./sliding-queue.js",
|
22
|
+
"./channel": "./channel.js",
|
23
|
+
"./semaphore": "./semaphore.js",
|
24
|
+
"./topic": "./topic.js",
|
23
25
|
".": "./index.js",
|
24
26
|
"./dropping-queue": "./dropping-queue.js",
|
25
|
-
"./
|
26
|
-
"./
|
27
|
-
"./
|
28
|
-
"./latch": "./latch.js",
|
29
|
-
"./concurrent": "./concurrent.d.ts",
|
30
|
-
"./topic": "./topic.js"
|
27
|
+
"./fiber": "./fiber.js",
|
28
|
+
"./fixed-queue": "./fixed-queue.js",
|
29
|
+
"./latch": "./latch.js"
|
31
30
|
}
|
32
31
|
}
|
package/concurrent.d.ts
DELETED
package/fiber/index.d.ts
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @module Fiber
|
3
|
-
*/
|
4
|
-
/**
|
5
|
-
* When the fiber is paused
|
6
|
-
*/
|
7
|
-
export declare const paused: (t: Thread) => boolean;
|
8
|
-
/**
|
9
|
-
* When the fiber is running
|
10
|
-
*/
|
11
|
-
export declare const running: (t: Thread) => boolean;
|
12
|
-
/**
|
13
|
-
* When the fiber is done
|
14
|
-
*/
|
15
|
-
export declare const done: (t: Thread) => boolean;
|
16
|
-
/**
|
17
|
-
* Describe a fiber
|
18
|
-
*/
|
19
|
-
export interface Thread<T = unknown, TReturn = unknown> {
|
20
|
-
/**
|
21
|
-
* The original generator
|
22
|
-
*/
|
23
|
-
0: Generator<T, TReturn>;
|
24
|
-
/**
|
25
|
-
* The waiting promise
|
26
|
-
*/
|
27
|
-
1: Promise<T | TReturn>;
|
28
|
-
/**
|
29
|
-
* Fiber status
|
30
|
-
*/
|
31
|
-
2: 0 | 1 | 2;
|
32
|
-
/**
|
33
|
-
* Callback to continue running the fiber
|
34
|
-
*/
|
35
|
-
3: null | (() => void);
|
36
|
-
}
|
37
|
-
/**
|
38
|
-
* Describe a fiber runtime
|
39
|
-
*/
|
40
|
-
export type Runtime = <const T, const TReturn>(gen: Generator<T, TReturn>) => Thread<T, TReturn>;
|
41
|
-
/**
|
42
|
-
* A basic fiber runtime
|
43
|
-
* @param g
|
44
|
-
*/
|
45
|
-
export declare const start: Runtime;
|
46
|
-
/**
|
47
|
-
* Pause the execution of a fiber
|
48
|
-
* @param t
|
49
|
-
*/
|
50
|
-
export declare const pause: (t: Thread) => void;
|
51
|
-
/**
|
52
|
-
* Resume the execution of a fiber
|
53
|
-
* @param t
|
54
|
-
*/
|
55
|
-
export declare const resume: (t: Thread) => void;
|
56
|
-
/**
|
57
|
-
* Stop the execution of a fiber and retrieve the result
|
58
|
-
* @param t
|
59
|
-
*/
|
60
|
-
export declare const stop: <T extends Thread>(t: T) => T[1];
|
61
|
-
/**
|
62
|
-
* Wait for a fiber and retrieve its result
|
63
|
-
* @param t
|
64
|
-
*/
|
65
|
-
export declare function join<T extends Thread>(t: T): Generator<Awaited<T[1]>, Awaited<T[1]>>;
|
66
|
-
/**
|
67
|
-
* Wait for a fiber to finish and retrieve its result
|
68
|
-
* @param t
|
69
|
-
*/
|
70
|
-
export declare const finish: <T extends Thread>(t: T) => T[1];
|
71
|
-
/**
|
72
|
-
* Wait for a promise to resolve then retrieve its result
|
73
|
-
*/
|
74
|
-
export declare function wait<T extends Promise<any>>(t: T): Generator<Awaited<T>, Awaited<T>>;
|
package/fiber/index.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export let paused=(t)=>t[2]===0;export let running=(t)=>t[2]===1;export let done=(t)=>t[2]===2;let invoke=async(g,thread)=>{let t=g.next();while(!t.done){let v=await t.value;if(thread[2]===0){let r;let p=new Promise((res)=>{r=res});thread[3]=r;await p}if(thread[2]===2)return v;t=g.next(v)}thread[2]=2;return t.value};export let start=(g)=>{let thread=[g,null,1,null];thread[1]=invoke(g,thread);return thread};export let pause=(t)=>{if(t[2]===1)t[2]=0};export let resume=(t)=>{if(t[2]===0){t[2]=1;t[3]?.()}};export let stop=(t)=>{if(t[2]===0){t[2]=2;t[3]()}else t[2]=2;return t[1]};export function*join(t){return yield t[1]}export let finish=(t)=>t[1];export function*wait(t){return yield t}
|