ciorent 0.0.21 → 0.0.22

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
@@ -6,9 +6,7 @@ Semaphore is a concurrency primitive used to control access to a common resource
6
6
  import * as semaphore from 'ciorent/semaphore';
7
7
  import * as cio from 'ciorent';
8
8
 
9
- // Only allow 2 of these tasks to run concurrently
10
- const task = semaphore.task(
11
- semaphore.init(2),
9
+ const task = semaphore.wrap(
12
10
  async (task: number) => {
13
11
  for (let i = 1; i <= 5; i++) {
14
12
  console.log('Task', task, 'iteration', i);
@@ -19,42 +17,11 @@ const task = semaphore.task(
19
17
  }
20
18
  );
21
19
 
22
- // Try to run 6 tasks concurrently
23
- cio.concurrent(6, task);
24
- ```
25
-
26
- ## Fibers
27
- Virtual threads with more controlled execution.
28
-
29
- ```ts
30
- import * as cio from 'ciorent';
31
- import * as fiber from 'ciorent/fiber';
32
-
33
- const thread1 = fiber.fn(function* () {
34
- console.log('Fiber 1 started');
35
-
36
- // Thread1 will be interrupted by thread2
37
- // As thread2 will end first
38
- yield cio.sleep(1000);
39
-
40
- console.log('Fiber 1 done');
41
- });
42
-
43
- const thread2 = fiber.fn(function* (thread) {
44
- console.log('Fiber 2 started');
45
-
46
- yield;
47
- console.log('Fiber 2 resumed');
48
-
49
- // Start thread 1 and make thread1
50
- // lifetime depends on thread2
51
- fiber.mount(fiber.start(thread1), thread);
20
+ // Only allow 2 task to run concurrently
21
+ const sem = semaphore.init(2);
52
22
 
53
- console.log('Fiber 2 done');
54
- });
55
-
56
- // Start running the thread
57
- fiber.start(thread2);
23
+ // Try to run 6 tasks concurrently
24
+ cio.concurrent(6, (sem, id) => task(sem, id), sem);
58
25
  ```
59
26
 
60
27
  ## Latch
@@ -136,6 +103,40 @@ cio.concurrent(5, async (id: number) => {
136
103
  publisher();
137
104
  ```
138
105
 
106
+ ## Fibers
107
+ Virtual threads with more controlled execution.
108
+
109
+ ```ts
110
+ import * as cio from 'ciorent';
111
+ import * as fiber from 'ciorent/fiber';
112
+
113
+ const thread1 = fiber.fn(function* () {
114
+ console.log('Fiber 1 started');
115
+
116
+ // Thread1 will be interrupted by thread2
117
+ // As thread2 will end first
118
+ yield cio.sleep(1000);
119
+
120
+ console.log('Fiber 1 done');
121
+ });
122
+
123
+ const thread2 = fiber.fn(function* (thread) {
124
+ console.log('Fiber 2 started');
125
+
126
+ yield;
127
+ console.log('Fiber 2 resumed');
128
+
129
+ // Start thread 1 and make thread1
130
+ // lifetime depends on thread2
131
+ fiber.mount(fiber.spawn(thread1), thread);
132
+
133
+ console.log('Fiber 2 done');
134
+ });
135
+
136
+ // Start running the thread
137
+ fiber.spawn(thread2);
138
+ ```
139
+
139
140
  ## Channel
140
141
  Channel is a synchronization primitive via message passing. A message may be sent over a channel, and another process is able to receive messages sent over a channel it has a reference to.
141
142
 
@@ -183,20 +184,23 @@ import * as cio from 'ciorent';
183
184
  // Expensive sync task
184
185
  const task1 = async () => {
185
186
  let x = 0;
186
- for (let i = 0; i < (Math.random() + 15) * 1e7; i++) {
187
- // Frequent pausing
188
- if (i % 2e6 === 0)
189
- await cio.pause;
190
187
 
188
+ // Pause to let task2 to run
189
+ await cio.pause;
190
+
191
+ for (let i = 0; i < (Math.random() + 15) * 1e6; i++)
191
192
  x += Math.random() * 32 + i * Math.round(Math.random() * 16);
192
- }
193
+
193
194
  console.log('Finish task 1:', x);
194
195
  };
195
196
 
196
197
  // Short async task
197
198
  const task2 = async () => {
198
199
  console.log('Fetch start', performance.now().toFixed(2) + 'ms');
200
+
201
+ // This will pause task2 to let task1 to continue running
199
202
  const txt = await fetch('http://example.com');
203
+
200
204
  console.log('Fetch status', txt.status);
201
205
  };
202
206
 
package/fiber.d.ts CHANGED
@@ -47,7 +47,7 @@ export declare const fn: <const Fn extends (thread: Thread, ...args: any[]) => G
47
47
  * A basic fiber runtime
48
48
  * @param g
49
49
  */
50
- export declare const start: Runtime;
50
+ export declare const spawn: Runtime;
51
51
  /**
52
52
  * Pause the execution of a fiber
53
53
  * @param t
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)=>{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;thread[3].forEach(stop);return t.value};export let fn=(f)=>f;export let start=(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)=>{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;thread[3].forEach(stop);return t.value};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/index.d.ts CHANGED
@@ -26,10 +26,10 @@ export declare const sleepSync: (ms: number) => void;
26
26
  * @param n
27
27
  * @param task - The function to run
28
28
  */
29
- export declare const sequential: (n: number, task: (id: number) => Promise<any>) => Promise<void>;
29
+ export declare const sequential: <const T extends any[]>(n: number, task: (...args: [...T, id: number]) => Promise<any>, ...args: T) => Promise<void>;
30
30
  /**
31
31
  * Spawn n tasks that runs concurrently
32
32
  * @param n
33
33
  * @param task - The function to run
34
34
  */
35
- export declare const concurrent: (n: number, task: (id: number) => Promise<any>) => Promise<any>;
35
+ export declare const concurrent: <const T extends any[]>(n: number, task: (...args: [...T, id: number]) => Promise<any>, ...args: T) => Promise<any>;
package/index.js CHANGED
@@ -1 +1 @@
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)}));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)=>{for(let i=0;i<n;i++)await task(i)};export let concurrent=(n,task)=>{let arr=new Array(n);for(let i=0;i<n;i++)arr[i]=task(i);return Promise.all(arr)};
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)}));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 concurrent=(n,task,...args)=>{let arr=new Array(n);for(let i=0;i<n;i++)arr[i]=task(...args,i);return Promise.all(arr)};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ciorent",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "description": "A lightweight, low-overhead concurrency library",
5
5
  "homepage": "https://ciorent.netlify.app",
6
6
  "repository": {
@@ -19,13 +19,13 @@
19
19
  "types": "./index.d.ts",
20
20
  "exports": {
21
21
  "./sliding-queue": "./sliding-queue.js",
22
+ "./fixed-queue": "./fixed-queue.js",
23
+ "./latch": "./latch.js",
24
+ "./dropping-queue": "./dropping-queue.js",
22
25
  "./channel": "./channel.js",
23
- "./semaphore": "./semaphore.js",
24
- "./topic": "./topic.js",
25
26
  ".": "./index.js",
26
- "./dropping-queue": "./dropping-queue.js",
27
- "./fiber": "./fiber.js",
28
- "./fixed-queue": "./fixed-queue.js",
29
- "./latch": "./latch.js"
27
+ "./topic": "./topic.js",
28
+ "./semaphore": "./semaphore.js",
29
+ "./fiber": "./fiber.js"
30
30
  }
31
31
  }
package/semaphore.d.ts CHANGED
@@ -35,7 +35,3 @@ export declare const signal: (s: Semaphore) => void;
35
35
  * Wrap a task to bind to a custom semaphore later
36
36
  */
37
37
  export declare const wrap: <Args extends any[], Return extends Promise<any>>(f: (...args: Args) => Return) => ((s: Semaphore, ...a: Args) => Return);
38
- /**
39
- * Create a task that acquire a semaphore and release the access when it's finished
40
- */
41
- export declare const task: <F extends (...args: any[]) => Promise<any>>(s: Semaphore, f: F) => F;
package/semaphore.js CHANGED
@@ -1 +1 @@
1
- import{pause as resolvedPromise}from"./index.js";export let init=(n)=>{let root=[null,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][1]=[r,null];return p}return resolvedPromise};export let signal=(s)=>{if(s[0]<0)(s[2]=s[2][1])[0]();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][1]=[r,null];await p}try{return await f(...a)}finally{signal(s)}};export let task=(s,f)=>{f=wrap(f);return(...a)=>f(s,...a)};
1
+ import{pause as resolvedPromise}from"./index.js";export let init=(n)=>{let root=[null,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][1]=[r,null];return p}return resolvedPromise};export let signal=(s)=>{if(s[0]<0)(s[2]=s[2][1])[0]();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][1]=[r,null];await p}try{return await f(...a)}finally{signal(s)}};