Skip to content
Snippets Groups Projects
Commit f16c699d authored by David Sehnal's avatar David Sehnal
Browse files

Added linked list to mol-data, refactoring

parent 64ba197d
No related branches found
No related tags found
No related merge requests found
Showing
with 257 additions and 18 deletions
/**
* Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
export * from './generic/hash-set'
export * from './generic/linked-list'
export * from './generic/unique-array'
\ No newline at end of file
/**
* Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
import { LinkedList } from '../linked-list'
describe('linked list', () => {
function toArray<T>(list: LinkedList<T>) {
const ret: T[] = [];
for (let t = list.first; !!t; t = t.next) {
ret[ret.length] = t.value;
}
return ret;
}
function create<T>(xs: T[]) {
const list = LinkedList<T>();
for (const x of xs) list.addLast(x);
return list;
}
it('add', () => {
const list = LinkedList<number>();
list.addFirst(1);
list.addLast(2);
list.addFirst(3);
list.addFirst(4);
list.addLast(5);
expect(toArray(list)).toEqual([4, 3, 1, 2, 5]);
expect(list.count).toBe(5);
});
it ('remove', () => {
const list = create([1, 2, 3, 4]);
let fst = list.removeFirst();
expect(fst).toBe(1);
expect(list.last!.value).toBe(4);
expect(list.count).toBe(3);
expect(toArray(list)).toEqual([2, 3, 4]);
let last = list.removeLast();
expect(last).toBe(4);
expect(list.last!.value).toBe(3);
expect(list.count).toBe(2);
expect(toArray(list)).toEqual([2, 3]);
let n3 = list.find(3)!;
list.remove(n3);
expect(list.first!.value).toBe(2);
expect(list.last!.value).toBe(2);
expect(list.count).toBe(1);
expect(toArray(list)).toEqual([2]);
list.removeFirst();
expect(list.first).toBe(null);
expect(list.last).toBe(null);
expect(list.count).toBe(0);
expect(toArray(list)).toEqual([]);
})
});
\ No newline at end of file
File moved
/**
* Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
*/
interface LinkedList<T> {
readonly count: number,
readonly first: LinkedList.Node<T> | null,
readonly last: LinkedList.Node<T> | null,
addFirst(value: T): LinkedList.Node<T>,
addLast(value: T): LinkedList.Node<T>,
remove(node: LinkedList.Node<T>): void,
removeFirst(): T | undefined,
removeLast(): T | undefined,
find(value: T): LinkedList.Node<T> | undefined
}
function LinkedList<T>(): LinkedList<T> {
return new LinkedListImpl();
}
namespace LinkedList {
export interface Node<T> {
previous: Node<T> | null,
next: Node<T> | null,
inList: boolean,
value: T
}
}
function createListNode<T>(value: T): LinkedList.Node<T> {
return { previous: null, next: null, inList: true, value };
}
class LinkedListImpl<T> implements LinkedList<T> {
count: number = 0;
first: LinkedList.Node<T> | null = null;
last: LinkedList.Node<T> | null = null;
addFirst(value: T) {
const node = createListNode(value);
node.inList = true;
if (this.first) this.first.previous = node;
node.next = this.first;
this.first = node;
this.count++;
if (!this.last) this.last = node;
return node;
}
addLast(value: T) {
const node = createListNode(value);
if (this.last !== null) {
this.last.next = node;
}
node.previous = this.last;
this.last = node;
if (this.first === null) {
this.first = node;
}
node.inList = true;
this.count++;
return node;
}
removeFirst(): T | undefined {
const fst = this.first;
if (fst) {
this.remove(fst);
return fst.value;
}
return void 0;
}
removeLast(): T | undefined {
const last = this.last;
if (last) {
this.remove(last);
return last.value;
}
return void 0;
}
remove(node: LinkedList.Node<T>) {
if (!node.inList) return;
node.inList = false;
if (node.previous !== null) {
node.previous.next = node.next;
}
else if (/*first == item*/ node.previous === null) {
this.first = node.next;
}
if (node.next !== null) {
node.next.previous = node.previous;
}
else if (/*last == item*/ node.next === null) {
this.last = node.previous;
}
node.next = null;
node.previous = null;
this.count--;
}
find(value: T): LinkedList.Node<T> | undefined {
let current = this.first;
while (current !== null) {
if (current.value === value) return current;
current = current.next;
}
return void 0;
}
}
export { LinkedList }
\ No newline at end of file
...@@ -8,5 +8,6 @@ import * as DB from './db' ...@@ -8,5 +8,6 @@ import * as DB from './db'
import * as Int from './int' import * as Int from './int'
import Iterator from './iterator' import Iterator from './iterator'
import * as Util from './util' import * as Util from './util'
import * as Generic from './generic'
export { DB, Int, Iterator, Util } export { DB, Int, Iterator, Util, Generic }
\ No newline at end of file \ No newline at end of file
...@@ -5,8 +5,6 @@ ...@@ -5,8 +5,6 @@
*/ */
export * from './util/chunked-array' export * from './util/chunked-array'
export * from './util/unique-array'
export * from './util/hash-set'
export * from './util/equivalence-classes' export * from './util/equivalence-classes'
export * from './util/hash-functions' export * from './util/hash-functions'
export * from './util/sort' export * from './util/sort'
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* @author David Sehnal <david.sehnal@gmail.com> * @author David Sehnal <david.sehnal@gmail.com>
*/ */
import { HashSet } from 'mol-data/util' import { HashSet } from 'mol-data/generic'
import { Structure, AtomSet } from '../structure' import { Structure, AtomSet } from '../structure'
// A selection is a pair of a Structure and a sequence of unique AtomSets // A selection is a pair of a Structure and a sequence of unique AtomSets
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
import { OrderedSet, Iterator } from 'mol-data/int' import { OrderedSet, Iterator } from 'mol-data/int'
import { UniqueArray } from 'mol-data/util' import { UniqueArray } from 'mol-data/generic'
import SymmetryOperator from 'mol-math/geometry/symmetry-operator' import SymmetryOperator from 'mol-math/geometry/symmetry-operator'
import { Model, Format } from '../model' import { Model, Format } from '../model'
import Unit from './unit' import Unit from './unit'
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
*/ */
import Scheduler from './scheduler' import Scheduler from './scheduler'
import timeNow from './time' import timeNow from './util/now'
interface Computation<A> { interface Computation<A> {
(ctx?: Computation.Context): Promise<A> (ctx?: Computation.Context): Promise<A>
......
...@@ -7,10 +7,38 @@ ...@@ -7,10 +7,38 @@
import Task from '../task' import Task from '../task'
import RuntimeContext from './runtime-context' import RuntimeContext from './runtime-context'
import Progress from './progress' import Progress from './progress'
import now from '../util/now'
function defaultProgress(rootTaskId: number, task: Task<any>): Task.Progress {
return {
rootTaskId,
taskId: task.id,
taskName: task.name,
message: 'Running...',
elapsedMs: { real: 0, cpu: 0 },
canAbort: true,
isIndeterminate: true,
current: 0,
max: 0
};
}
class ProgressInfo {
taskId: number;
elapsedMs: { real: number, cpu: number };
tree: Progress.Node;
tryAbort?: (reason?: string) => void;
snapshot(): Progress {
return 0 as any;
}
}
class ObservableExecutor { class ObservableExecutor {
progressInfo: ProgressInfo;
async run<T>(task: Task<T>): Promise<T> { async run<T>(task: Task<T>): Promise<T> {
const ctx = new ObservableRuntimeContext(); const ctx = new ObservableRuntimeContext(task.id, task, 0);
if (!task.__onAbort) return task.__f(ctx); if (!task.__onAbort) return task.__f(ctx);
try { try {
...@@ -27,14 +55,35 @@ class ObservableExecutor { ...@@ -27,14 +55,35 @@ class ObservableExecutor {
} }
class ObservableRuntimeContext implements RuntimeContext { class ObservableRuntimeContext implements RuntimeContext {
id: number = 0; elapsedCpuMs: number;
requiresUpdate: boolean = false; lastScheduledTime: number;
started: number;
taskId: number;
taskName: string;
progress: Task.Progress;
updateRateMs: number;
get requiresUpdate(): boolean {
return now() - this.started > this.updateRateMs;
}
update(progress: Partial<RuntimeContext.ProgressUpdate>): Promise<void> { update(progress: Partial<RuntimeContext.ProgressUpdate>): Promise<void> {
return 0 as any; return 0 as any;
} }
runChild<T>(progress: Partial<RuntimeContext.ProgressUpdate>, task: Task<T>): Promise<T> { runChild<T>(progress: Partial<RuntimeContext.ProgressUpdate>, task: Task<T>): Promise<T> {
return 0 as any; return 0 as any;
} }
constructor(parentId: number, task: Task<any>, updateRateMs: number) {
this.started = now();
this.lastScheduledTime = this.started;
this.taskId = task.id;
this.taskName = task.name;
this.progress = defaultProgress(parentId, task);
this.updateRateMs = updateRateMs;
}
} }
function ExecuteObservable<T>(task: Task<T>, observer: Progress.Observer, updateRateMs = 250) { function ExecuteObservable<T>(task: Task<T>, observer: Progress.Observer, updateRateMs = 250) {
......
...@@ -9,6 +9,7 @@ import RuntimeContext from './execution/runtime-context' ...@@ -9,6 +9,7 @@ import RuntimeContext from './execution/runtime-context'
import ExecuteSynchronous from './execution/synchronous' import ExecuteSynchronous from './execution/synchronous'
import ExecuteObservable from './execution/observable' import ExecuteObservable from './execution/observable'
import Progress from './execution/progress' import Progress from './execution/progress'
import now from './util/now'
function Run<T>(task: Task<T>): Promise<T>; function Run<T>(task: Task<T>): Promise<T>;
function Run<T>(task: Task<T>, observer: Progress.Observer, updateRateMs?: number): Promise<T>; function Run<T>(task: Task<T>, observer: Progress.Observer, updateRateMs?: number): Promise<T>;
...@@ -17,4 +18,4 @@ function Run<T>(task: Task<T>, observer?: Progress.Observer, updateRateMs?: numb ...@@ -17,4 +18,4 @@ function Run<T>(task: Task<T>, observer?: Progress.Observer, updateRateMs?: numb
return ExecuteSynchronous(task); return ExecuteSynchronous(task);
} }
export { Task, RuntimeContext, Progress, Run } export { Task, RuntimeContext, Progress, Run, now }
\ No newline at end of file \ No newline at end of file
...@@ -35,18 +35,17 @@ namespace Task { ...@@ -35,18 +35,17 @@ namespace Task {
return ret; return ret;
} }
export type Progress = IndeterminateProgress | DeterminateProgress export interface Progress {
interface ProgressBase {
rootTaskId: number, rootTaskId: number,
taskId: number, taskId: number,
taskName: string,
message: string, message: string,
elapsedMs: { real: number, cpu: number }, elapsedMs: { real: number, cpu: number },
canAbort: boolean canAbort: boolean,
isIndeterminate: boolean,
current: number,
max: number
} }
export interface IndeterminateProgress extends ProgressBase { isIndeterminate: true }
export interface DeterminateProgress extends ProgressBase { isIndeterminate: false, current: number, max: number }
} }
export default Task export default Task
\ No newline at end of file
File moved
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment