ciorent 0.4.0 → 0.4.2

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
@@ -7,267 +7,3 @@ A lightweight, low-overhead concurrency library.
7
7
  - Fully type-safe.
8
8
 
9
9
  ## Examples
10
- ### Utilities
11
- #### Spawning tasks
12
- Utilities to create and run tasks.
13
- ```ts
14
- import * as co from 'ciorent';
15
-
16
- const task = async (id: number) => {
17
- await co.sleep((10 - id) * 20 + 50);
18
- console.log('Task', id, 'done');
19
- }
20
-
21
- // Spawn and run 5 tasks sequentially
22
- console.log('Running 5 tasks sequentially:');
23
- await co.sequential(5, task);
24
-
25
- // Spawn and run 5 tasks concurrently
26
- console.log('Running 5 tasks concurrently:');
27
- await Promise.all(co.spawn(5, task));
28
- ```
29
-
30
- #### Sleep
31
- Cross-runtime synchronous and asynchronous sleep functions.
32
- ```ts
33
- import * as co from 'ciorent';
34
-
35
- const logTime = (label: string) => console.log(`${label}: ${Math.floor(performance.now())}ms`);
36
-
37
- logTime('Start');
38
-
39
- // Non-blocking
40
- await co.sleep(500);
41
- logTime('After about 0.5s');
42
-
43
- // This blocks the event loop
44
- // On the browser this only works in workers and blocks the worker thread
45
- co.sleepSync(500);
46
- logTime('After another 0.5s');
47
- ```
48
-
49
- #### Debounce
50
- Postpones execution until after an idle period.
51
- ```ts
52
- import * as co from 'ciorent';
53
-
54
- const fn = co.debounce((id: number) => {
55
- console.log('ID:', id);
56
- }, 500);
57
-
58
- fn(1); // fn(1) gets skipped
59
- await co.sleep(100);
60
- fn(2); // fn(2) gets executed
61
- ```
62
-
63
- #### Throttle
64
- Executes a function at a regular interval.
65
- ```ts
66
- import * as co from 'ciorent';
67
-
68
- // Allow 2 calls in 500ms
69
- const throttle = co.throttle(500, 2);
70
-
71
- co.spawn(8, async (id) => {
72
- await throttle();
73
- console.log(`${id}: ${Math.floor(performance.now())}ms`);
74
- });
75
- ```
76
-
77
- #### Yield
78
- Continue the execution on next tick, allowing other asynchronous tasks to run.
79
- ```ts
80
- import * as co from 'ciorent';
81
-
82
- const logTime = (label: string) => console.log(`${label}: ${Math.floor(performance.now())}ms`);
83
-
84
- // Expensive sync task
85
- const task1 = async () => {
86
- let x = 0;
87
-
88
- // Simulate heavy operation
89
- for (let i = 0, l = (Math.random() + 15) * 1e6; i < l; i++) {
90
- // Yield control back occasionally to the runtime, allowing
91
- // it to schedule other tasks
92
- if (i % 1e5 === 0)
93
- await co.nextTick;
94
-
95
- x += Math.random() * 32 + i * Math.round(Math.random() * 16);
96
- }
97
-
98
- console.log('Task 1 result:', x);
99
- };
100
-
101
- // Short async task
102
- const task2 = async (id: number) => {
103
- logTime('Task 2.' + id + ' start fetching');
104
- await fetch('http://localhost:3000').catch(() => {});
105
- logTime('Task 2.' + id + ' done fetching');
106
- };
107
-
108
- task1();
109
-
110
- // Task 2 will not get blocked by task 1
111
- co.spawn(5, task2);
112
- ```
113
-
114
- ### Pubsub
115
- Pubsub allows broadcasting messages to topics that can be recieved by subscribers.
116
-
117
- ```ts
118
- import * as topic from 'ciorent/topic';
119
- import * as co from 'ciorent';
120
-
121
- const numbers = topic.init<number>();
122
-
123
- // Spawn 3 tasks that subscribe to the topic
124
- co.spawn(3, async (id) => {
125
- const subscriber = topic.subscribe(numbers);
126
-
127
- while (true) {
128
- const msg = await topic.dispatch(subscriber);
129
- if (msg == null) return;
130
- console.log('Task', id, 'recieved:', msg);
131
- }
132
- });
133
-
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);
142
- ```
143
-
144
- ### Stream
145
- Send and recieve data asynchronously through streams.
146
-
147
- ```ts
148
- import * as stream from 'ciorent/stream';
149
- import * as co from 'ciorent';
150
-
151
- const numbers = stream.init<number>();
152
-
153
- // Spawn 3 tasks that read from the stream
154
- co.spawn(3, async (id) => {
155
- while (true) {
156
- const msg = await stream.read(numbers);
157
- if (msg == null) return;
158
- console.log('Task', id, 'recieved:', msg);
159
- }
160
- });
161
-
162
- // Write messages to the stream
163
- for (let i = 0; i < 3; i++) {
164
- stream.write(numbers, i);
165
- await co.nextTick;
166
- }
167
-
168
- // Send undefined to every stream
169
- stream.flush(numbers);
170
- ```
171
-
172
- ### Semaphore
173
- Semaphore is a concurrency primitive used to control access to a common resource by multiple processes.
174
-
175
- ```ts
176
- import * as semaphore from 'ciorent/semaphore';
177
- import * as co from 'ciorent';
178
-
179
- // Only allow 2 task to run concurrently
180
- const sem = semaphore.init(2);
181
-
182
- const task = async (id: number) => {
183
- // Acquire the semaphore or wait for the semaphore to be available
184
- await semaphore.acquire(sem);
185
-
186
- console.log('Task', id, 'started');
187
-
188
- // Let the main thread schedules other tasks
189
- for (let i = 1; i <= 5; i++) await co.nextTick;
190
-
191
- console.log('Task', id, 'end');
192
-
193
- // Release the semaphore
194
- semaphore.release(sem);
195
- }
196
-
197
- // Try to run 5 tasks concurrently
198
- co.spawn(5, task);
199
- ```
200
-
201
- ### Fibers
202
- Virtual threads with more controlled execution.
203
-
204
- ```ts
205
- import * as co from 'ciorent';
206
- import * as fiber from 'ciorent/fiber';
207
-
208
- const logTime = (label: string) => console.log(`${label}: ${Math.floor(performance.now())}ms`);
209
-
210
- const f1 = fiber.fn(function* () {
211
- // Wait for a promise
212
- console.log('Fiber 1 waiting: 1s');
213
- yield co.sleep(1000);
214
-
215
- // Wait for a promise and return its result
216
- const res = yield* fiber.unwrap(Promise.resolve(1));
217
- console.log('Fiber 1 recieved:', res);
218
-
219
- return Math.random();
220
- });
221
-
222
- {
223
- // Start the fiber process on next event loop cycle
224
- const main = fiber.spawn(function* (proc) {
225
- // Start f1, wait for the process to complete and get the result
226
- console.log('Fiber 2: joins fiber 1');
227
- const res = yield* fiber.join(fiber.spawn(f1));
228
- console.log('Fiber 2 recieved:', res);
229
-
230
- // Start f1 and make its lifetime depends on current fiber
231
- console.log('Fiber 2: spawns fiber 1');
232
- const childProc = fiber.spawn(f1);
233
- fiber.mount(childProc, proc);
234
- });
235
-
236
- console.log('Fiber 2 started:', fiber.resumed(main));
237
-
238
- // Wait for the fiber process to finish
239
- await fiber.done(main);
240
-
241
- // Check finish status
242
- console.log('Fiber 2 completed:', fiber.completed(main));
243
- }
244
-
245
- {
246
- console.log('------------------------');
247
-
248
- const main = fiber.spawn(f1);
249
- console.log('Fiber 1 started:', fiber.resumed(main));
250
-
251
- // Interrupt a fiber
252
- fiber.interrupt(main);
253
-
254
- // Execution will be stopped on the last yield
255
- await fiber.done(main);
256
-
257
- console.log('Fiber 1 interrupted:', fiber.interrupted(main));
258
- }
259
-
260
- {
261
- console.log('------------------------');
262
-
263
- const main = fiber.spawn(f1);
264
- logTime('Fiber 1 started');
265
-
266
- // Wait for a time period then interrupt the fiber
267
- fiber.timeout(main, 500);
268
- await fiber.done(main);
269
-
270
- logTime('Fiber 1 interrupted');
271
- }
272
- ```
273
-
package/fiber.d.ts CHANGED
@@ -1,89 +1,70 @@
1
1
  /**
2
- * @module Fibers
3
- */
4
- /**
5
- * Describe a fiber process
6
- */
7
- export type Process<TReturn = unknown> = [
8
- proc: Promise<TReturn | undefined>,
9
- status: 0 | 1 | 2 | 3,
10
- resume: null | ((state: 1 | 3) => void),
11
- children: Process[]
12
- ];
13
- /**
14
- * Describe a fiber runtime
15
- */
16
- export type Runtime = <const TReturn, const Args extends any[]>(gen: (proc: Process<TReturn>, ...args: Args) => Generator<any, TReturn>, ...args: Args) => Process<TReturn>;
17
- /**
18
- * Check whether the fiber has been paused
19
- */
20
- export declare const paused: (t: Process) => boolean;
21
- /**
22
- * Check whether the fiber is running
23
- */
24
- export declare const resumed: (t: Process) => boolean;
25
- /**
26
- * Check whether the fiber has completed
27
- */
2
+ * Describe a fiber process
3
+ */
4
+ export type Process<TReturn = unknown> = [proc: Promise<TReturn | undefined>, status: 1 | 2 | 3, children: Process[]];
5
+ /**
6
+ * Describe a fiber runtime
7
+ */
8
+ export type Runtime = <
9
+ const TReturn,
10
+ const Args extends any[]
11
+ >(gen: (proc: Process<TReturn>, ...args: Args) => Generator<any, TReturn>, ...args: Args) => Process<TReturn>;
12
+ /**
13
+ * Check whether the fiber is running
14
+ */
15
+ export declare const running: (t: Process) => boolean;
16
+ /**
17
+ * Check whether the fiber has completed
18
+ */
28
19
  export declare const completed: (t: Process) => boolean;
29
20
  /**
30
- * Check whether the fiber has been interrupted
31
- */
21
+ * Check whether the fiber has been interrupted
22
+ */
32
23
  export declare const interrupted: (t: Process) => boolean;
33
24
  /**
34
- * Create a fiber function
35
- * @param f
36
- */
25
+ * Create a fiber function
26
+ * @param f
27
+ */
37
28
  export declare const fn: <const Fn extends (thread: Process, ...args: any[]) => Generator>(f: Fn) => Fn;
38
29
  /**
39
- * A basic fiber runtime
40
- * @param g
41
- */
30
+ * A basic fiber runtime
31
+ * @param g
32
+ */
42
33
  export declare const spawn: Runtime;
43
34
  /**
44
- * Pause the execution of a fiber
45
- * @param t
46
- */
47
- export declare const pause: (t: Process) => void;
48
- /**
49
- * Resume the execution of a fiber
50
- * @param t
51
- */
52
- export declare const resume: (t: Process) => void;
53
- /**
54
- * Interrupt the execution of a fiber
55
- * @param t
56
- */
35
+ * Interrupt the execution of a fiber
36
+ * @param t
37
+ */
57
38
  export declare const interrupt: (t: Process) => void;
58
39
  /**
59
- * Timeout a fiber
60
- * @param t
61
- * @param ms
62
- */
40
+ * Timeout a fiber
41
+ * @param t
42
+ * @param ms
43
+ */
63
44
  export declare const timeout: (t: Process, ms: number) => Promise<void>;
64
45
  /**
65
- * Wait for a fiber and retrieve its result
66
- * @param t
67
- */
46
+ * Wait for a fiber and retrieve its result
47
+ * @param t
48
+ */
68
49
  export declare function join<T extends Process>(t: T): Generator<Awaited<T[0]>, Awaited<T[0]>>;
69
50
  /**
70
- * Wait for a fiber to finish and retrieve its result
71
- * @param t
72
- */
51
+ * Wait for a fiber to finish and retrieve its result
52
+ * @param t
53
+ */
73
54
  export declare const done: <T extends Process>(t: T) => T[0];
74
55
  /**
75
- * Mount child fiber lifetime to parent lifetime
76
- * @param child
77
- * @param parent
78
- */
56
+ * Mount child fiber lifetime to parent lifetime
57
+ * @param child
58
+ * @param parent
59
+ */
79
60
  export declare const mount: (child: Process, parent: Process) => void;
80
61
  /**
81
- * Control the fiber with an abort signal
82
- * @param t
83
- * @param signal
84
- */
62
+ * Control the fiber with an abort signal
63
+ * @param t
64
+ * @param signal
65
+ */
85
66
  export declare const control: (t: Process, signal: AbortSignal) => void;
86
67
  /**
87
- * Unwrap a promise result
88
- */
68
+ * Unwrap a promise result
69
+ */
89
70
  export declare function unwrap<T extends Promise<any>>(t: T): Generator<Awaited<T>, Awaited<T>>;
package/fiber.js CHANGED
@@ -1 +1 @@
1
- import{sleep}from"./index.js";export let paused=(t)=>t[1]===0;export let resumed=(t)=>t[1]===1;export let completed=(t)=>t[1]===2;export let interrupted=(t)=>t[1]===3;let invoke=async(g,thread)=>{await 0;try{let t=g.next();while(!t.done){let v=await t.value;if(thread[1]===0)thread[1]=await new Promise((res)=>{thread[2]=res});if(thread[1]===3)return;t=g.next(v)}thread[1]=2;return t.value}finally{if(thread[1]!==2)thread[1]=3;thread[3].forEach(interrupt)}};export let fn=(f)=>f;export let spawn=(f,...args)=>{let t=[null,1,null,[]];t[0]=invoke(f(t,...args),t);return t};export let pause=(t)=>{if(t[1]===1)t[1]=0};export let resume=(t)=>{if(t[1]===0){if(t[2]===null)t[1]=1;else t[2](1)}};export let interrupt=(t)=>{if(t[1]!==2){if(t[1]===0&&t[2]!==null)t[2](3);else t[1]=3}};export let timeout=async(t,ms)=>{await sleep(ms);interrupt(t)};export function*join(t){return yield t[0]}export let done=(t)=>t[0];export let mount=(child,parent)=>{parent[3].push(child)};export let control=(t,signal)=>{signal.addEventListener("abort",()=>{interrupt(t)})};export function*unwrap(t){return yield t}
1
+ import{nextTick,sleep}from"./index.js";export let running=e=>e[1]===1;export let completed=e=>e[1]===2;export let interrupted=e=>e[1]===3;let invoke=async(f,p)=>{await nextTick;try{let e=f.next();for(;!e.done;){let m=await e.value;if(p[1]===3)return;e=f.next(m)}return p[1]=2,e.value}finally{p[1]!==2&&(p[1]=3),p[2].forEach(interrupt)}};export let fn=e=>e;export let spawn=(e,...f)=>{let p=[null,1,[]];return p[0]=invoke(e(p,...f),p),p};export let interrupt=e=>{e[1]!==2&&(e[1]=3)};export let timeout=async(e,p)=>{await sleep(p),interrupt(e)};export function*join(e){return yield e[0]}export let done=e=>e[0];export let mount=(e,f)=>{f[2].push(e)};export let control=(e,f)=>{f.addEventListener(`abort`,()=>{interrupt(e)})};export function*unwrap(e){return yield e}
package/index.d.ts CHANGED
@@ -1,49 +1,43 @@
1
1
  /**
2
- * @module Other utilities
3
- */
4
- /**
5
- * Continue the execution on next event loop cycle.
6
- *
7
- * You can `await` this **occasionally** in an expensive synchronous operation to avoid
8
- *
9
- * blocking the main thread and let other asynchronous task to run.
10
- */
2
+ * Continue the execution on next event loop cycle.
3
+ *
4
+ * You can `await` this **occasionally** in an expensive synchronous operation to avoid
5
+ *
6
+ * blocking the main thread and let other asynchronous task to run.
7
+ */
11
8
  export declare const nextTick: Promise<void>;
12
9
  /**
13
- * Sleep for a duration.
14
- * @param ms - Sleep duration in milliseconds
15
- */
10
+ * Sleep for a duration.
11
+ * @param ms - Sleep duration in milliseconds
12
+ */
16
13
  export declare const sleep: (ms: number) => Promise<void>;
17
14
  /**
18
- * Sleep for a duration synchronously.
19
- *
20
- * This method blocks the current thread.
21
- *
22
- * On the browser it only works in workers.
23
- * @param ms - Sleep duration in milliseconds
24
- */
15
+ * Sleep for a duration synchronously.
16
+ *
17
+ * This method blocks the current thread.
18
+ *
19
+ * On the browser it only works in workers.
20
+ * @param ms - Sleep duration in milliseconds
21
+ */
25
22
  export declare const sleepSync: (ms: number) => void;
26
23
  /**
27
- * Spawn n sequential task
28
- * @param n
29
- * @param task - The function to run
30
- */
24
+ * Spawn n sequential task
25
+ * @param n
26
+ * @param task - The function to run
27
+ */
31
28
  export declare const sequential: <const T extends any[]>(n: number, task: (...args: [...T, id: number]) => Promise<any>, ...args: T) => Promise<void>;
32
29
  /**
33
- * Spawn n concurrent tasks
34
- * @param n
35
- * @param task - The function to run
36
- */
37
- export declare const spawn: <const T extends any[], const R>(n: number, task: (...args: [...T, id: number]) => Promise<R>, ...args: T) => Promise<R>[];
38
- /**
39
- * Drop function calls until it doesn't get called for a specific period.
40
- * @param f - The target function to debounce (it must not throw errors)
41
- * @param ms - The time period in milliseconds
42
- */
43
- export declare const debounce: <const Args extends any[]>(f: (...args: Args) => any, ms: number) => ((...args: Args) => void);
44
- /**
45
- * Throttle function execution for a time period
46
- * @param ms - The time in milliseconds
47
- * @param limit - The call limit in the time period
48
- */
30
+ * Spawn n concurrent tasks
31
+ * @param n
32
+ * @param task - The function to run
33
+ */
34
+ export declare const spawn: <
35
+ const T extends any[],
36
+ const R
37
+ >(n: number, task: (...args: [...T, id: number]) => Promise<R>, ...args: T) => Promise<R>[];
38
+ /**
39
+ * Throttle function execution for a time period
40
+ * @param ms - The time in milliseconds
41
+ * @param limit - The call limit in the time period
42
+ */
49
43
  export declare const throttle: (ms: number, limit: number) => (() => Promise<void>);
package/index.js CHANGED
@@ -1 +1 @@
1
- export let nextTick=Promise.resolve();export let sleep=globalThis.Bun?.sleep??globalThis.process?.getBuiltinModule?.("timers/promises").setTimeout??((ms)=>new Promise((res)=>{setTimeout(res,ms)}));let sharedBuf=new Int32Array(new SharedArrayBuffer(4));export let sleepSync=globalThis.Bun?.sleepSync??((ms)=>{Atomics.wait(sharedBuf,0,0,ms)});export let sequential=async(n,task,...args)=>{for(let i=0;i<n;i++)await task(...args,i)};export let spawn=(n,task,...args)=>{let arr=new Array(n);for(let i=0;i<n;i++)arr[i]=task(...args,i);return arr};export let debounce=(f,ms)=>{let id;return(...a)=>{clearTimeout(id);id=setTimeout(f,ms,...a)}};export let throttle=(ms,limit)=>{let head=[null];let tail=head;let promiseCb=(res)=>{head=head[0]=[null,res]};let cur=limit;let scheduled=false;let unlock=()=>{cur=limit;if(tail===head){scheduled=false;return}do{cur--;(tail=tail[0])[1]()}while(cur>0&&tail!==head);setTimeout(unlock,ms)};return async()=>{if(cur===0)return new Promise(promiseCb);if(!scheduled){scheduled=true;setTimeout(unlock,ms)}cur--}};
1
+ export let nextTick=Promise.resolve();export let sleep=globalThis.Bun?.sleep??globalThis.process?.getBuiltinModule?.(`timers/promises`).setTimeout??(e=>new Promise(t=>{setTimeout(t,e)}));let sharedBuf=new Int32Array(new SharedArrayBuffer(4));export let sleepSync=globalThis.Bun?.sleepSync??(e=>{Atomics.wait(sharedBuf,0,0,e)});export let sequential=async(e,t,...n)=>{for(let r=0;r<e;r++)await t(...n,r)};export let spawn=(e,t,...n)=>{let r=Array(e);for(let i=0;i<e;i++)r[i]=t(...n,i);return r};export let throttle=(e,t)=>{let n=[null],r=n,i=e=>{n=n[0]=[null,e]},a=t,o=!1,s=()=>{if(a=t,r===n){o=!1;return}do a--,(r=r[0])[1]();while(a>0&&r!==n);setTimeout(s,e)};return async()=>{if(a===0)return new Promise(i);o||(o=!0,setTimeout(s,e)),a--}};
package/package.json CHANGED
@@ -1,28 +1,22 @@
1
1
  {
2
- "name": "ciorent",
3
- "version": "0.4.0",
4
- "description": "A lightweight, low-overhead concurrency library",
5
- "homepage": "https://ciorent.netlify.app",
6
- "repository": {
7
- "type": "github",
8
- "url": "https://github.com/re-utils/ciorent"
9
- },
10
- "keywords": [
11
- "low-overhead",
12
- "lightweight",
13
- "concurrency",
14
- "cross-runtime"
15
- ],
16
- "license": "MIT",
17
- "type": "module",
18
- "main": "./index.js",
19
- "types": "./index.d.ts",
20
- "exports": {
21
- "./fiber": "./fiber.js",
22
- "./queue": "./queue.d.ts",
23
- "./semaphore": "./semaphore.js",
24
- "./stream": "./stream.js",
25
- "./topic": "./topic.js",
26
- ".": "./index.js"
27
- }
2
+ "name": "ciorent",
3
+ "version": "0.4.2",
4
+ "description": "A lightweight, low-overhead concurrency library",
5
+ "homepage": "https://ciorent.netlify.app",
6
+ "repository": {
7
+ "type": "github",
8
+ "url": "https://github.com/re-utils/ciorent"
9
+ },
10
+ "keywords": ["low-overhead", "lightweight", "concurrency", "cross-runtime"],
11
+ "license": "MIT",
12
+ "type": "module",
13
+ "main": "./index.js",
14
+ "types": "./index.d.ts",
15
+ "exports": {
16
+ "./queue": "./queue.js",
17
+ "./fiber": "./fiber.js",
18
+ ".": "./index.js",
19
+ "./semaphore": "./semaphore.js",
20
+ "./stream": "./stream.js"
21
+ }
28
22
  }
package/queue.d.ts CHANGED
@@ -1,24 +1,19 @@
1
1
  /**
2
- * @module Queue utilities
3
- */
2
+ * @module Queue utilities
3
+ */
4
4
  /**
5
- * Describe a fixed-sized queue
6
- */
7
- export type FixedQueue<T extends {} = {}> = [
8
- buffer: (T | undefined | null)[],
9
- capacity: number,
10
- head: number,
11
- tail: number
12
- ];
5
+ * Describe a fixed-sized queue
6
+ */
7
+ export type FixedQueue<T extends {} = {}> = [buffer: (T | undefined | null)[], capacity: number, head: number, tail: number];
13
8
  /**
14
- * Describe a queue node (singly linked list node)
15
- */
9
+ * Describe a queue node (singly linked list node)
10
+ */
16
11
  export type QueueNode<T> = [next: QueueNode<T> | null, value: T];
17
12
  /**
18
- * Describe an unbounded queue
19
- */
13
+ * Describe an unbounded queue
14
+ */
20
15
  export type UnboundedQueue<T> = [head: QueueNode<T>, tail: QueueNode<T>];
21
16
  /**
22
- * Cached promise callback
23
- */
17
+ * Cached promise callback
18
+ */
24
19
  export type PromiseFn<T = any> = (res: (value?: T) => void) => void;
package/queue.js ADDED
@@ -0,0 +1 @@
1
+ export{};
package/semaphore.d.ts CHANGED
@@ -1,28 +1,24 @@
1
1
  /**
2
- * @module Semaphores
3
- */
4
- import type { PromiseFn, UnboundedQueue } from './queue.js';
2
+ * @module Semaphores
3
+ */
4
+ import type { PromiseFn, UnboundedQueue } from "./queue.js";
5
5
  /**
6
- * Describe a semaphore
7
- */
8
- export type Semaphore = [
9
- ...UnboundedQueue<() => void>,
10
- callback: PromiseFn<void>,
11
- remain: number
12
- ];
6
+ * Describe a semaphore
7
+ */
8
+ export type Semaphore = [...UnboundedQueue<() => void>, callback: PromiseFn<void>, remain: number];
13
9
  /**
14
- * Create a semaphore that allows n accesses
15
- */
10
+ * Create a semaphore that allows n accesses
11
+ */
16
12
  export declare const init: (n: number) => Semaphore;
17
13
  /**
18
- * Wait until the semaphore allows access
19
- */
14
+ * Wait until the semaphore allows access
15
+ */
20
16
  export declare const acquire: (s: Semaphore) => Promise<void>;
21
17
  /**
22
- * Signal to the semaphore to release access
23
- */
18
+ * Signal to the semaphore to release access
19
+ */
24
20
  export declare const release: (s: Semaphore) => void;
25
21
  /**
26
- * Bind a task to a semaphore
27
- */
22
+ * Bind a task to a semaphore
23
+ */
28
24
  export declare const bind: <T extends (...args: any[]) => Promise<any>>(f: T, s: Semaphore) => T;
package/semaphore.js CHANGED
@@ -1 +1 @@
1
- export let init=(n)=>{let root=[null];let sem=[root,root,(res)=>{sem[0]=sem[0][0]=[null,res]},n];return sem};export let acquire=async(s)=>{s[3]--;if(s[3]<0)return new Promise(s[2])};export let release=(s)=>{if(s[3]<0)(s[1]=s[1][0])[1]();s[3]++};export let bind=(f,s)=>async(...a)=>{s[3]--;if(s[3]<0)await new Promise(s[2]);try{return await f(...a)}finally{if(s[3]<0)(s[1]=s[1][0])[1]();s[3]++}};
1
+ export let init=e=>{let n=[null],r=[n,n,e=>{r[0]=r[0][0]=[null,e]},e];return r};export let acquire=async e=>{if(e[3]--,e[3]<0)return new Promise(e[2])};export let release=e=>{e[3]<0&&(e[1]=e[1][0])[1](),e[3]++};export let bind=(e,n)=>async(...r)=>{n[3]--,n[3]<0&&await new Promise(n[2]);try{return await e(...r)}finally{n[3]<0&&(n[1]=n[1][0])[1](),n[3]++}};
package/stream.d.ts CHANGED
@@ -1,31 +1,27 @@
1
1
  /**
2
- * @module Streams
3
- */
4
- import type { PromiseFn, UnboundedQueue } from './queue.js';
2
+ * @module Streams
3
+ */
4
+ import type { PromiseFn, UnboundedQueue } from "./queue.js";
5
5
  /**
6
- * Describe a stream
7
- */
8
- export type Stream<T extends {} = {}> = [
9
- ...UnboundedQueue<T | ((val?: T) => void)>,
10
- callback: PromiseFn<T>,
11
- queueing: boolean
12
- ];
6
+ * Describe a stream
7
+ */
8
+ export type Stream<T extends {} = {}> = [...UnboundedQueue<T | ((val?: T) => void)>, callback: PromiseFn<T>, queueing: boolean];
13
9
  /**
14
- * Create a stream
15
- */
10
+ * Create a stream
11
+ */
16
12
  export declare const init: <T extends {} = {}>() => Stream<T>;
17
13
  /**
18
- * Write a value to the stream
19
- * @param s
20
- * @param v
21
- */
14
+ * Write a value to the stream
15
+ * @param s
16
+ * @param v
17
+ */
22
18
  export declare const write: <T extends {} = {}>(s: Stream<T>, v: T) => void;
23
19
  /**
24
- * Read a value from the stream
25
- * @param s
26
- */
20
+ * Read a value from the stream
21
+ * @param s
22
+ */
27
23
  export declare const read: <T extends {} = {}>(s: Stream<T>) => Promise<T | undefined>;
28
24
  /**
29
- * Release all pending read with undefined
30
- */
25
+ * Release all pending read with undefined
26
+ */
31
27
  export declare const flush: (s: Stream) => void;
package/stream.js CHANGED
@@ -1 +1 @@
1
- export let init=()=>{let queue=[null];let s=[queue,queue,(res)=>{s[0]=s[0][0]=[null,res]},false];return s};export let write=(s,v)=>{if(!s[3]){if(s[1][0]!==null){(s[1]=s[1][0])[1](v);return}s[3]=true}s[0]=s[0][0]=[null,v]};export let read=async(s)=>{if(s[3]){s[1]=s[1][0];if(s[1][0]===null)s[3]=false;return s[1][1]}return new Promise(s[2])};export let flush=(s)=>{if(!s[3])while(s[1][0]!==null)(s[1]=s[1][0])[1]()};
1
+ export let init=()=>{let e=[null],r=[e,e,e=>{r[0]=r[0][0]=[null,e]},!1];return r};export let write=(e,r)=>{if(!e[3]){if(e[1][0]!==null){(e[1]=e[1][0])[1](r);return}e[3]=!0}e[0]=e[0][0]=[null,r]};export let read=async e=>e[3]?(e[1]=e[1][0],e[1][0]===null&&(e[3]=!1),e[1][1]):new Promise(e[2]);export let flush=e=>{if(!e[3])for(;e[1][0]!==null;)(e[1]=e[1][0])[1]()};
package/topic.d.ts DELETED
@@ -1,45 +0,0 @@
1
- /**
2
- * @module Pubsub
3
- */
4
- import type { PromiseFn, QueueNode } from './queue.js';
5
- /**
6
- * Describe a topic
7
- */
8
- export type Topic<T extends {} = {}> = [
9
- head: QueueNode<T>,
10
- callback: PromiseFn<void>,
11
- resolve: (() => void) | null,
12
- pending: Promise<void> | null
13
- ];
14
- /**
15
- * Describe a subscriber
16
- */
17
- export type Subscriber<T extends {} = {}> = [
18
- topic: Topic<T>,
19
- tail: QueueNode<T>
20
- ];
21
- /**
22
- * Create a topic
23
- */
24
- export declare const init: <T extends {} = {}>() => Topic<T>;
25
- /**
26
- * Publish a message to the topic
27
- * @param t - The topic
28
- * @param m - The message to publish
29
- */
30
- export declare const publish: <T extends {} = {}>(t: Topic<T>, m: T) => void;
31
- /**
32
- * Resolve all pending dispatch
33
- */
34
- export declare const flush: (t: Topic) => void;
35
- /**
36
- * Subscribe to a topic
37
- * @param t
38
- * @returns A subscriber object
39
- */
40
- export declare const subscribe: <T extends {}>(t: Topic<T>) => Subscriber<T>;
41
- /**
42
- * Wait for messages from the topic
43
- * @param s
44
- */
45
- export declare const dispatch: <T extends {}>(s: Subscriber<T>) => Promise<T | undefined>;
package/topic.js DELETED
@@ -1 +0,0 @@
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]};