{"version":3,"sources":["src/common/Queue.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAY,OAAO,EAAiB,MAAM,WAAW,CAAC;AAE7D,MAAM,WAAW,MAAM,CAAC,KAAK,CAAE,SAAQ,WAAW;IAC9C,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IAC3B,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAClD,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1B,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IACvB,MAAM,IAAI,MAAM,CAAC;CACpB;AAOD,qBAAa,KAAK,CAAC,KAAK,CAAE,YAAW,MAAM,CAAC,KAAK,CAAC;IAC9C,OAAO,CAAC,gBAAgB,CAAoD;IAC5E,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,eAAe,CAA4D;IACnF,OAAO,CAAC,qBAAqB,CAAkB;IAC/C,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,iBAAiB,CAAgB;gBAEtB,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC;IAO9B,OAAO,wBAGb;IAEM,kBAAkB,oCAiBxB;IAEM,OAAO,uBAUb;IAEM,IAAI,uBAWV;IAEM,MAAM,eAGZ;IAEM,UAAU,gBAEhB;IAEM,eAAe,mGAkDrB;IAEM,OAAO,4BAEb;IAED,OAAO,CAAC,KAAK,CA8CZ;IAED,OAAO,CAAC,cAAc,CAUrB;CACJ","file":"Queue.d.ts","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved.\n// Licensed under the MIT license.\n\nimport { InvalidOperationError, ObjectDisposedError } from \"./Error\";\nimport { IDetachable } from \"./IDetachable\";\nimport { IDisposable } from \"./IDisposable\";\nimport { List } from \"./List\";\nimport { Deferred, Promise, PromiseHelper } from \"./Promise\";\n\nexport interface IQueue<TItem> extends IDisposable {\n    enqueue(item: TItem): void;\n    enqueueFromPromise(promise: Promise<TItem>): void;\n    dequeue(): Promise<TItem>;\n    peek(): Promise<TItem>;\n    length(): number;\n}\n\nenum SubscriberType {\n    Dequeue,\n    Peek,\n}\n\nexport class Queue<TItem> implements IQueue<TItem> {\n    private privPromiseStore: List<Promise<TItem>> = new List<Promise<TItem>>();\n    private privList: List<TItem>;\n    private privDetachables: IDetachable[];\n    private privSubscribers: List<{ type: SubscriberType, deferral: Deferred<TItem> }>;\n    private privIsDrainInProgress: boolean = false;\n    private privIsDisposing: boolean = false;\n    private privDisposeReason: string = null;\n\n    public constructor(list?: List<TItem>) {\n        this.privList = list ? list : new List<TItem>();\n        this.privDetachables = [];\n        this.privSubscribers = new List<{ type: SubscriberType, deferral: Deferred<TItem> }>();\n        this.privDetachables.push(this.privList.onAdded(this.drain));\n    }\n\n    public enqueue = (item: TItem): void => {\n        this.throwIfDispose();\n        this.enqueueFromPromise(PromiseHelper.fromResult(item));\n    }\n\n    public enqueueFromPromise = (promise: Promise<TItem>): void => {\n        this.throwIfDispose();\n        this.privPromiseStore.add(promise);\n        promise.finally(() => {\n            while (this.privPromiseStore.length() > 0) {\n                if (!this.privPromiseStore.first().result().isCompleted) {\n                    break;\n                } else {\n                    const p = this.privPromiseStore.removeFirst();\n                    if (!p.result().isError) {\n                        this.privList.add(p.result().result);\n                    } else {\n                        // TODO: Log as warning.\n                    }\n                }\n            }\n        });\n    }\n\n    public dequeue = (): Promise<TItem> => {\n        this.throwIfDispose();\n        const deferredSubscriber = new Deferred<TItem>();\n\n        if (this.privSubscribers) {\n            this.privSubscribers.add({ deferral: deferredSubscriber, type: SubscriberType.Dequeue });\n            this.drain();\n        }\n\n        return deferredSubscriber.promise();\n    }\n\n    public peek = (): Promise<TItem> => {\n        this.throwIfDispose();\n        const deferredSubscriber = new Deferred<TItem>();\n\n        const subs = this.privSubscribers;\n        if (subs) {\n            this.privSubscribers.add({ deferral: deferredSubscriber, type: SubscriberType.Peek });\n            this.drain();\n        }\n\n        return deferredSubscriber.promise();\n    }\n\n    public length = (): number => {\n        this.throwIfDispose();\n        return this.privList.length();\n    }\n\n    public isDisposed = (): boolean => {\n        return this.privSubscribers == null;\n    }\n\n    public drainAndDispose = (pendingItemProcessor: (pendingItemInQueue: TItem) => void, reason?: string): Promise<boolean> => {\n        if (!this.isDisposed() && !this.privIsDisposing) {\n            this.privDisposeReason = reason;\n            this.privIsDisposing = true;\n\n            const subs = this.privSubscribers;\n            if (subs) {\n                while (subs.length() > 0) {\n                    const subscriber = subs.removeFirst();\n                    // TODO: this needs work (Resolve(null) instead?).\n                    subscriber.deferral.resolve(undefined);\n                    // subscriber.deferral.reject(\"Disposed\");\n                }\n\n                // note: this block assumes cooperative multitasking, i.e.,\n                // between the if-statement and the assignment there are no\n                // thread switches.\n                // Reason is that between the initial const = this.; and this\n                // point there is the derral.resolve() operation that might have\n                // caused recursive calls to the Queue, especially, calling\n                // Dispose() on the queue alredy (which would reset the var\n                // here to null!).\n                // That should generally hold true for javascript...\n                if (this.privSubscribers === subs) {\n                    this.privSubscribers = subs;\n                }\n            }\n\n            for (const detachable of this.privDetachables) {\n                detachable.detach();\n            }\n\n            if (this.privPromiseStore.length() > 0 && pendingItemProcessor) {\n                return PromiseHelper\n                    .whenAll(this.privPromiseStore.toArray())\n                    .continueWith(() => {\n                        this.privSubscribers = null;\n                        this.privList.forEach((item: TItem, index: number): void => {\n                            pendingItemProcessor(item);\n                        });\n                        this.privList = null;\n                        return true;\n                    });\n            } else {\n                this.privSubscribers = null;\n                this.privList = null;\n            }\n        }\n\n        return PromiseHelper.fromResult(true);\n    }\n\n    public dispose = (reason?: string): void => {\n        this.drainAndDispose(null, reason);\n    }\n\n    private drain = (): void => {\n        if (!this.privIsDrainInProgress && !this.privIsDisposing) {\n            this.privIsDrainInProgress = true;\n\n            const subs = this.privSubscribers;\n            const lists = this.privList;\n            if (subs && lists) {\n                while (lists.length() > 0 && subs.length() > 0 && !this.privIsDisposing) {\n                    const subscriber = subs.removeFirst();\n                    if (subscriber.type === SubscriberType.Peek) {\n                        subscriber.deferral.resolve(lists.first());\n                    } else {\n                        const dequeuedItem = lists.removeFirst();\n                        subscriber.deferral.resolve(dequeuedItem);\n                    }\n                }\n\n                // note: this block assumes cooperative multitasking, i.e.,\n                // between the if-statement and the assignment there are no\n                // thread switches.\n                // Reason is that between the initial const = this.; and this\n                // point there is the derral.resolve() operation that might have\n                // caused recursive calls to the Queue, especially, calling\n                // Dispose() on the queue alredy (which would reset the var\n                // here to null!).\n                // That should generally hold true for javascript...\n                if (this.privSubscribers === subs) {\n                    this.privSubscribers = subs;\n                }\n\n                // note: this block assumes cooperative multitasking, i.e.,\n                // between the if-statement and the assignment there are no\n                // thread switches.\n                // Reason is that between the initial const = this.; and this\n                // point there is the derral.resolve() operation that might have\n                // caused recursive calls to the Queue, especially, calling\n                // Dispose() on the queue alredy (which would reset the var\n                // here to null!).\n                // That should generally hold true for javascript...\n                if (this.privList === lists) {\n                    this.privList = lists;\n                }\n            }\n\n            this.privIsDrainInProgress = false;\n        }\n    }\n\n    private throwIfDispose = (): void => {\n        if (this.isDisposed()) {\n            if (this.privDisposeReason) {\n                throw new InvalidOperationError(this.privDisposeReason);\n            }\n\n            throw new ObjectDisposedError(\"Queue\");\n        } else if (this.privIsDisposing) {\n            throw new InvalidOperationError(\"Queue disposing\");\n        }\n    }\n}\n"]}