Created
August 7, 2019 17:17
-
-
Save hiredman/2271c48e1f036253ce37913abd3a680a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var cml = { | |
Buffer:function (n) { | |
var buf = []; | |
this.full=function() { | |
return !(buf.length < n); | |
} | |
this.add=function(item){ | |
buf.push(item); | |
} | |
this.remove=function(item){ | |
return buf.shift(); | |
} | |
this.size=function(){ | |
return buf.length; | |
} | |
return this; | |
}, | |
Channel:function (buffer){ | |
this.recvq = []; | |
this.sendq = []; | |
this.buffer = buffer; | |
// TODO: closed | |
return this | |
}, | |
RX:function (channel) { | |
this.block=function (resume_recv,recv_state) { | |
if(channel.buffer.size() > 0) { | |
var val = channel.buffer.remove(); | |
return function() { return val }; | |
} | |
var sendq = channel.sendq | |
var pessimistic = function () { | |
var recvq = channel.recvq; | |
recvq.push([resume_recv, recv_state]); | |
}; | |
while(true){ | |
if (sendq.length > 0) { | |
var val = sendq[0][0]; | |
var resume_sender = sendq[0][1]; | |
var state = sendq[0][2]; | |
if (state[0] == "W") { | |
state[0] = "S"; | |
sendq.shift(); | |
resume_sender(function () { return true; }); | |
return function() { return val }; | |
} else { | |
sendq.shift(); | |
} | |
} else { | |
return pessimistic(); | |
} | |
} | |
} | |
return this | |
}, | |
TX:function (channel, value) { | |
this.block=function (resume_send, send_state){ | |
var recvq = channel.recvq; | |
while(true){ | |
if(recvq.length > 0) { | |
var resume_recv = recvq[0][0]; | |
var state = recvq[0][1]; | |
if (state[0] == "W") { | |
state[0] = "S"; | |
recvq.shift(); | |
resume_recv(function () { return value; }); | |
return function() { return true }; | |
} else { | |
recvq.shift(); | |
} | |
} else { | |
if(!channel.buffer.full()) { | |
channel.buffer.add(value); | |
return function() { return true }; | |
} else { | |
var sendq = channel.sendq | |
sendq.push([value, resume_send, send_state]); | |
return false; | |
} | |
} | |
} | |
} | |
return this; | |
}, | |
Select:function (events) { | |
this.block=function (resume, state) { | |
for(var i = 0; i < events.length; i++) { | |
events[i].block(resume, state); | |
} | |
} | |
return this; | |
}, | |
Timeout:function (ms) { | |
var waits = []; | |
var done = false; | |
this.block=function (resume, state) { | |
if(done) { | |
state[0] = "S"; | |
return resume(function () {return true;}); | |
} else { | |
waits.push([resume, state]); | |
} | |
} | |
setTimeout(function () { | |
for(var i = 0; i < waits.length; i++) { | |
if(waits[i][1][0] == "W") { | |
waits[i][1][0] = "S"; | |
var resume = waits[i][0]; | |
setTimeout(function () { | |
return resume(function () {return true;}); | |
}); | |
} | |
} | |
waits = []; | |
}, ms); | |
return this | |
}, | |
sync:function (event, callback) { | |
var state = ["W"]; | |
var f = event.block(callback, state); | |
if (f) { | |
return callback(f); | |
} | |
}, | |
go:function (f) { | |
console.log(f); | |
var waits = []; | |
var iter = f(); | |
var result = iter.next(); | |
var step = function() { | |
if(!result.done) { | |
var state = ["W"]; | |
var f = result.value.block( | |
function (f) { | |
setTimeout(function () { | |
result = iter.next(f()); | |
step(); | |
}, 0); | |
}, | |
state); | |
if (f) { | |
result = iter.next(f()); | |
return step(); | |
} | |
} else { | |
for(var i = 0; i<waits.length; i++) { | |
if(waits[i][1][0] == "W") { | |
waits[i][1][0] = "S"; | |
var resume = waits[i][0]; | |
setTimeout(function () { | |
resume(function () {return result.value;}); | |
}, 0); | |
} | |
} | |
} | |
} | |
setTimeout(step, 0); | |
return {block:function (resume, state) { | |
if(!result.done) { | |
waits.push([resume, state]); | |
} else { | |
state[0] = "S"; | |
return resume(function () {return result.value;}); | |
} | |
}}; | |
} | |
} | |
console.log("foo"); | |
var as = new cml.Channel(new cml.Buffer(0)); | |
var bs = new cml.Channel(new cml.Buffer(0)); | |
cml.go(function*(){ | |
yield new cml.Timeout(1000*Math.random()); | |
yield new cml.TX(as, "A"); | |
}) | |
cml.go(function*(){ | |
yield new cml.Timeout(1000*Math.random()); | |
yield new cml.TX(bs, "B"); | |
}) | |
var x = cml.go(function*(){ | |
var x = yield new cml.Select([new cml.RX(as),new cml.RX(bs)]); | |
console.log(x); | |
return 10; | |
}) | |
cml.go(function*(){ | |
var w = yield x; | |
console.log(w); | |
}) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment