diff --git a/JavaScript/4-bad.js b/JavaScript/4-bad.js index a706074..59dd975 100644 --- a/JavaScript/4-bad.js +++ b/JavaScript/4-bad.js @@ -1,32 +1,79 @@ 'use strict'; -// TODO: Refactor to respect SoC principle and -// optimize JavaScript for V8 - -const poolify = (factory, options, size, max) => { - const instances = []; // Preallocate array - for (let i = 0; i < size; i++) { // Use Array methods instead of loop - const instance = factory(...options); // Avoid array destructuring - instances.push(instance); - } - - return (instance) => { // Respect SoC and SOLID/SRP - if (instance) { // Avoid if-statement - if (instances.length < max) { - instances.push(instance); +const poolify = (factory, size, max) => { + const instances = new Array(size).fill(null).map(factory); + const queue = []; + let available = instances.length; + + const processQueue = () => { + while (queue.length > 0 && available > 0){ + const { resolve } = queue.shift(); + resolve(instances.pop()); + available--; + } + }; + + const acquire = () => { + return new Promise((resolve) => { + if(available > 0){ + const instance = instances.pop(); + available--; + resolve(instance); } + else { + queue.push({ resolve }); + } + }); + }; + + const release = (instance) => { + if (instances.length < max) { + instances.push(instance); + available++; + processQueue(); } - instance = instances.pop(); // Do not reassign incoming parameters - if (!instance) instance = factory(...options); - return instance; }; + + return { acquire, release }; }; // Usage const createBuffer = (size) => new Uint8Array(size); -const pool = poolify(createBuffer, [4096], 10, 15); -const instance = pool(); -console.log({ instance }); -pool(instance); +const bufferSize = 4096; +const createFileBuffer = () => createBuffer(bufferSize); + +const size = 2; +const max = 4; +const pool = poolify(createFileBuffer, size, max); + +(async () => { + const instance1 = await pool.acquire(); + console.log('Acquired instance 1', instance1); + setTimeout(() => { + console.log('Releasing instance 1'); + pool.release(instance1); + }, 1000); + + const instance2 = await pool.acquire(); + console.log('Acquired instance 2', instance2); + setTimeout(() => { + console.log('Releasing instance 2'); + pool.release(instance2); + }, 1500); + + const instance3 = await pool.acquire(); + console.log('Acquired instance 3', instance3); + setTimeout(() => { + console.log('Releasing instance 3'); + pool.release(instance3); + }, 1000); + + const instance4 = await pool.acquire(); + console.log('Acquired instance 4', instance4); + setTimeout(() => { + console.log('Releasing instance 4'); + pool.release(instance4); + }, 1500); +})(); \ No newline at end of file diff --git a/JavaScript/4-improved.js b/JavaScript/4-improved.js index 20a016e..0271975 100644 --- a/JavaScript/4-improved.js +++ b/JavaScript/4-improved.js @@ -1,17 +1,42 @@ 'use strict'; -const poolify = (factory, { size, max }) => { - const instances = new Array(size).fill(null).map(factory); - - const acquire = () => instances.pop() || factory(); +class ObjectPool { + constructor (factory, { size, max }) { + this.factory = factory; + this.max = max; + this.instances = new Array(size).fill(null).map(() => this.factory()); + this.queue = []; + this.available = this.instances.length; + }; - const release = (instance) => { - if (instances.length < max) { - instances.push(instance); + _processQueue() { + while (this.queue.length > 0 && this.available > 0){ + const { resolve } = this.queue.shift(); + resolve(this.instances.pop()); + this.available--; } }; - return { acquire, release }; + acquire () { + return new Promise((resolve) => { + if(this.available > 0){ + const instance = this.instances.pop(); + this.available--; + resolve(instance); + } + else{ + this.queue.push({ resolve }); + } + }); + }; + + release (instance) { + if (this.instances.length < this.max) { + this.instances.push(instance); + this.available++; + this._processQueue(); + } + }; }; // Usage @@ -21,7 +46,34 @@ const createBuffer = (size) => new Uint8Array(size); const FILE_BUFFER_SIZE = 4096; const createFileBuffer = () => createBuffer(FILE_BUFFER_SIZE); -const pool = poolify(createFileBuffer, { size: 10, max: 15 }); -const instance = pool.acquire(); -console.log({ instance }); -pool.release(instance); +const pool = new ObjectPool(createFileBuffer, { size: 2, max: 4 }); + +(async () => { + const instance1 = await pool.acquire(); + console.log('Acquired instance 1', instance1); + setTimeout(() => { + console.log('Releasing instance 1'); + pool.release(instance1); + }, 1000); + + const instance2 = await pool.acquire(); + console.log('Acquired instance 2', instance2); + setTimeout(() => { + console.log('Releasing instance 2'); + pool.release(instance2); + }, 1500); + + const instance3 = await pool.acquire(); + console.log('Acquired instance 3', instance3); + setTimeout(() => { + console.log('Releasing instance 3'); + pool.release(instance3); + }, 1000); + + const instance4 = await pool.acquire(); + console.log('Acquired instance 4', instance4); + setTimeout(() => { + console.log('Releasing instance 4'); + pool.release(instance4); + }, 1500); +})(); \ No newline at end of file