ciorent 0.1.1 → 0.1.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
@@ -1,4 +1,33 @@
1
1
  A lightweight, low-overhead concurrency library.
2
+ ## Semaphore
3
+ Semaphore is a concurrency primitive used to control access to a common resource by multiple processes.
4
+
5
+ ```ts
6
+ import * as semaphore from 'ciorent/semaphore';
7
+ import * as cio from 'ciorent';
8
+
9
+ // Only allow 2 task to run concurrently
10
+ const sem = semaphore.init(2);
11
+
12
+ const task = async (id: number) => {
13
+ // Acquire the semaphore or wait for the semaphore to be available
14
+ await semaphore.pause(sem);
15
+
16
+ console.log('Task', id, 'started');
17
+
18
+ // Let the main thread schedules other tasks
19
+ for (let i = 1; i <= 5; i++) await cio.pause;
20
+
21
+ console.log('Task', id, 'end');
22
+
23
+ // Release the semaphore
24
+ semaphore.signal(sem);
25
+ }
26
+
27
+ // Try to run 5 tasks concurrently
28
+ cio.concurrent(5, task);
29
+ ```
30
+
2
31
  ## Fibers
3
32
  Virtual threads with more controlled execution.
4
33
 
@@ -134,35 +163,6 @@ run();
134
163
  console.log('Starting...');
135
164
  ```
136
165
 
137
- ## Semaphore
138
- Semaphore is a concurrency primitive used to control access to a common resource by multiple processes.
139
-
140
- ```ts
141
- import * as semaphore from 'ciorent/semaphore';
142
- import * as cio from 'ciorent';
143
-
144
- // Only allow 2 task to run concurrently
145
- const sem = semaphore.init(2);
146
-
147
- const task = async (id: number) => {
148
- // Acquire the semaphore or wait for the semaphore to be available
149
- await semaphore.pause(sem);
150
-
151
- console.log('Task', id, 'started');
152
-
153
- // Let the main thread schedules other tasks
154
- for (let i = 1; i <= 5; i++) await cio.pause;
155
-
156
- console.log('Task', id, 'end');
157
-
158
- // Release the semaphore
159
- semaphore.signal(sem);
160
- }
161
-
162
- // Try to run 5 tasks concurrently
163
- cio.concurrent(5, task);
164
- ```
165
-
166
166
  ## Utilities
167
167
  ### Pausing
168
168
  Delay the execution of a function for other asynchronous tasks to run.
@@ -253,16 +253,16 @@ Limits the number of calls within a time window.
253
253
  ```ts
254
254
  import * as cio from 'ciorent';
255
255
 
256
- // Allow 1 call in 500ms
256
+ // Allow 2 calls in 500ms, other calls are dropped
257
257
  const fn = cio.rateLimit((id: number) => {
258
258
  console.log('Call ' + id + ':', Math.floor(performance.now()) + 'ms');
259
- }, 500, 1);
259
+ }, 500, 2);
260
260
 
261
- fn(1); // fn(1) gets executed
262
- await cio.sleep(100);
263
- fn(2); // fn(2) gets skipped
264
- await cio.sleep(500);
265
- fn(3); // fn(3) gets executed
261
+ // Some calls will be dropped
262
+ for (let i = 0; i < 8; i++) {
263
+ fn(i);
264
+ await cio.sleep(400);
265
+ }
266
266
  ```
267
267
 
268
268
  ### Throttle
@@ -275,6 +275,6 @@ const fn = cio.throttle((id: number) => {
275
275
  console.log(id + ': ' + Math.floor(performance.now()) + 'ms');
276
276
  }, 500, 2);
277
277
 
278
- cio.concurrent(8, (id) => fn(id));
278
+ cio.concurrent(8, fn);
279
279
  ```
280
280
 
package/fiber.js CHANGED
@@ -1 +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)=>{try{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;return t.value}finally{thread[3].forEach(stop)}};export let fn=(f)=>f;export let spawn=(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}
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)=>{try{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)return v;t=g.next(v)}thread[1]=2;return t.value}finally{thread[3].forEach(stop)}};export let fn=(f)=>f;export let spawn=(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.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "A lightweight, low-overhead concurrency library",
5
5
  "homepage": "https://ciorent.netlify.app",
6
6
  "repository": {
@@ -18,14 +18,14 @@
18
18
  "main": "./index.js",
19
19
  "types": "./index.d.ts",
20
20
  "exports": {
21
- "./sliding-queue": "./sliding-queue.js",
22
- "./semaphore": "./semaphore.js",
23
- "./topic": "./topic.js",
24
- ".": "./index.js",
25
- "./latch": "./latch.js",
26
- "./channel": "./channel.js",
27
21
  "./fixed-queue": "./fixed-queue.js",
22
+ "./sliding-queue": "./sliding-queue.js",
28
23
  "./dropping-queue": "./dropping-queue.js",
29
- "./fiber": "./fiber.js"
24
+ "./fiber": "./fiber.js",
25
+ "./channel": "./channel.js",
26
+ ".": "./index.js",
27
+ "./topic": "./topic.js",
28
+ "./semaphore": "./semaphore.js",
29
+ "./latch": "./latch.js"
30
30
  }
31
31
  }
package/semaphore.d.ts CHANGED
@@ -32,6 +32,6 @@ export declare const pause: (s: Semaphore) => Promise<void>;
32
32
  */
33
33
  export declare const signal: (s: Semaphore) => void;
34
34
  /**
35
- * Wrap a task to bind to a custom semaphore later
35
+ * Bind a task to a semaphore
36
36
  */
37
- export declare const wrap: <Args extends any[], Return extends Promise<any>>(f: (...args: Args) => Return) => ((s: Semaphore, ...a: Args) => Return);
37
+ export declare const bind: <T extends (...args: any[]) => Promise<any>>(f: T, s: Semaphore) => T;
package/semaphore.js CHANGED
@@ -1 +1 @@
1
- import{pause as resolvedPromise}from"./index.js";export let init=(n)=>{let root=[null];return[n,root,root]};export let pause=(s)=>{s[0]--;if(s[0]<0){let r;let p=new Promise((res)=>{r=res});s[1]=s[1][0]=[null,r];return p}return resolvedPromise};export let signal=(s)=>{if(s[0]<0)(s[2]=s[2][0])[1]();s[0]++};export let wrap=(f)=>async(s,...a)=>{s[0]--;if(s[0]<0){let r;let p=new Promise((res)=>{r=res});s[1]=s[1][0]=[null,r];await p}try{return await f(...a)}finally{signal(s)}};
1
+ import{pause as resolvedPromise}from"./index.js";export let init=(n)=>{let root=[null];return[n,root,root]};export let pause=(s)=>{s[0]--;if(s[0]<0){let r;let p=new Promise((res)=>{r=res});s[1]=s[1][0]=[null,r];return p}return resolvedPromise};export let signal=(s)=>{if(s[0]<0)(s[2]=s[2][0])[1]();s[0]++};export let bind=(f,s)=>async(...a)=>{s[0]--;if(s[0]<0){let r;let p=new Promise((res)=>{r=res});s[1]=s[1][0]=[null,r];await p}try{return await f(...a)}finally{if(s[0]<0)(s[2]=s[2][0])[1]();s[0]++}};