function SyncChannel() { this.writers = []; this.readers = []; this.syncing = false; } SyncChannel.prototype.tryRead = function () { if (this.writers.length > 0) { var writer = this.writers.shift(); writer.continuation(); return { value: writer.value }; } else { return null; } }; SyncChannel.prototype.tryWrite = function (value) { if (this.readers.length > 0) { var reader = this.readers.shift(); reader.continuation(value); return true; } else { return false; } }; SyncChannel.prototype.read = function (continuation) { var channel = this; var reader = { continuation: continuation }; channel.readers.push(reader); if (!channel.syncing) channel.sync(); return function cancel() { var index = channel.readers.indexOf(reader); channel.readers.splice(index, 1); } }; SyncChannel.prototype.write = function (value, continuation) { continuation = continuation || function () { }; var channel = this; var writer = { continuation: continuation, value: value }; channel.writers.push(writer); if (!channel.syncing) channel.sync(); return function cancel() { var index = channel.writers.indexOf(writer); channel.writers.splice(index, 1); } }; SyncChannel.prototype.sync = function () { var channel = this; channel.syncing = true; (function loop() { setImmediate(function () { if (channel.readers.length > 0 && channel.writers.length > 0) { var reader = channel.readers.shift(); var writer = channel.writers.shift(); reader.continuation(writer.value); writer.continuation(); loop(); } else { channel.syncing = false; } }); })(); }; module.exports = SyncChannel;