ciorent 0.0.17 → 0.0.20

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
@@ -23,42 +23,38 @@ const task = semaphore.task(
23
23
  cio.concurrent(6, task);
24
24
  ```
25
25
 
26
- ## Channel
27
- 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.
26
+ ## Fibers
27
+ Virtual threads with more controlled execution.
28
28
 
29
29
  ```ts
30
- import * as channel from 'ciorent/channel';
31
30
  import * as cio from 'ciorent';
31
+ import * as fiber from 'ciorent/fiber';
32
32
 
33
- const c = channel.init<number>();
33
+ const thread1 = fiber.fn(function* () {
34
+ console.log('Fiber 1 started');
34
35
 
35
- const run = async () => {
36
- for (let i = 0; i < 10; i++) {
37
- await cio.sleep(10);
38
- channel.send(c, i);
39
- console.log('Sent', i);
40
- }
36
+ // Thread1 will be interrupted by thread2
37
+ // As thread2 will end first
38
+ yield cio.sleep(1000);
41
39
 
42
- // Resolve all waiting promises with `undefined`
43
- // This is a way to tell the reciever to not listen to more data
44
- channel.flush(c);
45
- };
40
+ console.log('Fiber 1 done');
41
+ })
46
42
 
47
- const log = async () => {
48
- while (true) {
49
- // Wait until a value is sent
50
- const x = await channel.recieve(c);
51
- if (x == null) break;
43
+ const thread2 = fiber.fn(function* (thread) {
44
+ console.log('Fiber 2 started');
52
45
 
53
- console.log('Recieved', x);
54
- };
55
- }
46
+ yield;
47
+ console.log('Fiber 2 resumed');
56
48
 
57
- run();
58
- log();
49
+ // Start thread 1 and make thread1
50
+ // lifetime depends on thread2
51
+ fiber.mount(fiber.start(thread1), thread);
59
52
 
60
- // This runs first
61
- console.log('Starting...');
53
+ console.log('Fiber 2 done');
54
+ });
55
+
56
+ // Start running the thread
57
+ fiber.start(thread2);
62
58
  ```
63
59
 
64
60
  ## Pubsub
@@ -140,6 +136,44 @@ await main();
140
136
  await main();
141
137
  ```
142
138
 
139
+ ## Channel
140
+ 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
+ ```ts
143
+ import * as channel from 'ciorent/channel';
144
+ import * as cio from 'ciorent';
145
+
146
+ const c = channel.init<number>();
147
+
148
+ const run = async () => {
149
+ for (let i = 0; i < 10; i++) {
150
+ await cio.sleep(10);
151
+ channel.send(c, i);
152
+ console.log('Sent', i);
153
+ }
154
+
155
+ // Resolve all waiting promises with `undefined`
156
+ // This is a way to tell the reciever to not listen to more data
157
+ channel.flush(c);
158
+ };
159
+
160
+ const log = async () => {
161
+ while (true) {
162
+ // Wait until a value is sent
163
+ const x = await channel.recieve(c);
164
+ if (x == null) break;
165
+
166
+ console.log('Recieved', x);
167
+ };
168
+ }
169
+
170
+ run();
171
+ log();
172
+
173
+ // This runs first
174
+ console.log('Starting...');
175
+ ```
176
+
143
177
  ## Utilities
144
178
  ### Pausing
145
179
  Delay the execution of a function for other asynchronous tasks to run.
@@ -172,12 +206,17 @@ task2();
172
206
  ```
173
207
 
174
208
  ### Sleep
175
- A cross-runtime sleep function.
209
+ Cross-runtime synchronous and asynchronous sleep functions.
176
210
  ```ts
177
- import { sleep } from 'ciorent';
211
+ import { sleep, sleepSync } from 'ciorent';
178
212
 
179
213
  await sleep(500);
180
214
  console.log('Hi');
215
+
216
+ // This blocks the current thread
217
+ // On the browser this only works in workers
218
+ sleepSync(500);
219
+ console.log('Hi');
181
220
  ```
182
221
 
183
222
  ### Spawning tasks
package/fiber.d.ts ADDED
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @module Fibers
3
+ */
4
+ /**
5
+ * Check whether the fiber is paused
6
+ */
7
+ export declare const paused: (t: Thread) => boolean;
8
+ /**
9
+ * Check whether the fiber is running
10
+ */
11
+ export declare const running: (t: Thread) => boolean;
12
+ /**
13
+ * Check whether the fiber is done
14
+ */
15
+ export declare const done: (t: Thread) => boolean;
16
+ /**
17
+ * Describe a fiber
18
+ */
19
+ export interface Thread<T = unknown, TReturn = unknown> {
20
+ /**
21
+ * The waiting promise
22
+ */
23
+ 0: Promise<T | TReturn>;
24
+ /**
25
+ * Fiber status
26
+ */
27
+ 1: 0 | 1 | 2;
28
+ /**
29
+ * Callback to continue running the fiber
30
+ */
31
+ 2: null | (() => void);
32
+ /**
33
+ * Bounded threads
34
+ */
35
+ 3: Thread[];
36
+ }
37
+ /**
38
+ * Describe a fiber runtime
39
+ */
40
+ export type Runtime = <const T, const TReturn, const Args extends any[]>(gen: (thread: Thread<T, TReturn>, ...args: Args) => Generator<T, TReturn>, ...args: Args) => Thread<T, TReturn>;
41
+ /**
42
+ * Create a fiber function
43
+ * @param f
44
+ */
45
+ export declare const fn: <const Fn extends (thread: Thread, ...args: any[]) => Generator>(f: Fn) => Fn;
46
+ /**
47
+ * A basic fiber runtime
48
+ * @param g
49
+ */
50
+ export declare const start: Runtime;
51
+ /**
52
+ * Pause the execution of a fiber
53
+ * @param t
54
+ */
55
+ export declare const pause: (t: Thread) => void;
56
+ /**
57
+ * Resume the execution of a fiber
58
+ * @param t
59
+ */
60
+ export declare const resume: (t: Thread) => void;
61
+ /**
62
+ * Stop the execution of a fiber
63
+ * @param t
64
+ */
65
+ export declare const stop: (t: Thread) => void;
66
+ /**
67
+ * Wait for a fiber and retrieve its result
68
+ * @param t
69
+ */
70
+ export declare function join<T extends Thread>(t: T): Generator<Awaited<T[1]>, Awaited<T[1]>>;
71
+ /**
72
+ * Wait for a fiber to finish and retrieve its result
73
+ * @param t
74
+ */
75
+ export declare const finish: <T extends Thread>(t: T) => T[1];
76
+ /**
77
+ * Mount child fiber lifetime to parent lifetime
78
+ * @param child
79
+ * @param parent
80
+ */
81
+ export declare const mount: (child: Thread, parent: Thread) => void;
82
+ /**
83
+ * Unwrap a promise result
84
+ */
85
+ export declare function unwrap<T extends Promise<any>>(t: T): Generator<Awaited<T>, Awaited<T>>;
package/fiber.js ADDED
@@ -0,0 +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 function*unwrap(t){return yield t}
package/fixed-queue.d.ts CHANGED
@@ -26,10 +26,7 @@ export interface FixedQueue<T extends {}> {
26
26
  /**
27
27
  * Describe a queue node (singly linked list node)
28
28
  */
29
- export type QueueNode<T> = [
30
- value: T,
31
- next: QueueNode<T> | null
32
- ];
29
+ export type QueueNode<T> = [value: T, next: QueueNode<T> | null];
33
30
  /**
34
31
  * Create a fixed queue.
35
32
  * @param n - The queue size
package/index.d.ts CHANGED
@@ -14,6 +14,13 @@ export declare const pause: Promise<void>;
14
14
  * @param ms - Sleep duration in milliseconds
15
15
  */
16
16
  export declare const sleep: (ms: number) => Promise<void>;
17
+ /**
18
+ * Sleep for a duration synchronously.
19
+ *
20
+ * On the browser it only works in workers.
21
+ * @param ms - Sleep duration in milliseconds
22
+ */
23
+ export declare const sleepSync: (ms: number) => void;
17
24
  /**
18
25
  * Spawn n tasks that runs sequentially
19
26
  * @param n
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)}));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)=>{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)};
package/latch.d.ts CHANGED
@@ -4,10 +4,7 @@
4
4
  /**
5
5
  * Describe a latch
6
6
  */
7
- export type Latch = [
8
- pause: Promise<void>,
9
- open: () => void
10
- ];
7
+ export type Latch = [pause: Promise<void>, open: () => void];
11
8
  /**
12
9
  * Create a latch
13
10
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ciorent",
3
- "version": "0.0.17",
3
+ "version": "0.0.20",
4
4
  "description": "A lightweight, low-overhead concurrency library",
5
5
  "homepage": "https://ciorent.netlify.app",
6
6
  "repository": {
@@ -17,27 +17,15 @@
17
17
  "type": "module",
18
18
  "main": "./index.js",
19
19
  "types": "./index.d.ts",
20
- "scripts": {
21
- "task": "bun scripts/task.ts",
22
- "build:test": "bun task build && bun docs && bun test",
23
- "build:publish": "bun build:test && bun task report-size && bun task publish",
24
- "lint": "eslint ./src",
25
- "lint:fix": "eslint ./src --fix",
26
- "docs": "typedoc"
27
- },
28
- "devDependencies": {
29
- "@stylistic/eslint-plugin": "latest",
30
- "@types/bun": "latest",
31
- "@types/uglify-js": "latest",
32
- "eslint": "latest",
33
- "eslint-plugin-jsdoc": "latest",
34
- "mitata": "latest",
35
- "terser": "^5.39.0",
36
- "tsx": "latest",
37
- "typedoc": "^0.27.9",
38
- "typedoc-material-theme": "^1.3.0",
39
- "typedoc-plugin-inline-sources": "^1.2.1",
40
- "typescript": "latest",
41
- "typescript-eslint": "latest"
20
+ "exports": {
21
+ "./fixed-queue": "./fixed-queue.js",
22
+ "./sliding-queue": "./sliding-queue.js",
23
+ "./fiber": "./fiber.js",
24
+ "./channel": "./channel.js",
25
+ "./dropping-queue": "./dropping-queue.js",
26
+ "./topic": "./topic.js",
27
+ ".": "./index.js",
28
+ "./semaphore": "./semaphore.js",
29
+ "./latch": "./latch.js"
42
30
  }
43
- }
31
+ }
package/semaphore.d.ts CHANGED
@@ -34,7 +34,7 @@ export declare const signal: (s: Semaphore) => void;
34
34
  /**
35
35
  * Wrap a task to bind to a custom semaphore later
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 wrap: <Args extends any[], Return extends Promise<any>>(f: (...args: Args) => Return) => ((s: Semaphore, ...a: Args) => Return);
38
38
  /**
39
39
  * Create a task that acquire a semaphore and release the access when it's finished
40
40
  */
package/concurrent.d.ts DELETED
@@ -1,11 +0,0 @@
1
- /**
2
- * @module Concurrency controls
3
- */
4
- /**
5
- * Describe an async task
6
- */
7
- export type Task<T = unknown> = () => Promise<T>;
8
- /**
9
- * Describe a concurrency controller
10
- */
11
- export type Controller = <T>(task: Task<T>) => Promise<T>;