ciorent 0.3.7 → 0.3.8

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
@@ -32,7 +32,7 @@ Cross-runtime synchronous and asynchronous sleep functions.
32
32
  ```ts
33
33
  import * as co from 'ciorent';
34
34
 
35
- const logTime = (label: string) => console.log(`${label}: ${Math.floor(performance.now())}ms`);;
35
+ const logTime = (label: string) => console.log(`${label}: ${Math.floor(performance.now())}ms`);
36
36
 
37
37
  logTime('Start');
38
38
 
@@ -112,39 +112,33 @@ co.spawn(5, task2);
112
112
  ```
113
113
 
114
114
  ### Pubsub
115
- A fast, simple publish-subscribe API.
115
+ Pubsub allows broadcasting messages to topics that can be recieved by subscribers.
116
116
 
117
117
  ```ts
118
118
  import * as topic from 'ciorent/topic';
119
119
  import * as co from 'ciorent';
120
120
 
121
- const messages = topic.init<number>();
122
-
123
- // A task that publish messages
124
- const publisher = async () => {
125
- for (let i = 0; i < 3; i++) {
126
- await co.sleep(100);
127
- topic.publish(messages, i);
128
- }
129
-
130
- // Resolve all waiting promises
131
- // And clear the value queue
132
- topic.flush(messages);
133
- }
121
+ const numbers = topic.init();
134
122
 
135
- // Spawn 3 tasks that recieve messages
136
- co.spawn(3, async (id: number) => {
137
- const sub = topic.subscribe(messages);
123
+ // Spawn 3 tasks that subscribe to the topic
124
+ co.spawn(3, async (id) => {
125
+ const subscriber = topic.subscribe(numbers);
138
126
 
139
127
  while (true) {
140
- // Block until the value is sent
141
- const x = await topic.dispatch(sub);
142
- if (x == null) break;
143
- console.log(`Task ${id} recieved: ${x}`);
128
+ const msg = await topic.dispatch(subscriber);
129
+ if (msg == null) return;
130
+ console.log('Task', id, 'recieved:', msg);
144
131
  }
145
132
  });
146
133
 
147
- publisher();
134
+ // Publish messages to the topic
135
+ for (let i = 0; i < 3; i++) {
136
+ topic.publish(numbers, i);
137
+ await co.nextTick;
138
+ }
139
+
140
+ // Send undefined to every topic
141
+ topic.flush(numbers);
148
142
  ```
149
143
 
150
144
  ### Semaphore
@@ -176,6 +170,34 @@ const task = async (id: number) => {
176
170
  co.spawn(5, task);
177
171
  ```
178
172
 
173
+ ### Pubsub
174
+ Pubsub allows broadcasting messages to topics that can be recieved by subscribers.
175
+
176
+ ```ts
177
+ import * as stream from 'ciorent/stream';
178
+ import * as co from 'ciorent';
179
+
180
+ const numbers = stream.init();
181
+
182
+ // Spawn 3 tasks that read from the stream
183
+ co.spawn(3, async (id) => {
184
+ while (true) {
185
+ const msg = await stream.read(numbers);
186
+ if (msg == null) return;
187
+ console.log('Task', id, 'recieved:', msg);
188
+ }
189
+ });
190
+
191
+ // Write messages to the stream
192
+ for (let i = 0; i < 3; i++) {
193
+ stream.write(numbers, i);
194
+ await co.nextTick;
195
+ }
196
+
197
+ // Send undefined to every stream
198
+ stream.flush(numbers);
199
+ ```
200
+
179
201
  ### Defer
180
202
  Wait for a value to be resolved.
181
203
 
@@ -205,44 +227,6 @@ task();
205
227
  prepare();
206
228
  ```
207
229
 
208
- ### Channel
209
- 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.
210
-
211
- ```ts
212
- import * as channel from 'ciorent/channel';
213
- import * as co from 'ciorent';
214
-
215
- const chan = channel.init<number>();
216
-
217
- const run = async () => {
218
- for (let i = 0; i < 5; i++) {
219
- await co.sleep(100);
220
- channel.send(chan, i);
221
- console.log('Sent', i);
222
- }
223
-
224
- // Resolve all waiting promises with `undefined`
225
- // This is a way to tell the reciever to not listen to more data
226
- channel.flush(chan);
227
- };
228
-
229
- const log = async () => {
230
- while (true) {
231
- // Wait until a value is sent to the channel
232
- const x = await channel.recieve(chan);
233
- if (x == null) break;
234
-
235
- console.log('Recieved', x);
236
- };
237
- }
238
-
239
- log();
240
- run();
241
-
242
- // This runs first
243
- console.log('Starting...');
244
- ```
245
-
246
230
  ### Fibers
247
231
  Virtual threads with more controlled execution.
248
232
 
package/fiber.d.ts CHANGED
@@ -4,24 +4,24 @@
4
4
  /**
5
5
  * Describe a fiber process
6
6
  */
7
- export interface Process<TReturn = unknown> {
7
+ export type Process<TReturn = unknown> = [
8
8
  /**
9
9
  * The waiting promise
10
10
  */
11
- 0: Promise<TReturn | undefined>;
11
+ proc: Promise<TReturn | undefined>,
12
12
  /**
13
13
  * Fiber status
14
14
  */
15
- 1: 0 | 1 | 2 | 3;
15
+ status: 0 | 1 | 2 | 3,
16
16
  /**
17
- * Callback to continue running the fiber
17
+ * Callback to resume the fiber
18
18
  */
19
- 2: null | ((state: 1 | 3) => void);
19
+ resume: null | ((state: 1 | 3) => void),
20
20
  /**
21
21
  * Bounded fibers
22
22
  */
23
- 3: Process[];
24
- }
23
+ children: Process[]
24
+ ];
25
25
  /**
26
26
  * Describe a fiber runtime
27
27
  */
package/lock.d.ts CHANGED
@@ -5,16 +5,16 @@ import type { Node as QueueNode } from './queue.js';
5
5
  /**
6
6
  * Describe a lock
7
7
  */
8
- export interface Lock<T = any> {
8
+ export type Lock<T = any> = [
9
9
  /**
10
10
  * The head of the Promise resolve queue
11
11
  */
12
- 0: QueueNode<(value?: T) => void>;
12
+ head: QueueNode<(value?: T) => void>,
13
13
  /**
14
14
  * The tail of the Promise resolve queue
15
15
  */
16
- 1: QueueNode<(value?: T) => void>;
17
- }
16
+ tail: QueueNode<(value?: T) => void>
17
+ ];
18
18
  /**
19
19
  * Release an item
20
20
  * @param lock
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ciorent",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "A lightweight, low-overhead concurrency library",
5
5
  "homepage": "https://ciorent.netlify.app",
6
6
  "repository": {
@@ -19,14 +19,14 @@
19
19
  "types": "./index.d.ts",
20
20
  "exports": {
21
21
  "./queue": "./queue.js",
22
- "./channel": "./channel.js",
23
22
  "./sliding-queue": "./sliding-queue.js",
24
- "./topic": "./topic.js",
25
- "./lock": "./lock.js",
26
- ".": "./index.js",
23
+ "./dropping-queue": "./dropping-queue.js",
27
24
  "./semaphore": "./semaphore.js",
25
+ "./lock": "./lock.js",
28
26
  "./defer": "./defer.js",
29
- "./dropping-queue": "./dropping-queue.js",
27
+ ".": "./index.js",
28
+ "./stream": "./stream.js",
29
+ "./topic": "./topic.js",
30
30
  "./fiber": "./fiber.js"
31
31
  }
32
32
  }
package/queue.d.ts CHANGED
@@ -4,33 +4,30 @@
4
4
  /**
5
5
  * Describe a fixed-sized queue
6
6
  */
7
- export interface Fixed<T extends {}> {
7
+ export type Fixed<T extends {} = {}> = [
8
8
  /**
9
9
  * Pre-allocated queue
10
10
  */
11
- readonly 0: (T | undefined | null)[];
11
+ buffer: (T | undefined | null)[],
12
12
  /**
13
13
  * Queue capacity
14
14
  */
15
- readonly 1: number;
15
+ capacity: number,
16
16
  /**
17
17
  * Head pointer
18
18
  */
19
- 2: number;
19
+ head: number,
20
20
  /**
21
21
  * Tail pointer
22
22
  */
23
- 3: number;
24
- }
23
+ tail: number
24
+ ];
25
25
  /**
26
26
  * Describe a queue node (singly linked list node)
27
27
  */
28
- export interface Node<T> {
29
- 0: Node<T> | null;
30
- 1: T;
31
- }
28
+ export type Node<T> = [next: Node<T> | null, value: T];
32
29
  /**
33
30
  * Create a fixed queue
34
31
  * @param n - The queue size
35
32
  */
36
- export declare const fixed: <T extends {}>(n: number) => Fixed<T>;
33
+ export declare const fixed: <T extends {} = {}>(n: number) => Fixed<T>;
package/semaphore.d.ts CHANGED
@@ -5,12 +5,12 @@ import { type Lock } from './lock.js';
5
5
  /**
6
6
  * Describe a semaphore
7
7
  */
8
- export interface Semaphore extends Lock<void> {
8
+ export type Semaphore = Lock<void, [
9
9
  /**
10
10
  * Current remaining process allowed
11
11
  */
12
- 3: number;
13
- }
12
+ remain: number
13
+ ]>;
14
14
  /**
15
15
  * Create a semaphore that allows n accesses
16
16
  */
package/stream.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @module Streams
3
+ */
4
+ import type { Node as QueueNode } from './queue.js';
5
+ import type { AcquireCallback } from './lock.js';
6
+ /**
7
+ * Describe a stream
8
+ */
9
+ export type Stream<T extends {} = {}> = [
10
+ /**
11
+ * Queue head
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>
26
+ ];
27
+ /**
28
+ * Create a stream
29
+ */
30
+ export declare const init: <T extends {} = {}>() => Stream<T>;
31
+ /**
32
+ * Write a value to the stream
33
+ * @param s
34
+ * @param v
35
+ */
36
+ export declare const write: <T extends {} = {}>(s: Stream<T>, v: T) => void;
37
+ /**
38
+ * Read a value from the stream
39
+ * @param s
40
+ */
41
+ export declare const read: <T extends {} = {}>(s: Stream<T>) => Promise<T | undefined>;
42
+ /**
43
+ * Release all pending read with undefined
44
+ */
45
+ export declare const flush: (s: Stream) => void;
package/stream.js ADDED
@@ -0,0 +1 @@
1
+ export let init=()=>{let queue=[null];let s=[queue,queue,false,(res)=>{s[0]=s[0][0]=[null,res]}];return s};export let write=(s,v)=>{if(!s[2]){if(s[1][0]!==null){(s[1]=s[1][0])[1](v);return}s[2]=true}s[0]=s[0][0]=[null,v]};export let read=(s)=>{if(s[2]){s[1]=s[1][0];if(s[1][0]===null)s[2]=false;return Promise.resolve(s[1][1])}return new Promise(s[3])};export let flush=(s)=>{if(!s[2])while(s[1][0]!==null)(s[1]=s[1][0])[1]()};
package/topic.d.ts CHANGED
@@ -1,57 +1,46 @@
1
1
  /**
2
2
  * @module Pubsub
3
3
  */
4
- import type { Node as QueueNode } from './queue.js';
4
+ import type { AcquireCallback } from "./lock.js";
5
+ import type { Node as QueueNode } from "./queue.js";
5
6
  /**
6
7
  * Describe a topic
7
8
  */
8
- export interface Topic<T extends {}> {
9
- /**
10
- * The head node of the value queue
11
- */
12
- 0: QueueNode<T>;
13
- /**
14
- * The waiting subscriber resolves
15
- */
16
- 1: ((res: QueueNode<T>) => void)[];
17
- }
9
+ export type Topic<T extends {} = {}> = [
10
+ head: QueueNode<T>,
11
+ callback: AcquireCallback<void>,
12
+ resolve: (() => void) | null,
13
+ pending: Promise<void> | null
14
+ ];
18
15
  /**
19
- * Create a topic
20
- */
21
- export declare const init: <T extends {}>() => Topic<T>;
22
- /**
23
- * Describe a topic
16
+ * Describe a subscriber
24
17
  */
25
- export interface Subscriber<T extends {}> {
26
- 0: Topic<T>;
27
- 1: QueueNode<T>;
28
- }
18
+ export type Subscriber<T extends {} = {}> = [
19
+ topic: Topic<T>,
20
+ tail: QueueNode<T>
21
+ ];
29
22
  /**
30
- * Subscribe to a topic
31
- * @param t
23
+ * Create a topic
32
24
  */
33
- export declare const subscribe: <T extends {}>(t: Topic<T>) => Subscriber<T>;
25
+ export declare const init: <T extends {} = {}>() => Topic<T>;
34
26
  /**
35
- * Publish to a topic
36
- * @param t
27
+ * Publish a message to the topic
28
+ * @param t - The topic
29
+ * @param m - The message to publish
37
30
  */
38
- export declare const publish: <T extends {}>(t: Topic<T>, value: T) => void;
31
+ export declare const publish: <T extends {} = {}>(t: Topic<T>, m: T) => void;
39
32
  /**
40
- * Resolve all waiting promises and clear all pending values
41
- * @param t
33
+ * Resolve all pending dispatch
42
34
  */
43
- export declare const flush: <T extends {}>(t: Topic<T>) => void;
35
+ export declare const flush: (t: Topic) => void;
44
36
  /**
45
- * Get the next value in the message queue.
46
- *
47
- * Returns `undefined` if the message queue is empty
37
+ * Subscribe to a topic
48
38
  * @param t
39
+ * @returns A subscriber object
49
40
  */
50
- export declare const poll: <T extends {}>(t: Subscriber<T>) => T | undefined;
41
+ export declare const subscribe: <T extends {}>(t: Topic<T>) => Subscriber<T>;
51
42
  /**
52
- * Get the next value in the message queue
53
- *
54
- * Returns a promise that resolves when the message queue is not empty
43
+ * Wait for messages from the topic
55
44
  * @param t
56
45
  */
57
- export declare const dispatch: <T extends {}>(t: Subscriber<T>) => Promise<T | undefined>;
46
+ export declare const dispatch: <T extends {}>(s: Subscriber<T>) => Promise<T | undefined>;
package/topic.js CHANGED
@@ -1 +1 @@
1
- export let init=()=>{let t=[[null],[],(res)=>{t[1].push(res)}];return t};export let subscribe=(t)=>[t,t[0]];export let publish=(t,value)=>{let head=t[0]=t[0][0]=[null,value];for(let i=0,res=t[1];i<res.length;i++)res[i](head);t[1]=[]};export let flush=(t)=>{let head=t[0]=t[0][0]=[null,undefined];for(let i=0,res=t[1];i<res.length;i++)res[i](head);t[1]=[]};export let poll=(t)=>t[1][0]!==null?(t[1]=t[1][0])[1]:undefined;export let dispatch=async(t)=>t[1][0]!==null?(t[1]=t[1][0])[1]:(t[1]=await new Promise(t[0][2]))[1];
1
+ export let init=()=>{let t=[[null],(res)=>{t[2]=res},null,null];return t};export let publish=(t,m)=>{t[0]=t[0][0]=[null,m];t[2]?.();t[2]=null};export let flush=publish;export let subscribe=(t)=>[t,t[0]];export let dispatch=async(s)=>{if(s[1][0]===null)await(s[0][2]!==null?s[0][3]:s[0][3]=new Promise(s[0][1]));return(s[1]=s[1][0])[1]};
package/channel.d.ts DELETED
@@ -1,39 +0,0 @@
1
- /**
2
- * @module Channels
3
- */
4
- import type { Node as QueueNode } from './queue.js';
5
- import { type Lock } from './lock.js';
6
- /**
7
- * Describe a channel
8
- */
9
- export interface Channel<T = any> extends Lock<T> {
10
- /**
11
- * The head of the value queue
12
- */
13
- 3: QueueNode<T>;
14
- /**
15
- * The tail of the value queue
16
- */
17
- 4: QueueNode<T>;
18
- }
19
- /**
20
- * Create a channel
21
- */
22
- export declare const init: <T extends {}>() => Channel<T>;
23
- /**
24
- * Send a message to a channel
25
- * @param c - The channel to send to
26
- * @param t - The message to send
27
- */
28
- export declare const send: <T>(c: Channel<T>, t: T) => void;
29
- /**
30
- * Recieve a message from a channel, return null if the channel is closed
31
- * @param c
32
- */
33
- export declare const recieve: <T>(c: Channel<T>) => Promise<T | undefined>;
34
- /**
35
- * Recieve a message from a channel, return undefined if no message is currently in queue
36
- * @param c
37
- */
38
- export declare const poll: <T>(c: Channel<T>) => T | undefined;
39
- export { flush } from './lock.js';
package/channel.js DELETED
@@ -1 +0,0 @@
1
- import{release as lockRelease,released as lockReleased}from"./lock.js";export let init=()=>{let resolveQu=[null];let qu=[null];let chan=[resolveQu,resolveQu,(res)=>{chan[0]=chan[0][0]=[null,res]},qu,qu];return chan};export let send=(c,t)=>{if(lockReleased(c))c[3]=c[3][0]=[null,t];else lockRelease(c,t)};export let recieve=(c)=>c[4][0]!==null?Promise.resolve((c[4]=c[4][0])[1]):new Promise(c[2]);export let poll=(c)=>c[4][0]!==null?(c[4]=c[4][0])[1]:undefined;export{flush}from"./lock.js";