ciorent 0.0.1 → 0.0.3
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 +102 -1
- package/channel.d.ts +14 -13
- package/channel.js +1 -1
- package/index.d.ts +11 -2
- package/index.js +1 -1
- package/latch.d.ts +9 -0
- package/latch.js +1 -0
- package/package.json +7 -4
- package/queue/dropping.d.ts +13 -0
- package/queue/dropping.js +1 -0
- package/queue/index.d.ts +31 -0
- package/queue/index.js +1 -0
- package/queue/sliding.d.ts +17 -0
- package/queue/sliding.js +1 -0
package/README.md
CHANGED
@@ -1,2 +1,103 @@
|
|
1
1
|
# Ciorent
|
2
|
-
A concurrency library.
|
2
|
+
A low-overhead, cross-runtime concurrency library.
|
3
|
+
|
4
|
+
## Example usage
|
5
|
+
Pausing to prioritize an asynchronous task:
|
6
|
+
```ts
|
7
|
+
import * as cio from 'ciorent';
|
8
|
+
|
9
|
+
// Expensive sync task
|
10
|
+
const task1 = async () => {
|
11
|
+
let x = 0;
|
12
|
+
for (let i = 0; i < (Math.random() + 15) * 1e7; i++) {
|
13
|
+
// Occasional pausing
|
14
|
+
if (i % 2e6 === 0)
|
15
|
+
await cio.pause;
|
16
|
+
|
17
|
+
x += Math.random() * 32 + i * Math.round(Math.random() * 16);
|
18
|
+
}
|
19
|
+
console.log('Finish task 1:', x);
|
20
|
+
};
|
21
|
+
|
22
|
+
// Short async task
|
23
|
+
const task2 = async () => {
|
24
|
+
console.log('Fetch start', performance.now().toFixed(2) + 'ms');
|
25
|
+
const txt = await fetch('http://example.com');
|
26
|
+
console.log('Fetch status', txt.status);
|
27
|
+
};
|
28
|
+
|
29
|
+
// Task 2 will not get blocked by task 1
|
30
|
+
task1();
|
31
|
+
task2();
|
32
|
+
```
|
33
|
+
|
34
|
+
Sleep for a duration:
|
35
|
+
```ts
|
36
|
+
import * as cio from 'ciorent';
|
37
|
+
|
38
|
+
await cio.sleep(1000);
|
39
|
+
console.log('Slept for about 1s');
|
40
|
+
```
|
41
|
+
|
42
|
+
Go-like channels for synchronizations:
|
43
|
+
```ts
|
44
|
+
import * as channel from 'ciorent/channel';
|
45
|
+
|
46
|
+
const c = channel.init<number>();
|
47
|
+
const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms));
|
48
|
+
|
49
|
+
const run = async () => {
|
50
|
+
for (let i = 0; i < 10; i++) {
|
51
|
+
await sleep(10);
|
52
|
+
channel.send(c, i);
|
53
|
+
console.log('Sent', i);
|
54
|
+
}
|
55
|
+
|
56
|
+
// Send the closed signal to the reciever
|
57
|
+
// Or else channel.recieve will block forever
|
58
|
+
channel.close(c);
|
59
|
+
};
|
60
|
+
|
61
|
+
const log = async () => {
|
62
|
+
while (true) {
|
63
|
+
// Non-blocking
|
64
|
+
const x = await channel.recieve(c);
|
65
|
+
|
66
|
+
// If the channel has been closed
|
67
|
+
if (x === null) break;
|
68
|
+
|
69
|
+
console.log('Recieved', x);
|
70
|
+
};
|
71
|
+
}
|
72
|
+
|
73
|
+
run();
|
74
|
+
log();
|
75
|
+
|
76
|
+
// This runs first
|
77
|
+
console.log('Starting...');
|
78
|
+
```
|
79
|
+
|
80
|
+
Latches:
|
81
|
+
```ts
|
82
|
+
import latch from 'ciorent/latch';
|
83
|
+
|
84
|
+
const [startFetch, pauseFetch] = latch();
|
85
|
+
|
86
|
+
const task = async () => {
|
87
|
+
// Blocks until the latch is open
|
88
|
+
await pauseFetch;
|
89
|
+
|
90
|
+
const res = await fetch('http://example.com');
|
91
|
+
console.log('Fetch status:', res.status);
|
92
|
+
}
|
93
|
+
|
94
|
+
const prepare = () => {
|
95
|
+
console.log('Run before fetch');
|
96
|
+
|
97
|
+
// Unblock the latch
|
98
|
+
startFetch();
|
99
|
+
}
|
100
|
+
|
101
|
+
task();
|
102
|
+
setTimeout(prepare, 500);
|
103
|
+
```
|
package/channel.d.ts
CHANGED
@@ -14,46 +14,47 @@ export interface Channel<T> {
|
|
14
14
|
/**
|
15
15
|
* The head of the value queue
|
16
16
|
*/
|
17
|
-
1: QueueNode<
|
17
|
+
1: QueueNode<T>;
|
18
18
|
/**
|
19
19
|
* The tail of the value queue
|
20
20
|
*/
|
21
|
-
2: QueueNode<
|
21
|
+
2: QueueNode<T>;
|
22
22
|
/**
|
23
23
|
* The head of the Promise resolve queue
|
24
24
|
*/
|
25
|
-
3: QueueNode<(value:
|
25
|
+
3: QueueNode<(value: T | null) => void>;
|
26
26
|
/**
|
27
27
|
* The tail of the Promise resolve queue
|
28
28
|
*/
|
29
|
-
4: QueueNode<(value:
|
29
|
+
4: QueueNode<(value: T | null) => void>;
|
30
30
|
}
|
31
|
-
/**
|
32
|
-
* A signal that means the channel has closed
|
33
|
-
*/
|
34
|
-
export declare const closed: unique symbol;
|
35
31
|
/**
|
36
32
|
* Create a channel
|
37
33
|
*/
|
38
|
-
export declare const init: <T>() => Channel<T>;
|
34
|
+
export declare const init: <T extends {}>() => Channel<T>;
|
39
35
|
/**
|
40
36
|
* Send a message to a channel
|
41
37
|
* @param c - The channel to send to
|
42
38
|
* @param t - The message to send
|
43
39
|
*/
|
44
|
-
export declare const send: <T>(c: Channel<T>, t:
|
40
|
+
export declare const send: <T>(c: Channel<T>, t: T) => void;
|
41
|
+
/**
|
42
|
+
* Recieve a message from a channel, return null if the channel is closed
|
43
|
+
* @param c
|
44
|
+
*/
|
45
|
+
export declare const recieve: <T>(c: Channel<T>) => Promise<T | null>;
|
45
46
|
/**
|
46
|
-
* Recieve a message from a channel
|
47
|
+
* Recieve a message from a channel, return null if no message is currently in queue
|
47
48
|
* @param c
|
48
49
|
*/
|
49
|
-
export declare const
|
50
|
+
export declare const poll: <T>(c: Channel<T>) => T | null;
|
50
51
|
/**
|
51
52
|
* Close a channel
|
52
53
|
* @param c
|
53
54
|
*/
|
54
55
|
export declare const close: <T>(c: Channel<T>) => void;
|
55
56
|
/**
|
56
|
-
* Check whether a channel is still open
|
57
|
+
* Check whether a channel is still open
|
57
58
|
* @param c
|
58
59
|
*/
|
59
60
|
export declare const active: (c: Channel<any>) => boolean;
|
package/channel.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
let resolvedNull=Promise.resolve(null);export let init=()=>{let qu=[null,null];let resolveQu=[null,null];return[true,qu,qu,resolveQu,resolveQu]};export let send=(c,t)=>{if(c[0]){if(c[4][1]!==null)(c[4]=c[4][1])[0](t);else c[1]=c[1][1]=[t,null]}};export let recieve=(c)=>c[2][1]!==null?Promise.resolve((c[2]=c[2][1])[0]):c[0]?new Promise((res)=>{c[3]=c[3][1]=[res,null]}):resolvedNull;export let poll=(c)=>c[2][1]!==null?(c[2]=c[2][1])[0]:null;export let close=(c)=>{c[0]=false;while(c[4][1]!==null)(c[4]=c[4][1])[0](null)};export let active=(c)=>c[0];
|
package/index.d.ts
CHANGED
@@ -1,8 +1,17 @@
|
|
1
1
|
/**
|
2
2
|
* @module
|
3
|
-
*
|
3
|
+
* Other utilities
|
4
4
|
*/
|
5
5
|
/**
|
6
|
-
*
|
6
|
+
* Continue running the function on next microtask.
|
7
|
+
*
|
8
|
+
* You can `await` this **occasionally** in an expensive synchronous operation to avoid
|
9
|
+
*
|
10
|
+
* blocking the main thread and let other asynchronous task to run.
|
7
11
|
*/
|
8
12
|
export declare const pause: Promise<void>;
|
13
|
+
/**
|
14
|
+
* Sleep for a duration
|
15
|
+
* @param ms - Sleep duration in milliseconds
|
16
|
+
*/
|
17
|
+
export declare const sleep: (ms: number) => Promise<void>;
|
package/index.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export let pause=Promise.resolve();
|
1
|
+
export let pause=Promise.resolve();export let sleep=globalThis.Bun?.sleep??globalThis.process?.getBuiltinModule?.("timers/promises").setTimeout??((ms)=>new Promise((res)=>{setTimeout(res,ms)}));
|
package/latch.d.ts
ADDED
package/latch.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export default ()=>{let r;let p=new Promise((res)=>{r=res});return[r,p]};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "ciorent",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.3",
|
4
4
|
"description": "A concurrency library",
|
5
5
|
"keywords": [],
|
6
6
|
"license": "MIT",
|
@@ -12,7 +12,8 @@
|
|
12
12
|
"build:test": "bun task build && bun test",
|
13
13
|
"build:publish": "bun task build && bun task report-size && bun task publish",
|
14
14
|
"lint": "eslint ./src",
|
15
|
-
"lint:fix": "eslint ./src --fix"
|
15
|
+
"lint:fix": "eslint ./src --fix",
|
16
|
+
"docs": "typedoc ./src/** --entryPointStrategy Expand --plugin typedoc-material-theme --skipErrorChecking"
|
16
17
|
},
|
17
18
|
"devDependencies": {
|
18
19
|
"@stylistic/eslint-plugin": "latest",
|
@@ -21,9 +22,11 @@
|
|
21
22
|
"eslint": "latest",
|
22
23
|
"eslint-plugin-jsdoc": "latest",
|
23
24
|
"mitata": "latest",
|
25
|
+
"terser": "^5.39.0",
|
24
26
|
"tsx": "latest",
|
27
|
+
"typedoc": "^0.27.9",
|
28
|
+
"typedoc-material-theme": "^1.3.0",
|
25
29
|
"typescript": "latest",
|
26
|
-
"typescript-eslint": "latest"
|
27
|
-
"uglify-js": "latest"
|
30
|
+
"typescript-eslint": "latest"
|
28
31
|
}
|
29
32
|
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/**
|
2
|
+
* @module
|
3
|
+
* Dropping queues
|
4
|
+
*/
|
5
|
+
import type { FixedQueue } from '.';
|
6
|
+
export { default as init } from '.';
|
7
|
+
export { pop } from './sliding';
|
8
|
+
/**
|
9
|
+
* Push an item to a dropping queue
|
10
|
+
* @param q - The queue to push to
|
11
|
+
* @param item
|
12
|
+
*/
|
13
|
+
export declare const push: <T extends {}>(q: FixedQueue<T>, item: T) => boolean;
|
@@ -0,0 +1 @@
|
|
1
|
+
export{default as init}from".";export{pop}from"./sliding";export let push=(q,item)=>{if(q[0][(q[2]+1)%q[1]]!=null)return false;q[0][q[2]=(q[2]+1)%q[1]]=item;return true};
|
package/queue/index.d.ts
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
/**
|
2
|
+
* @module
|
3
|
+
* Queue utilities
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* Describe a fixed-sized queue
|
7
|
+
*/
|
8
|
+
export interface FixedQueue<T extends {}> {
|
9
|
+
/**
|
10
|
+
* Pre-allocated queue
|
11
|
+
*/
|
12
|
+
readonly 0: (T | undefined | null)[];
|
13
|
+
/**
|
14
|
+
* Queue capacity
|
15
|
+
*/
|
16
|
+
readonly 1: number;
|
17
|
+
/**
|
18
|
+
* Head pointer
|
19
|
+
*/
|
20
|
+
2: number;
|
21
|
+
/**
|
22
|
+
* Tail pointer
|
23
|
+
*/
|
24
|
+
3: number;
|
25
|
+
}
|
26
|
+
/**
|
27
|
+
* Create a fixed queue.
|
28
|
+
* @param n - The queue size
|
29
|
+
*/
|
30
|
+
declare const _default: <T extends {}>(n: number) => FixedQueue<T>;
|
31
|
+
export default _default;
|
package/queue/index.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export default (n)=>[new Array(n),n,-1,-1];
|
@@ -0,0 +1,17 @@
|
|
1
|
+
/**
|
2
|
+
* @module
|
3
|
+
* Sliding queues
|
4
|
+
*/
|
5
|
+
import type { FixedQueue } from '.';
|
6
|
+
export { default as init } from '.';
|
7
|
+
/**
|
8
|
+
* Push an item to a sliding queue
|
9
|
+
* @param q - The queue to push to
|
10
|
+
* @param item
|
11
|
+
*/
|
12
|
+
export declare const push: <T extends {}>(q: FixedQueue<T>, item: T) => void;
|
13
|
+
/**
|
14
|
+
* Pop an item from the queue
|
15
|
+
* @param q - The queue to pull from
|
16
|
+
*/
|
17
|
+
export declare const pop: <T extends {}>(q: FixedQueue<T>) => T | undefined;
|
package/queue/sliding.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export{default as init}from".";export let push=(q,item)=>{q[0][q[2]=(q[2]+1)%q[1]]=item};export let pop=(q)=>{let val=q[0][(q[3]+1)%q[1]];if(val!=null){q[0][q[3]=(q[3]+1)%q[1]]=null;return val}};
|