ciorent 0.0.5 → 0.0.7

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
@@ -77,7 +77,7 @@ console.log('Starting...');
77
77
  ```
78
78
 
79
79
  ## Latch
80
- Latch is a synchronization tool that works like a gate, pausing tasks until the latch is opened.
80
+ A latch is a synchronization tool that allows one or more threads to wait until a specific condition is met.
81
81
 
82
82
  ```ts
83
83
  import * as latch from 'ciorent/latch';
@@ -151,3 +151,30 @@ const main = async () => {
151
151
  // Run fetch after 500ms
152
152
  await main();
153
153
  ```
154
+
155
+ ## Semaphore
156
+ A semaphore is a synchronization tool to control access to shared resources.
157
+
158
+ It's essentially a counter that regulates how many threads or processes can access a particular resource or section of code.
159
+
160
+ ```ts
161
+ import * as semaphore from 'ciorent/semaphore';
162
+ import * as cio from 'ciorent';
163
+
164
+ // Only allow 2 of these tasks to run concurrently
165
+ const task = semaphore.task(
166
+ semaphore.init(2),
167
+ async (task: number) => {
168
+ for (let i = 1; i <= 5; i++) {
169
+ await cio.pause;
170
+ console.log('Task', task, 'iteration', i);
171
+ }
172
+
173
+ await cio.sleep(500);
174
+ console.log('Task', task, 'end');
175
+ }
176
+ );
177
+
178
+ // Try to run 5 tasks concurrently
179
+ for (let i = 1; i <= 5; i++) task(i);
180
+ ```
package/channel.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * @module
3
3
  * Channels
4
4
  */
5
- type QueueNode<T> = [T, QueueNode<T> | null];
5
+ import type { QueueNode } from './queue';
6
6
  /**
7
7
  * Describe a channel
8
8
  */
@@ -58,4 +58,3 @@ export declare const close: <T>(c: Channel<T>) => void;
58
58
  * @param c
59
59
  */
60
60
  export declare const active: (c: Channel<any>) => boolean;
61
- export {};
package/index.d.ts CHANGED
@@ -15,3 +15,11 @@ export declare const pause: Promise<void>;
15
15
  * @param ms - Sleep duration in milliseconds
16
16
  */
17
17
  export declare const sleep: (ms: number) => Promise<void>;
18
+ /**
19
+ * Spawn n tasks
20
+ * @param n
21
+ * @param task - The function to run
22
+ * @param args - The arguments to pass in the function
23
+ * @returns
24
+ */
25
+ export declare const spawn: <Args extends any[], R extends Promise<any>>(n: number, task: (...args: Args) => R, ...args: Args) => R[];
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)}));
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 spawn=(n,task,...args)=>{let a=new Array(n);while(n--!==0)a[n]=task(...args);return a};
package/package.json CHANGED
@@ -1,21 +1,25 @@
1
1
  {
2
2
  "name": "ciorent",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "A low-overhead, lightweight concurrency library",
5
5
  "homepage": "https://ciorent.netlify.app",
6
6
  "repository": {
7
7
  "type": "github",
8
8
  "url": "https://github.com/re-utils/ciorent"
9
9
  },
10
- "keywords": [],
10
+ "keywords": [
11
+ "low-overhead",
12
+ "lightweight",
13
+ "concurrency"
14
+ ],
11
15
  "license": "MIT",
12
16
  "type": "module",
13
17
  "main": "./index.js",
14
18
  "types": "./index.d.ts",
15
19
  "scripts": {
16
20
  "task": "bun scripts/task.ts",
17
- "build:test": "bun task build && bun test",
18
- "build:publish": "bun task build && bun task report-size && bun task publish",
21
+ "build:test": "bun docs && bun task build && bun test",
22
+ "build:publish": "bun build:test && bun task report-size && bun task publish",
19
23
  "lint": "eslint ./src",
20
24
  "lint:fix": "eslint ./src --fix",
21
25
  "docs": "typedoc ./src/** --entryPointStrategy Expand --plugin typedoc-material-theme --skipErrorChecking"
package/queue/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /**
2
+ * @private
2
3
  * @module
3
4
  * Queue utilities
4
5
  */
@@ -23,6 +24,13 @@ export interface FixedQueue<T extends {}> {
23
24
  */
24
25
  3: number;
25
26
  }
27
+ /**
28
+ * Describe a queue node (singly linked list node)
29
+ */
30
+ export type QueueNode<T> = [
31
+ value: T,
32
+ next: QueueNode<T> | null
33
+ ];
26
34
  /**
27
35
  * Create a fixed queue.
28
36
  * @param n - The queue size
package/semaphore.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @module
3
+ * Semaphores
4
+ */
5
+ import type { QueueNode } from './queue';
6
+ /**
7
+ * Describe a semaphore
8
+ */
9
+ export interface Semaphore {
10
+ /**
11
+ * Current remaining process allowed
12
+ */
13
+ 0: number;
14
+ /**
15
+ * The head of the Promise resolve queue
16
+ */
17
+ 1: QueueNode<() => void>;
18
+ /**
19
+ * The tail of the Promise resolve queue
20
+ */
21
+ 2: QueueNode<() => void>;
22
+ }
23
+ /**
24
+ * Create a semaphore that allows n accesses
25
+ */
26
+ export declare const init: (n: number) => Semaphore;
27
+ /**
28
+ * Wait until the semaphore allows access
29
+ */
30
+ export declare const pause: (s: Semaphore) => Promise<void>;
31
+ /**
32
+ * Signal to the semaphore to release access
33
+ */
34
+ export declare const signal: (s: Semaphore) => void;
35
+ /**
36
+ * Create a task that acquire a semaphore and release the access later
37
+ */
38
+ export declare const task: <F extends (...args: any[]) => Promise<any>>(s: Semaphore, f: F) => F;
package/semaphore.js ADDED
@@ -0,0 +1 @@
1
+ import{pause as resolvedPromise}from".";export let init=(n)=>{let root=[null,null];return[n,root,root]};export let pause=(s)=>{if(s[0]===0){let r;let p=new Promise((res)=>{r=res});s[1]=s[1][1]=[r,null];return p}s[0]--;return resolvedPromise};export let signal=(s)=>{if(s[1]===s[2])s[0]++;else(s[2]=s[2][1])[0]()};export let task=(s,f)=>async(...a)=>{try{await pause(s);return f(...a)}finally{signal(s)}};