microsoft-cognitiveservices-speech-sdk
Version:
Microsoft Cognitive Services Speech SDK for JavaScript
172 lines (170 loc) • 7.21 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Queue = void 0;
const Error_js_1 = require("./Error.js");
const List_js_1 = require("./List.js");
const Promise_js_1 = require("./Promise.js");
var SubscriberType;
(function (SubscriberType) {
SubscriberType[SubscriberType["Dequeue"] = 0] = "Dequeue";
SubscriberType[SubscriberType["Peek"] = 1] = "Peek";
})(SubscriberType || (SubscriberType = {}));
class Queue {
constructor(list) {
this.privPromiseStore = new List_js_1.List();
this.privIsDrainInProgress = false;
this.privIsDisposing = false;
this.privDisposeReason = null;
this.privList = list ? list : new List_js_1.List();
this.privDetachables = [];
this.privSubscribers = new List_js_1.List();
this.privDetachables.push(this.privList.onAdded(() => this.drain()));
}
enqueue(item) {
this.throwIfDispose();
this.enqueueFromPromise(new Promise((resolve) => resolve(item)));
}
enqueueFromPromise(promise) {
this.throwIfDispose();
promise.then((val) => {
this.privList.add(val);
// eslint-disable-next-line @typescript-eslint/no-empty-function
}, () => { });
}
dequeue() {
this.throwIfDispose();
const deferredSubscriber = new Promise_js_1.Deferred();
if (this.privSubscribers) {
this.privSubscribers.add({ deferral: deferredSubscriber, type: SubscriberType.Dequeue });
this.drain();
}
return deferredSubscriber.promise;
}
peek() {
this.throwIfDispose();
const deferredSubscriber = new Promise_js_1.Deferred();
const subs = this.privSubscribers;
if (subs) {
this.privSubscribers.add({ deferral: deferredSubscriber, type: SubscriberType.Peek });
this.drain();
}
return deferredSubscriber.promise;
}
length() {
this.throwIfDispose();
return this.privList.length();
}
isDisposed() {
return this.privSubscribers == null;
}
async drainAndDispose(pendingItemProcessor, reason) {
if (!this.isDisposed() && !this.privIsDisposing) {
this.privDisposeReason = reason;
this.privIsDisposing = true;
const subs = this.privSubscribers;
if (subs) {
while (subs.length() > 0) {
const subscriber = subs.removeFirst();
// TODO: this needs work (Resolve(null) instead?).
subscriber.deferral.resolve(undefined);
// subscriber.deferral.reject("Disposed");
}
// note: this block assumes cooperative multitasking, i.e.,
// between the if-statement and the assignment there are no
// thread switches.
// Reason is that between the initial const = this.; and this
// point there is the derral.resolve() operation that might have
// caused recursive calls to the Queue, especially, calling
// Dispose() on the queue alredy (which would reset the var
// here to null!).
// That should generally hold true for javascript...
if (this.privSubscribers === subs) {
this.privSubscribers = subs;
}
}
for (const detachable of this.privDetachables) {
await detachable.detach();
}
if (this.privPromiseStore.length() > 0 && pendingItemProcessor) {
const promiseArray = [];
this.privPromiseStore.toArray().forEach((wrapper) => {
promiseArray.push(wrapper);
});
return Promise.all(promiseArray).finally(() => {
this.privSubscribers = null;
this.privList.forEach((item) => {
pendingItemProcessor(item);
});
this.privList = null;
return;
}).then();
}
else {
this.privSubscribers = null;
this.privList = null;
}
}
}
async dispose(reason) {
await this.drainAndDispose(null, reason);
}
drain() {
if (!this.privIsDrainInProgress && !this.privIsDisposing) {
this.privIsDrainInProgress = true;
const subs = this.privSubscribers;
const lists = this.privList;
if (subs && lists) {
while (lists.length() > 0 && subs.length() > 0 && !this.privIsDisposing) {
const subscriber = subs.removeFirst();
if (subscriber.type === SubscriberType.Peek) {
subscriber.deferral.resolve(lists.first());
}
else {
const dequeuedItem = lists.removeFirst();
subscriber.deferral.resolve(dequeuedItem);
}
}
// note: this block assumes cooperative multitasking, i.e.,
// between the if-statement and the assignment there are no
// thread switches.
// Reason is that between the initial const = this.; and this
// point there is the derral.resolve() operation that might have
// caused recursive calls to the Queue, especially, calling
// Dispose() on the queue alredy (which would reset the var
// here to null!).
// That should generally hold true for javascript...
if (this.privSubscribers === subs) {
this.privSubscribers = subs;
}
// note: this block assumes cooperative multitasking, i.e.,
// between the if-statement and the assignment there are no
// thread switches.
// Reason is that between the initial const = this.; and this
// point there is the derral.resolve() operation that might have
// caused recursive calls to the Queue, especially, calling
// Dispose() on the queue alredy (which would reset the var
// here to null!).
// That should generally hold true for javascript...
if (this.privList === lists) {
this.privList = lists;
}
}
this.privIsDrainInProgress = false;
}
}
throwIfDispose() {
if (this.isDisposed()) {
if (this.privDisposeReason) {
throw new Error_js_1.InvalidOperationError(this.privDisposeReason);
}
throw new Error_js_1.ObjectDisposedError("Queue");
}
else if (this.privIsDisposing) {
throw new Error_js_1.InvalidOperationError("Queue disposing");
}
}
}
exports.Queue = Queue;
//# sourceMappingURL=Queue.js.map