Change the loadedChunks property, on ChunkedStream instances, from an Array to a Set

In the old code the use of an Array meant that we had to *manually* track the `numChunksLoaded` property, given that simply using the Array `length` wouldn't have worked since there's no guarantee that the data is loaded in order when e.g. range requests are in use.

Tracking closely related state *separately* in this manner never seem like a good idea, and we can now instead utilize a Set to avoid that.
This commit is contained in:
Jonas Jenwald 2020-06-05 14:10:51 +02:00
parent 7aa1b2d418
commit b7272a34eb

View File

@ -29,8 +29,7 @@ class ChunkedStream {
this.pos = 0; this.pos = 0;
this.end = length; this.end = length;
this.chunkSize = chunkSize; this.chunkSize = chunkSize;
this.loadedChunks = []; this._loadedChunks = new Set();
this.numChunksLoaded = 0;
this.numChunks = Math.ceil(length / chunkSize); this.numChunks = Math.ceil(length / chunkSize);
this.manager = manager; this.manager = manager;
this.progressiveDataLength = 0; this.progressiveDataLength = 0;
@ -42,7 +41,7 @@ class ChunkedStream {
getMissingChunks() { getMissingChunks() {
const chunks = []; const chunks = [];
for (let chunk = 0, n = this.numChunks; chunk < n; ++chunk) { for (let chunk = 0, n = this.numChunks; chunk < n; ++chunk) {
if (!this.loadedChunks[chunk]) { if (!this._loadedChunks.has(chunk)) {
chunks.push(chunk); chunks.push(chunk);
} }
} }
@ -53,6 +52,10 @@ class ChunkedStream {
return [this]; return [this];
} }
get numChunksLoaded() {
return this._loadedChunks.size;
}
allChunksLoaded() { allChunksLoaded() {
return this.numChunksLoaded === this.numChunks; return this.numChunksLoaded === this.numChunks;
} }
@ -75,10 +78,9 @@ class ChunkedStream {
const endChunk = Math.floor((end - 1) / chunkSize) + 1; const endChunk = Math.floor((end - 1) / chunkSize) + 1;
for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) { for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
if (!this.loadedChunks[curChunk]) { // Since a value can only occur *once* in a `Set`, there's no need to
this.loadedChunks[curChunk] = true; // manually check `Set.prototype.has()` before adding the value here.
++this.numChunksLoaded; this._loadedChunks.add(curChunk);
}
} }
} }
@ -95,10 +97,9 @@ class ChunkedStream {
: Math.floor(position / this.chunkSize); : Math.floor(position / this.chunkSize);
for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) { for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
if (!this.loadedChunks[curChunk]) { // Since a value can only occur *once* in a `Set`, there's no need to
this.loadedChunks[curChunk] = true; // manually check `Set.prototype.has()` before adding the value here.
++this.numChunksLoaded; this._loadedChunks.add(curChunk);
}
} }
} }
@ -112,7 +113,7 @@ class ChunkedStream {
return; return;
} }
if (!this.loadedChunks[chunk]) { if (!this._loadedChunks.has(chunk)) {
throw new MissingDataException(pos, pos + 1); throw new MissingDataException(pos, pos + 1);
} }
this.lastSuccessfulEnsureByteChunk = chunk; this.lastSuccessfulEnsureByteChunk = chunk;
@ -130,7 +131,7 @@ class ChunkedStream {
const beginChunk = Math.floor(begin / chunkSize); const beginChunk = Math.floor(begin / chunkSize);
const endChunk = Math.floor((end - 1) / chunkSize) + 1; const endChunk = Math.floor((end - 1) / chunkSize) + 1;
for (let chunk = beginChunk; chunk < endChunk; ++chunk) { for (let chunk = beginChunk; chunk < endChunk; ++chunk) {
if (!this.loadedChunks[chunk]) { if (!this._loadedChunks.has(chunk)) {
throw new MissingDataException(begin, end); throw new MissingDataException(begin, end);
} }
} }
@ -140,7 +141,7 @@ class ChunkedStream {
const numChunks = this.numChunks; const numChunks = this.numChunks;
for (let i = 0; i < numChunks; ++i) { for (let i = 0; i < numChunks; ++i) {
const chunk = (beginChunk + i) % numChunks; // Wrap around to beginning. const chunk = (beginChunk + i) % numChunks; // Wrap around to beginning.
if (!this.loadedChunks[chunk]) { if (!this._loadedChunks.has(chunk)) {
return chunk; return chunk;
} }
} }
@ -148,7 +149,7 @@ class ChunkedStream {
} }
hasChunk(chunk) { hasChunk(chunk) {
return !!this.loadedChunks[chunk]; return this._loadedChunks.has(chunk);
} }
get length() { get length() {
@ -286,7 +287,7 @@ class ChunkedStream {
const endChunk = Math.floor((this.end - 1) / chunkSize) + 1; const endChunk = Math.floor((this.end - 1) / chunkSize) + 1;
const missingChunks = []; const missingChunks = [];
for (let chunk = beginChunk; chunk < endChunk; ++chunk) { for (let chunk = beginChunk; chunk < endChunk; ++chunk) {
if (!this.loadedChunks[chunk]) { if (!this._loadedChunks.has(chunk)) {
missingChunks.push(chunk); missingChunks.push(chunk);
} }
} }