8000 Async Pool with await/await and timeout · HowProgrammingWorks/Pool@e7723ea · GitHub
[go: up one dir, main page]

Skip to content

Commit e7723ea

Browse files
committed
Async Pool with await/await and timeout
1 parent dcbed2a commit e7723ea

File tree

2 files changed

+192
-0
lines changed

2 files changed

+192
-0
lines changed

JavaScript/a-await.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
'use strict';
2+
3+
class Pool {
4+
constructor() {
5+
this.items = [];
6+
this.free = [];
7+
this.queue = [];
8+
this.current = 0;
9+
this.size = 0;
10+
this.available = 0;
11+
}
12+
13+
async next() {
14+
if (this.size === 0) return null;
15+
if (this.available === 0) {
16+
return new Promise((resolve) => {
17+
this.queue.push(resolve);
18+
});
19+
}
20+
let item = null;
21+
let free = false;
22+
do {
23+
item = this.items[this.current];
24+
free = this.free[this.current];
25+
this.current++;
26+
} while (!item || !free);
27+
if (this.current === this.size) this.current = 0;
28+
return item;
29+
}
30+
31+
add(item) {
32+
if (this.items.includes(item)) throw new Error('Pool: add duplicates');
33+
this.size++;
34+
this.available++;
35+
this.items.push(item);
36+
this.free.push(true);
37+
}
38+
39+
async capture() {
40+
const item = await this.next();
41+
if (!item) return null;
42+
const index = this.items.indexOf(item);
43+
this.free[index] = false;
44+
this.available--;
45+
return item;
46+
}
47+
48+
release(item) {
49+
const index = this.items.indexOf(item);
50+
if (index < 0) throw new Error('Pool: release unexpected item');
51+
if (this.free[index]) throw new Error('Pool: release not captured');
52+
this.free[index] = true;
53+
this.available++;
54+
if (this.queue.length > 0) {
55+
const resolve = this.queue.shift();
56+
if (resolve) setTimeout(resolve, 0, item);
57+
}
58+
}
59+
}
60+
61+
// Usage
62+
63+
(async () => {
64+
const pool = new Pool();
65+
pool.add({ item: 1 });
66+
pool.add({ item: 2 });
67+
const last = { item: 3 };
68+
pool.add(last);
69+
70+
const x1 = await pool.capture();
71+
console.log({ x1 });
72+
const x2 = await pool.capture();
73+
console. 57AE log({ x2 });
74+
const x3 = await pool.capture();
75+
console.log({ x3 });
76+
77+
pool.capture().then((x4) => {
78+
console.log({ x4 });
79+
});
80+
pool.capture().then((x5) => {
81+
console.log({ x5 });
82+
});
83+
pool.capture().then((x6) => {
84+
console.log({ x6 });
85+
});
86+
87+
pool.release(x2);
88+
pool.release(x1);
89+
pool.release(x3);
90+
})();

JavaScript/b-timeout.js

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
'use strict';
2+
3+
class Pool {
4+
constructor(options = {}) {
5+
this.items = [];
6+
this.free = [];
7+
this.queue = [];
8+
this.timeout = options.timeout || 0;
9+
this.current = 0;
10+
this.size = 0;
11+
this.available = 0;
12+
}
13+
14+
async next() {
15+
if (this.size === 0) return null;
16+
if (this.available === 0) {
17+
return new Promise((resolve, reject) => {
18+
const waiting = { resolve, timer: null };
19+
waiting.timer = setTimeout(() => {
20+
waiting.resolve = null;
21+
this.queue.shift();
22+
reject(new Error('Pool next item timeout'));
23+
}, this.timeout);
24+
this.queue.push(waiting);
25+
});
26+
}
27+
let item = null;
28+
let free = false;
29+
do {
30+
item = this.items[this.current];
31+
free = this.free[this.current];
32+
this.current++;
33+
} while (!item || !free);
34+
if (this.current === this.size) this.current = 0;
35+
return item;
36+
}
37+
38+
add(item) {
39+
if (this.items.includes(item)) throw new Error('Pool: add duplicates');
40+
this.size++;
41+
this.available++;
42+
this.items.push(item);
43+
this.free.push(true);
44+
}
45+
46+
async capture() {
47+
const item = await this.next();
48+
if (!item) return null;
49+
const index = this.items.indexOf(item);
50+
this.free[index] = false;
51+
this.available--;
52+
return item;
53+
}
54+
55+
release(item) {
56+
const index = this.items.indexOf(item);
57+
if (index < 0) throw new Error('Pool: release unexpected item');
58+
if (this.free[index]) throw new Error('Pool: release not captured');
59+
this.free[index] = true;
60+
this.available++;
61+
if (this.queue.length > 0) {
62+
const { resolve, timer } = this.queue.shift();
63+
clearTimeout(timer);
64+
if (resolve) setTimeout(resolve, 0, item);
65+
}
66+
}
67+
}
68+
69+
// Usage
70+
71+
(async () => {
72+
const pool = new Pool({ timeout: 5000 });
73+
pool.add({ item: 1 });
74+
pool.add({ item: 2 });
75+
const last = { item: 3 };
76+
pool.add(last);
77+
78+
const x1 = await pool.capture();
79+
console.log({ x1 });
80+
const x2 = await pool.capture();
81+
console.log({ x2 });
82+
const x3 = await pool.capture();
83+
console.log({ x3 });
84+
85+
pool.capture().then((x4) => {
86+
console.log({ x4 });
87+
});
88+
pool.capture().then((x5) => {
89+
console.log({ x5 });
90+
});
91+
pool.capture().then((x6) => {
92+
console.log({ x6 });
93+
}).catch((err) => {
94+
console.error({ err });
95+
});
96+
97+
pool.release(x2);
98+
pool.release(x1);
99+
setTimeout(() => {
100+
pool.release(x3);
101+
}, 3000);
102+
})();

0 commit comments

Comments
 (0)
0