Skip to content

Instantly share code, notes, and snippets.

@hiredman
Created August 7, 2019 17:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hiredman/2271c48e1f036253ce37913abd3a680a to your computer and use it in GitHub Desktop.
Save hiredman/2271c48e1f036253ce37913abd3a680a to your computer and use it in GitHub Desktop.
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