From dd6534d56cc3b2dbb3ce7ba938a6ea2e41631873 Mon Sep 17 00:00:00 2001
From: Jake <jake.read@cba.mit.edu>
Date: Mon, 2 Sep 2019 14:52:40 -0400
Subject: [PATCH] refactor transport, coming back to life
---
bootstrap.js | 2 +-
hunks/debug/timing.js | 4 +-
hunks/hunks.js | 168 ++++++++++++----------
hunks/manager.js | 11 +-
hunks/view.js | 6 +-
save/contexts/cuttlefish/simple-loop.json | 4 +-
6 files changed, 109 insertions(+), 86 deletions(-)
diff --git a/bootstrap.js b/bootstrap.js
index 9912334..b2adef4 100644
--- a/bootstrap.js
+++ b/bootstrap.js
@@ -39,7 +39,7 @@ function bootloop() {
console.error('loop halting, mgr bailing')
return
}
- setTimeout(bootloop)
+ setTimeout(bootloop, 50)
}
window.onload = () => {
diff --git a/hunks/debug/timing.js b/hunks/debug/timing.js
index 3655235..a5f19d0 100644
--- a/hunks/debug/timing.js
+++ b/hunks/debug/timing.js
@@ -20,7 +20,7 @@ function Timing(){
let out = new Output('boolean', 'thru', this)
this.outputs.push(out)
- let count = new State('number', 'average', 100)
+ let count = new State('number', 'average', 20)
this.states.push(count)
let val = false
@@ -37,7 +37,7 @@ function Timing(){
t1 = performance.now()
// work
avsum += t1 - t0
- t0 = t1
+ t0 = t1
avcnt ++
if(avcnt > count.value){
console.log("tm: ", avsum / count.value)
diff --git a/hunks/hunks.js b/hunks/hunks.js
index 40d6ca9..f409fd0 100644
--- a/hunks/hunks.js
+++ b/hunks/hunks.js
@@ -2,7 +2,9 @@
/* ------------------------ HUNKITUP ------------------------- */
/* --------------------------- ---------------------------- */
-import { TSET } from '../typeset.js'
+import {
+ TSET
+} from '../typeset.js'
function Hunkify(hunk) {
// scripting languages should name hunks by their script location and filename
@@ -18,7 +20,7 @@ function Hunkify(hunk) {
let str = `LG from ${hunk.name} at ${hunk.ind}: `
for (let i = 0; i < arguments.length; i++) {
str += arguments[i]
- if(i < arguments.length - 1) str += ', '
+ if (i < arguments.length - 1) str += ', '
}
console.log(str)
}
@@ -37,41 +39,64 @@ function Hunkify(hunk) {
/* --------------------------- ---------------------------- */
function Input(type, name, parent, linktype) {
+ // naming, etc
this.name = name
this.type = type
- // need this ...
this.parent = parent
- this.ref = null
- this.data = null
- this.io = false
- // rules, baby (nevermind: no rules)
- if (!isOKType(type)) {
- //throw new Error(`unknown type specified at input, wyd? type: ${this.type}, name: ${this.name}`)
+ // we keep access to the outputs we're hooked up to here
+ this.connections = new Array()
+ this.io = () => {
+ // if any of our connections have data that we haven't read once yet,
+ for (var i = 0; i < this.connections.length; i++) {
+ // have to update calls to .io -> .io()
+ if (this.connections[i].io) return true
+ }
+ return false
}
-
- // output.transport() uses this to deliver data,
- this.put = (data, ref) => {
- // used when MGR does transport
- if (data === undefined || data === null) {
- console.log("THROWING PUT OF UNDEF OR NULL")
- console.log('to', this)
- throw new Error('UNDEF OR NULL PUT TO LINK')
- } else {
- this.data = data
- // minutia hack for view function (??? @ jake wyd ???)
- if (ref) this.ref = ref
- this.io = true
+ // get calls are now a bit messier,
+ // we have multiple wires,
+ this.lastGet = -1 // place we read from last (have multiple wires case)
+ this.copyOut = {}
+ this.get = () => {
+ // we want to (roughly) round robin these
+ var i = this.lastGet
+ // find the next occupied conn
+ for(var u = 0; u < this.connections.length; u ++){
+ // increment, wrap
+ i ++
+ if(i >= this.connections.length) i = 0
+ // do work,
+ console.log('work for', i, this.connections[i])
+ if (this.connections[i].io) {
+ // and set that wire to read / empty
+ this.connections[i].io = false
+ // and we'd like to remember from whence we last took data
+ this.lastGet = i
+ // get this data out ... we have to copy it out again, otherwise
+ // downstream operators may write to objects that have handles elsewhere
+ return this.copyOut(i)
+ }
}
+ // if we pass this for w/o hitting return,
+ console.error("Warn! Hunk pulling on empty input!")
+ return null
}
- // hunk pulls data via .get()
- this.get = () => {
- if (this.io) {
- this.io = false
- return this.data
- } else {
- throw new Error('Warn! Hunk pulling on empty input!')
- return null
+ // typing ... odd ?
+ if (type === "number" || type === "boolean" || type === "string") { // these are genuine base types and are not passed by reference,
+ this.copyOut = (indice) => {
+ console.log('cout reg')
+ return this.connections[indice].op.data
+ }
+ } else if (type === 'reference') {
+ this.copyOut = (indice) => {
+ console.log('cout ref')
+ return this.connections[indice].op.ref
+ }
+ } else { // this would cover "Object" and "Any" and whatever else, do your typechecking there
+ this.copyOut = (indice) => {
+ console.log('cout else')
+ return deepCopy(this.connections[indice].op.data)
}
}
@@ -84,8 +109,6 @@ function Input(type, name, parent, linktype) {
return index
}
- // we keep a list as well,
- this.connections = new Array()
this.disconnect = (output) => {
let index = this.connections.findIndex((cand) => {
return (cand.parent.ind === output.parent.ind && cand.name === output.name && cand.type === output.type)
@@ -94,6 +117,7 @@ function Input(type, name, parent, linktype) {
this.connections.splice(index, 1)
// find the reference in our array,
}
+
this.disconnectAll = () => {
for (let op of this.connections) {
op.remove(this)
@@ -105,6 +129,7 @@ function Input(type, name, parent, linktype) {
// assume clear upstream on startup, maybe dangerous?
this.icus = true
}
+
}
/* --------------------------- ---------------------------- */
@@ -112,14 +137,30 @@ function Input(type, name, parent, linktype) {
/* --------------------------- ---------------------------- */
function Output(type, name, parent, linktype) {
+ // naming, etc
this.name = name
this.type = type
this.parent = parent
+ // store,
this.ref = null
this.data = null
- this.posted = false
- this.io = false
+ // hookup
this.connections = new Array()
+ // check in realtime, manager does less
+ this.io = () => {
+ for (var i = 0; i < this.connections.length; i++) {
+ // connection arrays contain 'wires' ... these are stateful
+ if (this.connections[i].io) return true
+ }
+ return false
+ }
+
+ // when we put, we use this to set states
+ this.setIo = () => {
+ for (var i = 0; i < this.connections.length; i++) {
+ this.connections[i].io = true
+ }
+ }
/* --------------------------- ---------------------------- */
/* ------------ OUTPUT PUT AND TRANSPORT (TYPED) ------------- */
@@ -129,77 +170,49 @@ function Output(type, name, parent, linktype) {
// copy-in (chances are that after .put call the referenced object changes, before it is copied out)
// and copy-out (same on the other side, we are potentially passing to many downstream, need a different copy for each)
this.put = {}
- this.transport = {}
// typing ... odd ?
- if (type === "Number" || type === "Boolean" || type === "String") { // these are genuine base types and are not passed by reference,
+ if (type === "number" || type === "boolean" || type === "string") { // these are genuine base types and are not passed by reference,
this.put = (data) => {
- if (!(this.io)) {
+ if (!(this.io())) {
this.ref = data
this.data = data // so this is effectively a pass
- this.io = true
- this.posted = false
+ this.setIo()
return true
} else {
console.error(`ERROOOOOOR: put called on occupied output: output ${this.name} in ${this.parent.name}`)
return false
}
}
- this.transport = () => {
- for (let input of this.connections) {
- input.put(this.data)
- }
- this.posted = true
- }
} else if (type === 'reference') {
- // that's *right*
this.put = (data) => {
- if(!this.io) {
+ if (!this.io()) {
this.ref = data
this.data = data
- this.io = true
- this.posted = false
+ this.setIo()
return true
} else {
console.error(`ERROOOOOOR: put called on occupied output: output ${this.name} in ${this.parent.name}`)
return false
}
}
- this.transport = () => {
- for(let input of this.connections){
- input.put(this.data, this.data)
- }
- this.posted = true
- }
} else { // this would cover "Object" and "Any" and whatever else, do your typechecking there
// no rules bb
// names still gotta match tho
// scratch that, truly no rules
//if(!(type === "Object" || type === "Any")) throw new Error(`unknown type specified at hunk, wyd? type: ${this.type}, name: ${this.name}`)
this.put = (data) => {
- if (!this.io) {
+ if (!this.io()) {
// HACK for view
this.ref = data
// make case for byteArray: themr buffers
this.data = deepCopy(data)
- this.io = true
- this.posted = false
+ this.setIo()
return true
} else {
console.error(`WARN: put called on occupied output: output ${this.name} in ${this.parent.name}`)
return false
}
}
- this.transport = () => {
- for (let input of this.connections) {
- input.put(deepCopy(this.data), this.ref)
- }
- this.posted = true
- }
- }
-
- this.clear = () => {
- this.data = null
- this.io = false
}
/* --------------------------- ---------------------------- */
@@ -209,8 +222,16 @@ function Output(type, name, parent, linktype) {
this.attach = (input) => {
// no rules on types ATM, historic placeholder
if (this.type === input.type || input.type === 'any' || true) {
- input.connections.push(this)
- this.connections.push(input)
+ // the wire is the stateful part,
+ let wire = {
+ op: this,
+ opi: this.connections.length,
+ ip: input,
+ ipi: input.connections.length,
+ io: false
+ }
+ input.connections.push(wire)
+ this.connections.push(wire)
return true
} else {
throw new Error('attempt to attach mismatched types')
@@ -292,7 +313,7 @@ function State(type, name, startup) {
this.change = (value, msgid) => {
// coupla steps here, we track and then call internal fn,
this.msgid = msgid
- if(this.onChange){
+ if (this.onChange) {
this.onChange(value)
} else {
this.set(value)
@@ -307,12 +328,13 @@ function deepCopy(obj) {
return JSON.parse(JSON.stringify(obj))
}
+// depricated: used this to check (on input / output startup)
function isOKType(type) {
// etc, lowecase to match with typeof ~ queeeries ~
let ind = TSET.findIndex((cand) => {
return cand.name === type
})
- if(type === 'any'){
+ if (type === 'any') {
console.log('WARN!, type of "any" is a bit risky, and cannot traverse a link')
return true
} else if (ind === -1) {
diff --git a/hunks/manager.js b/hunks/manager.js
index 84b744e..99af7dc 100644
--- a/hunks/manager.js
+++ b/hunks/manager.js
@@ -478,7 +478,7 @@ function Manager() {
this.loop = () => {
// getting messages
- if (msgsin.io) {
+ if (msgsin.io()) {
let msg = msgsin.get()
if (msgverbose) console.log('MGR RX MSG:', msg)
if (!Array.isArray(msg)) throw new Error(`manager throwing object message, having header ${msg.header}`)
@@ -667,7 +667,7 @@ function Manager() {
// MSGS output check,
if (outmsgbuffer.length > 0) {
let debug = true
- if (!msgsout.io) {
+ if (!msgsout.io()) {
if (debug) {
let msg = outmsgbuffer.shift()
if (msgverbose) this.log(`buffer release msg type: ${msg.header}`)
@@ -679,8 +679,8 @@ function Manager() {
}
} // end msgs output check
- // TRANSPORT
-
+ // TRANSPORT (modmod: internal to outputs, inputs)
+ /*
hunks.forEach((hunk) => {
// begin transport, walk each output and push along
hunk.outputs.forEach((output) => {
@@ -726,6 +726,7 @@ function Manager() {
}
}) // end for each output
}) // end forEach((hunk)) for transport
+ */
// allow time, start at i = 1 so that we don't call out own loop, ourorbourousing ourselves to death
for (let i = 1; i < hunks.length; i++) {
@@ -742,7 +743,7 @@ function Manager() {
let writeMessage = (bytes) => {
if (this.isConnectedTo) {
- if (!msgsout.io && outmsgbuffer.length < 1) {
+ if (!msgsout.io() && outmsgbuffer.length < 1) {
// str8 shooters
if (msgverbose) this.log('msg out', bytes)
msgsout.put(bytes)
diff --git a/hunks/view.js b/hunks/view.js
index 2e29087..73bd3b6 100644
--- a/hunks/view.js
+++ b/hunks/view.js
@@ -890,7 +890,7 @@ function View() {
let outmsgbuffer = new Array()
let writeMessage = (bytes) => {
- if (!msgsout.io && outmsgbuffer.length < 1) {
+ if (!msgsout.io() && outmsgbuffer.length < 1) {
// str8 shooters
if (msgverbose) this.log('msg out', bytes)
msgsout.put(bytes)
@@ -932,7 +932,7 @@ function View() {
this.loop = () => {
// THE Q: is it trees or is it inputs / outputs ? ports ...
- if (msgsin.io) {
+ if (msgsin.io()) {
let msg = msgsin.get()
if (msgverbose) console.log('VIEW RX MSG:', msg)
if (!Array.isArray(msg)) throw new Error(`view throwing object message, having header ${msg.header}`)
@@ -1101,7 +1101,7 @@ function View() {
// MSGS output check,
if (outmsgbuffer.length > 0) {
let debug = true
- if (!msgsout.io) {
+ if (!msgsout.io()) {
if (debug) {
let msg = outmsgbuffer.shift()
if (msgverbose) this.log(`buffer release msg type: ${msg.header}`)
diff --git a/save/contexts/cuttlefish/simple-loop.json b/save/contexts/cuttlefish/simple-loop.json
index 8e139ed..b74f454 100644
--- a/save/contexts/cuttlefish/simple-loop.json
+++ b/save/contexts/cuttlefish/simple-loop.json
@@ -73,7 +73,7 @@
{
"name": "average",
"type": "number",
- "value": 100
+ "value": 20
}
]
},
@@ -124,4 +124,4 @@
"states": []
}
]
-}
\ No newline at end of file
+}
--
GitLab