/** * Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal */ import { RuntimeContext } from './execution/runtime-context' import { Progress } from './execution/progress' import { ExecuteObservable, ExecuteObservableChild, ExecuteInContext } from './execution/observable'; import { SyncRuntimeContext } from './execution/synchronous'; import { idFactory } from '../mol-util/id-factory'; /** A "named function wrapper" with built in "computation tree progress tracking". */ interface Task { /** run the task without observation */ run(): Promise, /** run the task with the specified observer, default updateRate is 250ms */ run(observer: Progress.Observer, updateRateMs?: number): Promise, /** * Run a child task that adds a new node to the progress tree. Allows to passing the progress so * that the progress tree can be kept in a "good state" without having to separately call update. */ runAsChild(ctx: RuntimeContext, progress?: string | Partial): Promise /** Run the task on the specified context. */ runInContext(ctx: RuntimeContext): Promise readonly id: number, readonly name: string } namespace Task { class Impl implements Task { readonly id: number; run(observer?: Progress.Observer, updateRateMs = 250): Promise { if (observer) return ExecuteObservable(this, observer, updateRateMs); return this.f(SyncRuntimeContext); } runAsChild(ctx: RuntimeContext, progress?: string | Partial): Promise { if (ctx.isSynchronous) return this.f(SyncRuntimeContext); return ExecuteObservableChild(ctx, this, progress as string | Partial); } runInContext(ctx: RuntimeContext): Promise { if (ctx.isSynchronous) return this.f(SyncRuntimeContext); return ExecuteInContext(ctx, this); } constructor(public name: string, public f: (ctx: RuntimeContext) => Promise, public onAbort?: () => void) { this.id = getNextId(); } } export interface Aborted { isAborted: true, reason: string } export function isAbort(e: any): e is Aborted { return !!e && !!e.isAborted; } export function Aborted(reason: string): Aborted { return { isAborted: true, reason }; } export function create(name: string, f: (ctx: RuntimeContext) => Promise, onAbort?: () => void): Task { return new Impl(name, f, onAbort); } export function constant(name: string, value: T): Task { return create(name, async ctx => value); } export function fail(name: string, reason: string): Task { return create(name, async ctx => { throw new Error(reason); }); } export interface Progress { taskId: number, taskName: string, startedTime: number, message: string, canAbort: boolean, isIndeterminate: boolean, current: number, max: number } const getNextId = idFactory(0, 0x3fffffff) } export { Task }