UNPKG

molstar

Version:

A comprehensive macromolecular library.

109 lines (108 loc) 3.94 kB
/** * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> */ import { Task } from '../../mol-task'; import { RxEventHelper } from '../../mol-util/rx-event-helper'; import { now } from '../../mol-util/now'; import { CreateObservableCtx, ExecuteInContext } from '../../mol-task/execution/observable'; import { arrayRemoveInPlace } from '../../mol-util/array'; export { TaskManager }; class TaskManager { constructor() { this.ev = RxEventHelper.create(); this.id = 0; this.runningTasks = new Set(); this.abortRequests = new Map(); this.options = new Map(); this.currentContext = []; this.events = { progress: this.ev(), finished: this.ev() }; } tryGetAbortTaskId(node) { if (this.abortRequests.has(node.progress.taskId)) return node.progress.taskId; for (const c of node.children) { const abort = this.tryGetAbortTaskId(c); if (abort !== void 0) return abort; } return void 0; } track(internalId, taskId) { return (progress) => { var _a; if (progress.canAbort && progress.requestAbort) { const abortTaskId = this.tryGetAbortTaskId(progress.root); if (abortTaskId !== void 0) progress.requestAbort(this.abortRequests.get(abortTaskId)); } const elapsed = now() - progress.root.progress.startedTime; this.events.progress.next({ id: internalId, useOverlay: (_a = this.options.get(taskId)) === null || _a === void 0 ? void 0 : _a.useOverlay, level: elapsed < 250 ? 'none' : 'background', progress }); }; } async run(task, params) { const id = this.id++; let ctx; if ((params === null || params === void 0 ? void 0 : params.createNewContext) || this.currentContext.length === 0) { ctx = { ctx: CreateObservableCtx(task, this.track(id, task.id), 100), refCount: 1 }; } else { ctx = this.currentContext[this.currentContext.length - 1]; ctx.refCount++; } try { this.options.set(task.id, { useOverlay: !!(params === null || params === void 0 ? void 0 : params.useOverlay) }); this.runningTasks.add(task.id); const ret = await ExecuteInContext(ctx.ctx, task); return ret; } finally { this.options.delete(task.id); this.runningTasks.delete(task.id); this.events.finished.next({ id }); this.abortRequests.delete(task.id); ctx.refCount--; if (ctx.refCount === 0) arrayRemoveInPlace(this.currentContext, ctx); } } requestAbortAll(reason) { this.runningTasks.forEach(id => this.abortRequests.set(id, reason)); } requestAbort(taskIdOrProgress, reason) { const id = typeof taskIdOrProgress === 'number' ? taskIdOrProgress : taskIdOrProgress.root.progress.taskId; this.abortRequests.set(id, reason); } dispose() { this.ev.dispose(); } } (function (TaskManager) { function delay(time) { return new Promise(res => setTimeout(res, time)); } function testTask(N) { return Task.create('Test', async (ctx) => { let i = 0; while (i < N) { await delay(100 + Math.random() * 200); if (ctx.shouldUpdate) { await ctx.update({ message: 'Step ' + i, current: i, max: N, isIndeterminate: false }); } i++; } }); } TaskManager.testTask = testTask; })(TaskManager || (TaskManager = {}));