Skip to content

Commit 8ed0442

Browse files
committed
feat(semaphore): throw RangeError for invalid size
1 parent 8006363 commit 8ed0442

File tree

2 files changed

+81
-5
lines changed

2 files changed

+81
-5
lines changed

semaphore.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@ export class Semaphore {
2323
* Creates a new semaphore with the specified limit.
2424
*
2525
* @param size The maximum number of times the semaphore can be acquired before blocking.
26-
* @throws Error if the size is less than 1.
26+
* @throws {RangeError} if the size is not a positive safe integer.
2727
*/
2828
constructor(size: number) {
29-
if (size < 0) {
30-
throw new Error("The size must be greater than 0");
29+
if (size <= 0 || !Number.isSafeInteger(size)) {
30+
throw new RangeError(
31+
`size must be a positive safe integer, got ${size}`,
32+
);
3133
}
3234
this.#rest = size + 1;
3335
}

semaphore_test.ts

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { assertEquals } from "@std/assert";
1+
import { assertEquals, assertThrows } from "@std/assert";
22
import { Semaphore } from "./semaphore.ts";
33

44
Deno.test("Semaphore", async (t) => {
55
await t.step(
6-
"regulates the number of workers concurrently running",
6+
"regulates the number of workers concurrently running (n=5)",
77
async () => {
88
let nworkers = 0;
99
const results: number[] = [];
@@ -32,4 +32,78 @@ Deno.test("Semaphore", async (t) => {
3232
]);
3333
},
3434
);
35+
36+
await t.step(
37+
"regulates the number of workers concurrently running (n=1)",
38+
async () => {
39+
let nworkers = 0;
40+
const results: number[] = [];
41+
const sem = new Semaphore(1);
42+
const worker = () => {
43+
return sem.lock(async () => {
44+
nworkers++;
45+
results.push(nworkers);
46+
await new Promise((resolve) => setTimeout(resolve, 10));
47+
nworkers--;
48+
});
49+
};
50+
await Promise.all([...Array(10)].map(() => worker()));
51+
assertEquals(nworkers, 0);
52+
assertEquals(results, [
53+
1,
54+
1,
55+
1,
56+
1,
57+
1,
58+
1,
59+
1,
60+
1,
61+
1,
62+
1,
63+
]);
64+
},
65+
);
66+
67+
await t.step(
68+
"regulates the number of workers concurrently running (n=10)",
69+
async () => {
70+
let nworkers = 0;
71+
const results: number[] = [];
72+
const sem = new Semaphore(10);
73+
const worker = () => {
74+
return sem.lock(async () => {
75+
nworkers++;
76+
results.push(nworkers);
77+
await new Promise((resolve) => setTimeout(resolve, 10));
78+
nworkers--;
79+
});
80+
};
81+
await Promise.all([...Array(10)].map(() => worker()));
82+
assertEquals(nworkers, 0);
83+
assertEquals(results, [
84+
1,
85+
2,
86+
3,
87+
4,
88+
5,
89+
6,
90+
7,
91+
8,
92+
9,
93+
10,
94+
]);
95+
},
96+
);
97+
98+
await t.step(
99+
"throws RangeError if size is not a positive safe integer",
100+
() => {
101+
assertThrows(() => new Semaphore(NaN), RangeError);
102+
assertThrows(() => new Semaphore(Infinity), RangeError);
103+
assertThrows(() => new Semaphore(-Infinity), RangeError);
104+
assertThrows(() => new Semaphore(-1), RangeError);
105+
assertThrows(() => new Semaphore(1.1), RangeError);
106+
assertThrows(() => new Semaphore(0), RangeError);
107+
},
108+
);
35109
});

0 commit comments

Comments
 (0)