ciorent 0.0.18 → 0.0.21

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
@@ -30,70 +30,74 @@ Virtual threads with more controlled execution.
30
30
  import * as cio from 'ciorent';
31
31
  import * as fiber from 'ciorent/fiber';
32
32
 
33
- function* thread1() {
33
+ const thread1 = fiber.fn(function* () {
34
34
  console.log('Fiber 1 started');
35
- yield;
35
+
36
+ // Thread1 will be interrupted by thread2
37
+ // As thread2 will end first
38
+ yield cio.sleep(1000);
39
+
36
40
  console.log('Fiber 1 done');
37
- }
41
+ });
38
42
 
39
- function* thread2() {
43
+ const thread2 = fiber.fn(function* (thread) {
40
44
  console.log('Fiber 2 started');
41
45
 
42
46
  yield;
43
47
  console.log('Fiber 2 resumed');
44
48
 
45
- // Wait for a promise
46
- yield* fiber.wait(cio.sleep(1000));
47
- console.log('Fiber 2 waited for 1s');
48
-
49
- // Start task 1 and wait for it to be done
50
- yield* fiber.join(
51
- fiber.start(thread1())
52
- );
49
+ // Start thread 1 and make thread1
50
+ // lifetime depends on thread2
51
+ fiber.mount(fiber.start(thread1), thread);
53
52
 
54
53
  console.log('Fiber 2 done');
55
- }
54
+ });
56
55
 
57
56
  // Start running the thread
58
- fiber.start(thread2());
57
+ fiber.start(thread2);
59
58
  ```
60
59
 
61
- ## Channel
62
- 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.
60
+ ## Latch
61
+ Latch is a synchronization primitive that allows one process to wait until another completes an operation before continuing execution.
63
62
 
64
63
  ```ts
65
- import * as channel from 'ciorent/channel';
64
+ import * as latch from 'ciorent/latch';
66
65
  import * as cio from 'ciorent';
67
66
 
68
- const c = channel.init<number>();
67
+ const fetchLatch = latch.init();
69
68
 
70
- const run = async () => {
71
- for (let i = 0; i < 10; i++) {
72
- await cio.sleep(10);
73
- channel.send(c, i);
74
- console.log('Sent', i);
75
- }
69
+ const task = async () => {
70
+ // Blocks until the latch is open
71
+ await latch.pause(fetchLatch);
76
72
 
77
- // Resolve all waiting promises with `undefined`
78
- // This is a way to tell the reciever to not listen to more data
79
- channel.flush(c);
80
- };
73
+ const res = await fetch('http://example.com');
74
+ console.log('Fetch status:', res.status);
75
+ }
81
76
 
82
- const log = async () => {
83
- while (true) {
84
- // Wait until a value is sent
85
- const x = await channel.recieve(c);
86
- if (x == null) break;
77
+ const prepare = () => {
78
+ console.log('Run before fetch:', performance.now().toFixed(2));
79
+ }
87
80
 
88
- console.log('Recieved', x);
89
- };
81
+ const main = async () => {
82
+ const p = task();
83
+ await cio.sleep(500);
84
+ prepare();
85
+
86
+ // Allows all previously blocked tasks to run
87
+ latch.open(fetchLatch);
88
+
89
+ // Reclose the latch
90
+ // Tasks that aren't blocked yet will be blocked
91
+ latch.reset(fetchLatch);
92
+
93
+ return p;
90
94
  }
91
95
 
92
- run();
93
- log();
96
+ // Run fetch after 500ms
97
+ await main();
94
98
 
95
- // This runs first
96
- console.log('Starting...');
99
+ // Run fetch after another 500ms
100
+ await main();
97
101
  ```
98
102
 
99
103
  ## Pubsub
@@ -132,47 +136,42 @@ cio.concurrent(5, async (id: number) => {
132
136
  publisher();
133
137
  ```
134
138
 
135
- ## Latch
136
- Latch is a synchronization primitive that allows one process to wait until another completes an operation before continuing execution.
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.
137
141
 
138
142
  ```ts
139
- import * as latch from 'ciorent/latch';
143
+ import * as channel from 'ciorent/channel';
140
144
  import * as cio from 'ciorent';
141
145
 
142
- const fetchLatch = latch.init();
143
-
144
- const task = async () => {
145
- // Blocks until the latch is open
146
- await latch.pause(fetchLatch);
147
-
148
- const res = await fetch('http://example.com');
149
- console.log('Fetch status:', res.status);
150
- }
151
-
152
- const prepare = () => {
153
- console.log('Run before fetch:', performance.now().toFixed(2));
154
- }
146
+ const c = channel.init<number>();
155
147
 
156
- const main = async () => {
157
- const p = task();
158
- await cio.sleep(500);
159
- prepare();
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
+ }
160
154
 
161
- // Allows all previously blocked tasks to run
162
- latch.open(fetchLatch);
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
+ };
163
159
 
164
- // Reclose the latch
165
- // Tasks that aren't blocked yet will be blocked
166
- latch.reset(fetchLatch);
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;
167
165
 
168
- return p;
166
+ console.log('Recieved', x);
167
+ };
169
168
  }
170
169
 
171
- // Run fetch after 500ms
172
- await main();
170
+ run();
171
+ log();
173
172
 
174
- // Run fetch after another 500ms
175
- await main();
173
+ // This runs first
174
+ console.log('Starting...');
176
175
  ```
177
176
 
178
177
  ## Utilities
@@ -207,13 +206,15 @@ task2();
207
206
  ```
208
207
 
209
208
  ### Sleep
210
- A cross-runtime sleep function.
209
+ Cross-runtime synchronous and asynchronous sleep functions.
211
210
  ```ts
212
211
  import { sleep, sleepSync } from 'ciorent';
213
212
 
214
213
  await sleep(500);
215
214
  console.log('Hi');
216
215
 
216
+ // This blocks the current thread
217
+ // On the browser this only works in workers
217
218
  sleepSync(500);
218
219
  console.log('Hi');
219
220
  ```
package/fiber.d.ts ADDED
@@ -0,0 +1,91 @@
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
+ * Control the fiber with an abort signal
84
+ * @param t
85
+ * @param signal
86
+ */
87
+ export declare const control: (t: Thread, signal: AbortSignal) => void;
88
+ /**
89
+ * Unwrap a promise result
90
+ */
91
+ 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 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.0.18",
3
+ "version": "0.0.21",
4
4
  "description": "A lightweight, low-overhead concurrency library",
5
5
  "homepage": "https://ciorent.netlify.app",
6
6
  "repository": {
@@ -18,15 +18,14 @@
18
18
  "main": "./index.js",
19
19
  "types": "./index.d.ts",
20
20
  "exports": {
21
- "./fixed-queue": "./fixed-queue.js",
22
21
  "./sliding-queue": "./sliding-queue.js",
22
+ "./channel": "./channel.js",
23
+ "./semaphore": "./semaphore.js",
24
+ "./topic": "./topic.js",
23
25
  ".": "./index.js",
24
26
  "./dropping-queue": "./dropping-queue.js",
25
- "./semaphore": "./semaphore.js",
26
- "./channel": "./channel.js",
27
- "./fiber": "./fiber/index.js",
28
- "./latch": "./latch.js",
29
- "./concurrent": "./concurrent.d.ts",
30
- "./topic": "./topic.js"
27
+ "./fiber": "./fiber.js",
28
+ "./fixed-queue": "./fixed-queue.js",
29
+ "./latch": "./latch.js"
31
30
  }
32
31
  }
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>;
package/fiber/index.d.ts DELETED
@@ -1,74 +0,0 @@
1
- /**
2
- * @module Fiber
3
- */
4
- /**
5
- * When the fiber is paused
6
- */
7
- export declare const paused: (t: Thread) => boolean;
8
- /**
9
- * When the fiber is running
10
- */
11
- export declare const running: (t: Thread) => boolean;
12
- /**
13
- * When 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 original generator
22
- */
23
- 0: Generator<T, TReturn>;
24
- /**
25
- * The waiting promise
26
- */
27
- 1: Promise<T | TReturn>;
28
- /**
29
- * Fiber status
30
- */
31
- 2: 0 | 1 | 2;
32
- /**
33
- * Callback to continue running the fiber
34
- */
35
- 3: null | (() => void);
36
- }
37
- /**
38
- * Describe a fiber runtime
39
- */
40
- export type Runtime = <const T, const TReturn>(gen: Generator<T, TReturn>) => Thread<T, TReturn>;
41
- /**
42
- * A basic fiber runtime
43
- * @param g
44
- */
45
- export declare const start: Runtime;
46
- /**
47
- * Pause the execution of a fiber
48
- * @param t
49
- */
50
- export declare const pause: (t: Thread) => void;
51
- /**
52
- * Resume the execution of a fiber
53
- * @param t
54
- */
55
- export declare const resume: (t: Thread) => void;
56
- /**
57
- * Stop the execution of a fiber and retrieve the result
58
- * @param t
59
- */
60
- export declare const stop: <T extends Thread>(t: T) => T[1];
61
- /**
62
- * Wait for a fiber and retrieve its result
63
- * @param t
64
- */
65
- export declare function join<T extends Thread>(t: T): Generator<Awaited<T[1]>, Awaited<T[1]>>;
66
- /**
67
- * Wait for a fiber to finish and retrieve its result
68
- * @param t
69
- */
70
- export declare const finish: <T extends Thread>(t: T) => T[1];
71
- /**
72
- * Wait for a promise to resolve then retrieve its result
73
- */
74
- export declare function wait<T extends Promise<any>>(t: T): Generator<Awaited<T>, Awaited<T>>;
package/fiber/index.js DELETED
@@ -1 +0,0 @@
1
- export let paused=(t)=>t[2]===0;export let running=(t)=>t[2]===1;export let done=(t)=>t[2]===2;let invoke=async(g,thread)=>{let t=g.next();while(!t.done){let v=await t.value;if(thread[2]===0){let r;let p=new Promise((res)=>{r=res});thread[3]=r;await p}if(thread[2]===2)return v;t=g.next(v)}thread[2]=2;return t.value};export let start=(g)=>{let thread=[g,null,1,null];thread[1]=invoke(g,thread);return thread};export let pause=(t)=>{if(t[2]===1)t[2]=0};export let resume=(t)=>{if(t[2]===0){t[2]=1;t[3]?.()}};export let stop=(t)=>{if(t[2]===0){t[2]=2;t[3]()}else t[2]=2;return t[1]};export function*join(t){return yield t[1]}export let finish=(t)=>t[1];export function*wait(t){return yield t}