ciorent 0.0.12 → 0.0.13
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 +80 -51
- package/dropping-queue.d.ts +1 -1
- package/dropping-queue.js +1 -1
- package/fixed-queue.d.ts +1 -2
- package/fixed-queue.js +1 -1
- package/package.json +1 -1
- package/semaphore.js +1 -1
- package/sliding-queue.d.ts +1 -1
- package/sliding-queue.js +1 -1
- package/topic.d.ts +61 -0
- package/topic.js +1 -0
package/README.md
CHANGED
@@ -1,48 +1,5 @@
|
|
1
|
-
A lightweight, low-overhead concurrency library
|
2
|
-
|
3
|
-
# Examples
|
4
|
-
## Channel
|
5
|
-
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.
|
6
|
-
|
7
|
-
```ts
|
8
|
-
import * as channel from 'ciorent/channel';
|
9
|
-
import * as cio from 'ciorent';
|
10
|
-
|
11
|
-
const c = channel.init<number>();
|
12
|
-
|
13
|
-
const run = async () => {
|
14
|
-
for (let i = 0; i < 10; i++) {
|
15
|
-
await cio.sleep(10);
|
16
|
-
channel.send(c, i);
|
17
|
-
console.log('Sent', i);
|
18
|
-
}
|
19
|
-
|
20
|
-
// Send the closed signal to the reciever
|
21
|
-
// Or else channel.recieve will block forever
|
22
|
-
channel.close(c);
|
23
|
-
};
|
24
|
-
|
25
|
-
const log = async () => {
|
26
|
-
while (true) {
|
27
|
-
// Non-blocking
|
28
|
-
const x = await channel.recieve(c);
|
29
|
-
|
30
|
-
// 'recieve' returns undefined if
|
31
|
-
// The channel has been closed
|
32
|
-
if (x == null) break;
|
33
|
-
|
34
|
-
console.log('Recieved', x);
|
35
|
-
};
|
36
|
-
}
|
37
|
-
|
38
|
-
run();
|
39
|
-
log();
|
40
|
-
|
41
|
-
// This runs first
|
42
|
-
console.log('Starting...');
|
43
|
-
```
|
44
|
-
|
45
|
-
## Semaphore
|
1
|
+
A lightweight, low-overhead concurrency library.
|
2
|
+
# Semaphore
|
46
3
|
Semaphore is a concurrency primitive used to control access to a common resource by multiple processes.
|
47
4
|
|
48
5
|
```ts
|
@@ -66,7 +23,7 @@ const task = semaphore.task(
|
|
66
23
|
cio.concurrent(6, task, 4);
|
67
24
|
```
|
68
25
|
|
69
|
-
|
26
|
+
# Latch
|
70
27
|
Latch is a synchronization primitive that allows one process to wait until another completes an operation before continuing execution.
|
71
28
|
|
72
29
|
```ts
|
@@ -109,8 +66,80 @@ await main();
|
|
109
66
|
await main();
|
110
67
|
```
|
111
68
|
|
112
|
-
|
113
|
-
|
69
|
+
# Channel
|
70
|
+
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.
|
71
|
+
|
72
|
+
```ts
|
73
|
+
import * as channel from 'ciorent/channel';
|
74
|
+
import * as cio from 'ciorent';
|
75
|
+
|
76
|
+
const c = channel.init<number>();
|
77
|
+
|
78
|
+
const run = async () => {
|
79
|
+
for (let i = 0; i < 10; i++) {
|
80
|
+
await cio.sleep(10);
|
81
|
+
channel.send(c, i);
|
82
|
+
console.log('Sent', i);
|
83
|
+
}
|
84
|
+
|
85
|
+
// Send the closed signal to the reciever
|
86
|
+
// Or else channel.recieve will block forever
|
87
|
+
channel.close(c);
|
88
|
+
};
|
89
|
+
|
90
|
+
const log = async () => {
|
91
|
+
while (true) {
|
92
|
+
// Non-blocking
|
93
|
+
const x = await channel.recieve(c);
|
94
|
+
|
95
|
+
// 'recieve' returns undefined if
|
96
|
+
// The channel has been closed
|
97
|
+
if (x == null) break;
|
98
|
+
|
99
|
+
console.log('Recieved', x);
|
100
|
+
};
|
101
|
+
}
|
102
|
+
|
103
|
+
run();
|
104
|
+
log();
|
105
|
+
|
106
|
+
// This runs first
|
107
|
+
console.log('Starting...');
|
108
|
+
```
|
109
|
+
|
110
|
+
# Pubsub
|
111
|
+
A simple publish-subscribe API
|
112
|
+
|
113
|
+
```ts
|
114
|
+
import * as topic from 'ciorent/topic';
|
115
|
+
import * as cio from 'ciorent';
|
116
|
+
|
117
|
+
const messages = topic.init<number>();
|
118
|
+
|
119
|
+
// A task that publish messages
|
120
|
+
const publisher = async () => {
|
121
|
+
for (let i = 0; i < 5; i++) {
|
122
|
+
await cio.sleep(50);
|
123
|
+
topic.pub(messages, i);
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
// Spawn 5 tasks that recieve messages
|
128
|
+
cio.concurrent(5, async (id: number) => {
|
129
|
+
const sub = topic.sub(messages);
|
130
|
+
|
131
|
+
while (true) {
|
132
|
+
const x = await topic.next(sub);
|
133
|
+
if (x == null) break;
|
134
|
+
console.log(`Task ${id}: ${x}`);
|
135
|
+
}
|
136
|
+
});
|
137
|
+
|
138
|
+
publisher();
|
139
|
+
```
|
140
|
+
|
141
|
+
# Utilities
|
142
|
+
## Pausing
|
114
143
|
Delay the execution of a function for other asynchronous tasks to run.
|
115
144
|
```ts
|
116
145
|
import * as cio from 'ciorent';
|
@@ -140,7 +169,7 @@ task1();
|
|
140
169
|
task2();
|
141
170
|
```
|
142
171
|
|
143
|
-
|
172
|
+
## Sleep
|
144
173
|
A cross-runtime sleep function.
|
145
174
|
```ts
|
146
175
|
import { sleep } from 'ciorent';
|
@@ -149,7 +178,7 @@ await sleep(500);
|
|
149
178
|
console.log('Hi');
|
150
179
|
```
|
151
180
|
|
152
|
-
|
181
|
+
## Basic concurrency
|
153
182
|
Control how many tasks can be executed concurrently.
|
154
183
|
```ts
|
155
184
|
import concurrent from 'ciorent/concurrent';
|
@@ -165,7 +194,7 @@ for (let id = 1; id <= 6; id++)
|
|
165
194
|
});
|
166
195
|
```
|
167
196
|
|
168
|
-
|
197
|
+
## Spawning tasks
|
169
198
|
Creating new tasks with controlled concurrency.
|
170
199
|
```ts
|
171
200
|
import * as cio from 'ciorent';
|
package/dropping-queue.d.ts
CHANGED
package/dropping-queue.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export{
|
1
|
+
export{init}from"./fixed-queue";export{pop}from"./sliding-queue";export let push=(q,item)=>{if(q[0][(q[2]+1)%q[1]]!=null)return false;q[0][q[2]=(q[2]+1)%q[1]]=item;return true};
|
package/fixed-queue.d.ts
CHANGED
package/fixed-queue.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export
|
1
|
+
export let init=(n)=>[new Array(n),n,-1,-1];
|
package/package.json
CHANGED
package/semaphore.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
import{pause as resolvedPromise}from".";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 task=(s,f)=>async(...a)=>{
|
1
|
+
import{pause as resolvedPromise}from".";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 task=(s,f)=>async(...a)=>{await pause(s);try{return await f(...a)}finally{signal(s)}};
|
package/sliding-queue.d.ts
CHANGED
package/sliding-queue.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export{
|
1
|
+
export{init}from"./fixed-queue";export let push=(q,item)=>{q[0][q[2]=(q[2]+1)%q[1]]=item};export let pop=(q)=>{let val=q[0][(q[3]+1)%q[1]];if(val!=null){q[0][q[3]=(q[3]+1)%q[1]]=null;return val}};
|
package/topic.d.ts
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
/**
|
2
|
+
* @module Pubsub
|
3
|
+
*/
|
4
|
+
import type { QueueNode } from './fixed-queue';
|
5
|
+
/**
|
6
|
+
* Describe a topic
|
7
|
+
*/
|
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?: T) => void)[];
|
17
|
+
/**
|
18
|
+
* The waiting subscribers
|
19
|
+
*/
|
20
|
+
2: Subscriber<T>[];
|
21
|
+
}
|
22
|
+
/**
|
23
|
+
* Create a topic
|
24
|
+
*/
|
25
|
+
export declare const init: <T extends {}>() => Topic<T>;
|
26
|
+
/**
|
27
|
+
* Describe a topic
|
28
|
+
*/
|
29
|
+
export interface Subscriber<T extends {}> {
|
30
|
+
0: Topic<T>;
|
31
|
+
1: QueueNode<T>;
|
32
|
+
}
|
33
|
+
/**
|
34
|
+
* Subscribe to a topic
|
35
|
+
* @param t
|
36
|
+
*/
|
37
|
+
export declare const sub: <T extends {}>(t: Topic<T>) => Subscriber<T>;
|
38
|
+
/**
|
39
|
+
* Subscribe to a topic
|
40
|
+
* @param t
|
41
|
+
*/
|
42
|
+
export declare const pub: <T extends {}>(t: Topic<T>, value: T) => void;
|
43
|
+
/**
|
44
|
+
* Resolve all waiting promises
|
45
|
+
* @param t
|
46
|
+
*/
|
47
|
+
export declare const close: <T extends {}>(t: Topic<T>) => void;
|
48
|
+
/**
|
49
|
+
* Get the next value in the message queue.
|
50
|
+
*
|
51
|
+
* Returns `undefined` if the message queue is empty
|
52
|
+
* @param t
|
53
|
+
*/
|
54
|
+
export declare const poll: <T extends {}>(t: Subscriber<T>) => T | undefined;
|
55
|
+
/**
|
56
|
+
* Get the next value in the message queue
|
57
|
+
*
|
58
|
+
* Returns a promise that resolves when the message queue is not empty
|
59
|
+
* @param t
|
60
|
+
*/
|
61
|
+
export declare const next: <T extends {}>(t: Subscriber<T>) => Promise<T | undefined>;
|
package/topic.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export let init=()=>[[null,null],[],[]];export let sub=(t)=>[t,t[0]];export let pub=(t,value)=>{let head=t[0]=t[0][1]=[value,null];for(let i=0,res=t[1],subs=t[2];i<res.length;i++){res[i](value);subs[i][1]=head}t[1]=[];t[2]=[]};export let close=(t)=>{for(let i=0,res=t[1],subs=t[2],head=t[0];i<res.length;i++){res[i]();subs[i][1]=head}t[1]=[];t[2]=[]};export let poll=(t)=>t[1][1]!==null?(t[1]=t[1][1])[0]:undefined;export let next=(t)=>{if(t[1][1]!==null)return Promise.resolve((t[1]=t[1][1])[0]);let topic=t[0];topic[2].push(t);return new Promise((res)=>{topic[1].push(res)})};
|