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 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<Promise<T | typeof closed>>;
17
+ 1: QueueNode<T>;
18
18
  /**
19
19
  * The tail of the value queue
20
20
  */
21
- 2: QueueNode<Promise<T | typeof closed>>;
21
+ 2: QueueNode<T>;
22
22
  /**
23
23
  * The head of the Promise resolve queue
24
24
  */
25
- 3: QueueNode<(value: Promise<T | typeof closed> | T | typeof closed) => void>;
25
+ 3: QueueNode<(value: T | null) => void>;
26
26
  /**
27
27
  * The tail of the Promise resolve queue
28
28
  */
29
- 4: QueueNode<(value: Promise<T | typeof closed> | T | typeof closed) => void>;
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: Promise<T> | T) => void;
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 recieve: <T>(c: Channel<T>) => Promise<T | typeof closed>;
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 yet
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
- export let closed=Symbol();let closedPromise=Promise.resolve(closed);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 instanceof Promise?t:Promise.resolve(t),null]}};export let recieve=(c)=>c[2][1]!==null?(c[2]=c[2][1])[0]:c[0]?new Promise((res)=>{c[3]=c[3][1]=[res,null]}):closedPromise;export let close=(c)=>{c[0]=false;while(c[4][1]!==null)(c[4]=c[4][1])[0](closed)};export let active=(c)=>c[0];
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
- * Utilities for concurrency
3
+ * Other utilities
4
4
  */
5
5
  /**
6
- * Pause to run other tasks
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
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @module
3
+ * Latches
4
+ */
5
+ /**
6
+ * Create a latch
7
+ */
8
+ declare const _default: () => [resolve: () => void, promise: Promise<void>];
9
+ export default _default;
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.1",
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};
@@ -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;
@@ -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}};