Rewrite the scheduler: more efficient and always finite
parent
112693ad3e
commit
bdd83fee1c
|
@ -7,14 +7,16 @@ const pathlib = require('path');
|
|||
const extractors = require('./extractors');
|
||||
const Command = require('./commands');
|
||||
const {Scope, Module} = require('./scope');
|
||||
const CircularList = require('./list');
|
||||
|
||||
class Collector {
|
||||
constructor(parser, root = '.') {
|
||||
this.root = root;
|
||||
this.parser = parser;
|
||||
this.schemas = [];
|
||||
this.tasks = [];
|
||||
this.tasks = new CircularList;
|
||||
this.taskCount = 0;
|
||||
this.active = true;
|
||||
this.modules = new Map;
|
||||
this.global = Scope.global([]);
|
||||
this.running = false;
|
||||
|
@ -82,7 +84,7 @@ class Collector {
|
|||
if (type && type in extractors) {
|
||||
const task = this._collect(node, scope);
|
||||
|
||||
this.tasks.push(task);
|
||||
this.tasks.add(task);
|
||||
++this.taskCount;
|
||||
|
||||
continue;
|
||||
|
@ -109,6 +111,8 @@ class Collector {
|
|||
let result = null;
|
||||
|
||||
while (true) {
|
||||
this.active = true;
|
||||
|
||||
const {done, value} = iter.next(result);
|
||||
|
||||
if (done) {
|
||||
|
@ -199,17 +203,28 @@ class Collector {
|
|||
}
|
||||
|
||||
_schedule() {
|
||||
// TODO: prevent infinite loop.
|
||||
|
||||
const {tasks} = this;
|
||||
|
||||
for (let i = 0; tasks.length > 0; i = ++i % tasks.length) {
|
||||
const {done} = tasks[i].next();
|
||||
let marker = null;
|
||||
|
||||
while (!tasks.isEmpty) {
|
||||
const task = tasks.remove();
|
||||
|
||||
const {done} = task.next();
|
||||
|
||||
if (done) {
|
||||
// TODO: use linked list instead.
|
||||
tasks.splice(i, 1);
|
||||
--i;
|
||||
marker = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
tasks.add(task);
|
||||
|
||||
if (this.active) {
|
||||
marker = task;
|
||||
this.active = false;
|
||||
} else if (task === marker) {
|
||||
// TODO: warning.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
class CircularList {
|
||||
constructor() {
|
||||
this.mark = Symbol();
|
||||
this.prev = null;
|
||||
this.walk = null;
|
||||
}
|
||||
|
||||
get isEmpty() {
|
||||
return !this.walk;
|
||||
}
|
||||
|
||||
add(entry) {
|
||||
assert(!entry[this.mark]);
|
||||
|
||||
if (this.prev) {
|
||||
assert(this.walk);
|
||||
|
||||
this.prev = this.prev[this.mark] = entry;
|
||||
} else {
|
||||
assert(!this.walk);
|
||||
|
||||
this.walk = this.prev = entry;
|
||||
}
|
||||
|
||||
entry[this.mark] = this.walk;
|
||||
|
||||
assert(!this.prev || this.prev[this.mark] === this.walk);
|
||||
}
|
||||
|
||||
remove() {
|
||||
assert(this.walk);
|
||||
|
||||
const removed = this.walk;
|
||||
|
||||
if (removed === this.prev) {
|
||||
this.walk = this.prev = null;
|
||||
} else {
|
||||
this.walk = this.prev[this.mark] = removed[this.mark];
|
||||
}
|
||||
|
||||
removed[this.mark] = null;
|
||||
|
||||
return removed;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CircularList;
|
|
@ -24,6 +24,17 @@
|
|||
"namespace": "externals.first",
|
||||
"fields": [{"name": "d", "type": "double"}]
|
||||
},
|
||||
{
|
||||
"type": "record",
|
||||
"name": "X",
|
||||
"namespace": "externals",
|
||||
"fields": [
|
||||
{"name": "a", "type": "externals.first.A"},
|
||||
{"name": "b", "type": "externals.first.B"},
|
||||
{"name": "c", "type": "externals.first.CC"},
|
||||
{"name": "d", "type": "externals.first.D"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "record",
|
||||
"name": "N",
|
||||
|
@ -48,17 +59,6 @@
|
|||
"namespace": "externals.second",
|
||||
"fields": [{"name": "p", "type": "double"}]
|
||||
},
|
||||
{
|
||||
"type": "record",
|
||||
"name": "X",
|
||||
"namespace": "externals",
|
||||
"fields": [
|
||||
{"name": "a", "type": "externals.first.A"},
|
||||
{"name": "b", "type": "externals.first.B"},
|
||||
{"name": "c", "type": "externals.first.CC"},
|
||||
{"name": "d", "type": "externals.first.D"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "record",
|
||||
"name": "Y",
|
||||
|
|
Loading…
Reference in New Issue