ciorent 0.3.8 → 0.4.0
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 +22 -51
- package/fiber.d.ts +0 -12
- package/index.js +1 -1
- package/package.json +4 -8
- package/queue.d.ts +8 -17
- package/semaphore.d.ts +5 -6
- package/semaphore.js +1 -1
- package/stream.d.ts +4 -18
- package/stream.js +1 -1
- package/topic.d.ts +3 -4
- package/defer.d.ts +0 -22
- package/defer.js +0 -1
- package/dropping-queue.d.ts +0 -12
- package/dropping-queue.js +0 -1
- package/lock.d.ts +0 -33
- package/lock.js +0 -1
- package/queue.js +0 -1
- package/sliding-queue.d.ts +0 -16
- package/sliding-queue.js +0 -1
package/README.md
CHANGED
@@ -118,7 +118,7 @@ Pubsub allows broadcasting messages to topics that can be recieved by subscriber
|
|
118
118
|
import * as topic from 'ciorent/topic';
|
119
119
|
import * as co from 'ciorent';
|
120
120
|
|
121
|
-
const numbers = topic.init();
|
121
|
+
const numbers = topic.init<number>();
|
122
122
|
|
123
123
|
// Spawn 3 tasks that subscribe to the topic
|
124
124
|
co.spawn(3, async (id) => {
|
@@ -141,43 +141,14 @@ for (let i = 0; i < 3; i++) {
|
|
141
141
|
topic.flush(numbers);
|
142
142
|
```
|
143
143
|
|
144
|
-
###
|
145
|
-
|
146
|
-
|
147
|
-
```ts
|
148
|
-
import * as semaphore from 'ciorent/semaphore';
|
149
|
-
import * as co from 'ciorent';
|
150
|
-
|
151
|
-
// Only allow 2 task to run concurrently
|
152
|
-
const sem = semaphore.init(2);
|
153
|
-
|
154
|
-
const task = async (id: number) => {
|
155
|
-
// Acquire the semaphore or wait for the semaphore to be available
|
156
|
-
await semaphore.acquire(sem);
|
157
|
-
|
158
|
-
console.log('Task', id, 'started');
|
159
|
-
|
160
|
-
// Let the main thread schedules other tasks
|
161
|
-
for (let i = 1; i <= 5; i++) await co.nextTick;
|
162
|
-
|
163
|
-
console.log('Task', id, 'end');
|
164
|
-
|
165
|
-
// Release the semaphore
|
166
|
-
semaphore.release(sem);
|
167
|
-
}
|
168
|
-
|
169
|
-
// Try to run 5 tasks concurrently
|
170
|
-
co.spawn(5, task);
|
171
|
-
```
|
172
|
-
|
173
|
-
### Pubsub
|
174
|
-
Pubsub allows broadcasting messages to topics that can be recieved by subscribers.
|
144
|
+
### Stream
|
145
|
+
Send and recieve data asynchronously through streams.
|
175
146
|
|
176
147
|
```ts
|
177
148
|
import * as stream from 'ciorent/stream';
|
178
149
|
import * as co from 'ciorent';
|
179
150
|
|
180
|
-
const numbers = stream.init();
|
151
|
+
const numbers = stream.init<number>();
|
181
152
|
|
182
153
|
// Spawn 3 tasks that read from the stream
|
183
154
|
co.spawn(3, async (id) => {
|
@@ -198,33 +169,33 @@ for (let i = 0; i < 3; i++) {
|
|
198
169
|
stream.flush(numbers);
|
199
170
|
```
|
200
171
|
|
201
|
-
###
|
202
|
-
|
172
|
+
### Semaphore
|
173
|
+
Semaphore is a concurrency primitive used to control access to a common resource by multiple processes.
|
203
174
|
|
204
175
|
```ts
|
205
|
-
import * as
|
176
|
+
import * as semaphore from 'ciorent/semaphore';
|
177
|
+
import * as co from 'ciorent';
|
206
178
|
|
207
|
-
|
179
|
+
// Only allow 2 task to run concurrently
|
180
|
+
const sem = semaphore.init(2);
|
208
181
|
|
209
|
-
const
|
182
|
+
const task = async (id: number) => {
|
183
|
+
// Acquire the semaphore or wait for the semaphore to be available
|
184
|
+
await semaphore.acquire(sem);
|
210
185
|
|
211
|
-
|
212
|
-
// Blocks until the defer is resolved
|
213
|
-
const url = await defer.wait(deferredUrl);
|
186
|
+
console.log('Task', id, 'started');
|
214
187
|
|
215
|
-
|
216
|
-
|
217
|
-
logTime('Done fetching');
|
218
|
-
}
|
188
|
+
// Let the main thread schedules other tasks
|
189
|
+
for (let i = 1; i <= 5; i++) await co.nextTick;
|
219
190
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
191
|
+
console.log('Task', id, 'end');
|
192
|
+
|
193
|
+
// Release the semaphore
|
194
|
+
semaphore.release(sem);
|
224
195
|
}
|
225
196
|
|
226
|
-
|
227
|
-
|
197
|
+
// Try to run 5 tasks concurrently
|
198
|
+
co.spawn(5, task);
|
228
199
|
```
|
229
200
|
|
230
201
|
### Fibers
|
package/fiber.d.ts
CHANGED
@@ -5,21 +5,9 @@
|
|
5
5
|
* Describe a fiber process
|
6
6
|
*/
|
7
7
|
export type Process<TReturn = unknown> = [
|
8
|
-
/**
|
9
|
-
* The waiting promise
|
10
|
-
*/
|
11
8
|
proc: Promise<TReturn | undefined>,
|
12
|
-
/**
|
13
|
-
* Fiber status
|
14
|
-
*/
|
15
9
|
status: 0 | 1 | 2 | 3,
|
16
|
-
/**
|
17
|
-
* Callback to resume the fiber
|
18
|
-
*/
|
19
10
|
resume: null | ((state: 1 | 3) => void),
|
20
|
-
/**
|
21
|
-
* Bounded fibers
|
22
|
-
*/
|
23
11
|
children: Process[]
|
24
12
|
];
|
25
13
|
/**
|
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()=>{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??((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--}};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "ciorent",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.4.0",
|
4
4
|
"description": "A lightweight, low-overhead concurrency library",
|
5
5
|
"homepage": "https://ciorent.netlify.app",
|
6
6
|
"repository": {
|
@@ -18,15 +18,11 @@
|
|
18
18
|
"main": "./index.js",
|
19
19
|
"types": "./index.d.ts",
|
20
20
|
"exports": {
|
21
|
-
"./
|
22
|
-
"./
|
23
|
-
"./dropping-queue": "./dropping-queue.js",
|
21
|
+
"./fiber": "./fiber.js",
|
22
|
+
"./queue": "./queue.d.ts",
|
24
23
|
"./semaphore": "./semaphore.js",
|
25
|
-
"./lock": "./lock.js",
|
26
|
-
"./defer": "./defer.js",
|
27
|
-
".": "./index.js",
|
28
24
|
"./stream": "./stream.js",
|
29
25
|
"./topic": "./topic.js",
|
30
|
-
"
|
26
|
+
".": "./index.js"
|
31
27
|
}
|
32
28
|
}
|
package/queue.d.ts
CHANGED
@@ -4,30 +4,21 @@
|
|
4
4
|
/**
|
5
5
|
* Describe a fixed-sized queue
|
6
6
|
*/
|
7
|
-
export type
|
8
|
-
/**
|
9
|
-
* Pre-allocated queue
|
10
|
-
*/
|
7
|
+
export type FixedQueue<T extends {} = {}> = [
|
11
8
|
buffer: (T | undefined | null)[],
|
12
|
-
/**
|
13
|
-
* Queue capacity
|
14
|
-
*/
|
15
9
|
capacity: number,
|
16
|
-
/**
|
17
|
-
* Head pointer
|
18
|
-
*/
|
19
10
|
head: number,
|
20
|
-
/**
|
21
|
-
* Tail pointer
|
22
|
-
*/
|
23
11
|
tail: number
|
24
12
|
];
|
25
13
|
/**
|
26
14
|
* Describe a queue node (singly linked list node)
|
27
15
|
*/
|
28
|
-
export type
|
16
|
+
export type QueueNode<T> = [next: QueueNode<T> | null, value: T];
|
29
17
|
/**
|
30
|
-
*
|
31
|
-
* @param n - The queue size
|
18
|
+
* Describe an unbounded queue
|
32
19
|
*/
|
33
|
-
export
|
20
|
+
export type UnboundedQueue<T> = [head: QueueNode<T>, tail: QueueNode<T>];
|
21
|
+
/**
|
22
|
+
* Cached promise callback
|
23
|
+
*/
|
24
|
+
export type PromiseFn<T = any> = (res: (value?: T) => void) => void;
|
package/semaphore.d.ts
CHANGED
@@ -1,16 +1,15 @@
|
|
1
1
|
/**
|
2
2
|
* @module Semaphores
|
3
3
|
*/
|
4
|
-
import {
|
4
|
+
import type { PromiseFn, UnboundedQueue } from './queue.js';
|
5
5
|
/**
|
6
6
|
* Describe a semaphore
|
7
7
|
*/
|
8
|
-
export type Semaphore =
|
9
|
-
|
10
|
-
|
11
|
-
*/
|
8
|
+
export type Semaphore = [
|
9
|
+
...UnboundedQueue<() => void>,
|
10
|
+
callback: PromiseFn<void>,
|
12
11
|
remain: number
|
13
|
-
]
|
12
|
+
];
|
14
13
|
/**
|
15
14
|
* Create a semaphore that allows n accesses
|
16
15
|
*/
|
package/semaphore.js
CHANGED
@@ -1 +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]++}};
|
package/stream.d.ts
CHANGED
@@ -1,28 +1,14 @@
|
|
1
1
|
/**
|
2
2
|
* @module Streams
|
3
3
|
*/
|
4
|
-
import type {
|
5
|
-
import type { AcquireCallback } from './lock.js';
|
4
|
+
import type { PromiseFn, UnboundedQueue } from './queue.js';
|
6
5
|
/**
|
7
6
|
* Describe a stream
|
8
7
|
*/
|
9
8
|
export type Stream<T extends {} = {}> = [
|
10
|
-
|
11
|
-
|
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>
|
9
|
+
...UnboundedQueue<T | ((val?: T) => void)>,
|
10
|
+
callback: PromiseFn<T>,
|
11
|
+
queueing: boolean
|
26
12
|
];
|
27
13
|
/**
|
28
14
|
* Create a stream
|
package/stream.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export let init=()=>{let queue=[null];let s=[queue,queue,
|
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]()};
|
package/topic.d.ts
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
/**
|
2
2
|
* @module Pubsub
|
3
3
|
*/
|
4
|
-
import type {
|
5
|
-
import type { Node as QueueNode } from "./queue.js";
|
4
|
+
import type { PromiseFn, QueueNode } from './queue.js';
|
6
5
|
/**
|
7
6
|
* Describe a topic
|
8
7
|
*/
|
9
8
|
export type Topic<T extends {} = {}> = [
|
10
9
|
head: QueueNode<T>,
|
11
|
-
callback:
|
10
|
+
callback: PromiseFn<void>,
|
12
11
|
resolve: (() => void) | null,
|
13
12
|
pending: Promise<void> | null
|
14
13
|
];
|
@@ -41,6 +40,6 @@ export declare const flush: (t: Topic) => void;
|
|
41
40
|
export declare const subscribe: <T extends {}>(t: Topic<T>) => Subscriber<T>;
|
42
41
|
/**
|
43
42
|
* Wait for messages from the topic
|
44
|
-
* @param
|
43
|
+
* @param s
|
45
44
|
*/
|
46
45
|
export declare const dispatch: <T extends {}>(s: Subscriber<T>) => Promise<T | undefined>;
|
package/defer.d.ts
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @module Deferred values
|
3
|
-
*/
|
4
|
-
/**
|
5
|
-
* Describe a defer
|
6
|
-
*/
|
7
|
-
export type Defer<T = any> = [
|
8
|
-
wait: Promise<T>,
|
9
|
-
open: (value: T | PromiseLike<T>) => void
|
10
|
-
];
|
11
|
-
/**
|
12
|
-
* Create a latch
|
13
|
-
*/
|
14
|
-
export declare const init: <T>() => Defer<T>;
|
15
|
-
/**
|
16
|
-
* Wait until a deferred is resolved
|
17
|
-
*/
|
18
|
-
export declare const wait: <T>(d: Defer<T>) => Promise<T>;
|
19
|
-
/**
|
20
|
-
* Resolve the defer
|
21
|
-
*/
|
22
|
-
export declare const resolve: (<T extends {}>(d: Defer<T>, p: T | PromiseLike<T>) => void) & ((d: Defer<void>) => void);
|
package/defer.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export let init=()=>{let r;return[new Promise((res)=>{r=res}),r]};export let wait=(d)=>d[0];export let resolve=(d,p)=>{d[1](p)};
|
package/dropping-queue.d.ts
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @module Dropping queues
|
3
|
-
*/
|
4
|
-
import type { Fixed } from './queue.js';
|
5
|
-
export { fixed as init } from './queue.js';
|
6
|
-
export { pop } from './sliding-queue.js';
|
7
|
-
/**
|
8
|
-
* Push an item to a dropping queue
|
9
|
-
* @param q - The queue to push to
|
10
|
-
* @param item
|
11
|
-
*/
|
12
|
-
export declare const push: <T extends {}>(q: Fixed<T>, item: T) => boolean;
|
package/dropping-queue.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export{fixed as init}from"./queue.js";export{pop}from"./sliding-queue.js";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/lock.d.ts
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @module Lock utilities
|
3
|
-
*/
|
4
|
-
import type { Node as QueueNode } from './queue.js';
|
5
|
-
/**
|
6
|
-
* Describe a lock
|
7
|
-
*/
|
8
|
-
export type Lock<T = any> = [
|
9
|
-
/**
|
10
|
-
* The head of the Promise resolve queue
|
11
|
-
*/
|
12
|
-
head: QueueNode<(value?: T) => void>,
|
13
|
-
/**
|
14
|
-
* The tail of the Promise resolve queue
|
15
|
-
*/
|
16
|
-
tail: QueueNode<(value?: T) => void>
|
17
|
-
];
|
18
|
-
/**
|
19
|
-
* Release an item
|
20
|
-
* @param lock
|
21
|
-
* @param value
|
22
|
-
*/
|
23
|
-
export declare const release: <T>(lock: Lock<T>, value?: T) => void;
|
24
|
-
/**
|
25
|
-
* Return true if all items are released
|
26
|
-
* @param lock
|
27
|
-
*/
|
28
|
-
export declare const released: (lock: Lock) => boolean;
|
29
|
-
/**
|
30
|
-
* Release all items of a lock
|
31
|
-
* @param lock
|
32
|
-
*/
|
33
|
-
export declare const flush: (lock: Lock) => void;
|
package/lock.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export let release=(lock,value)=>{(lock[1]=lock[1][0])[1](value)};export let released=(lock)=>lock[1][0]===null;export let flush=(lock)=>{while(lock[1][0]!==null)(lock[1]=lock[1][0])[1]()};
|
package/queue.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export let fixed=(n)=>[new Array(n),n,-1,-1];
|
package/sliding-queue.d.ts
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @module Sliding queues
|
3
|
-
*/
|
4
|
-
import type { Fixed } from './queue.js';
|
5
|
-
export { fixed as init } from './queue.js';
|
6
|
-
/**
|
7
|
-
* Push an item to a sliding queue
|
8
|
-
* @param q - The queue to push to
|
9
|
-
* @param item
|
10
|
-
*/
|
11
|
-
export declare const push: <T extends {}>(q: Fixed<T>, item: T) => void;
|
12
|
-
/**
|
13
|
-
* Pop an item from the queue
|
14
|
-
* @param q - The queue to pop from
|
15
|
-
*/
|
16
|
-
export declare const pop: <T extends {}>(q: Fixed<T>) => T | undefined;
|
package/sliding-queue.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export{fixed as init}from"./queue.js";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}};
|