@prelude/channel
Version:
Channel module.
87 lines • 3.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.selectSync = exports.selectAsync = exports.selectNext = exports.select = void 0;
const channel_js_1 = require("./channel.js");
async function* select(...attempts) {
while (true) {
const result = await selectNext(...attempts);
if (result.done) {
break;
}
yield result.value;
}
}
exports.select = select;
async function selectNext(...attempts) {
return selectSync(attempts) ?? await selectAsync(attempts);
}
exports.selectNext = selectNext;
function selectAsync(attempts) {
return new Promise((resolve, reject) => {
const undos = [];
for (const attempt of attempts) {
if (attempt instanceof channel_js_1.Channel) {
undos.push(attempt.pushRead(result => {
undos.forEach(undo => undo());
resolve(result);
}));
}
else if (attempt instanceof channel_js_1.WriteAttempt) {
undos.push(attempt.channel.pushWrite({ value: attempt.value, enqueued: (err) => {
undos.forEach(_ => _());
if (err) {
reject(err);
return;
}
resolve(attempt.perform(attempt.value));
} }));
}
else if (attempt instanceof channel_js_1.ReadAttempt) {
undos.push(attempt.channel.pushRead(result => {
undos.forEach(undo => undo());
resolve(attempt.perform(result));
}));
}
else {
throw new Error('Invalid attempt.');
}
}
});
}
exports.selectAsync = selectAsync;
function selectSync(attempts) {
const n = attempts.length;
for (let i = 0; i < n; i++) {
const j = i + Math.floor(Math.random() * (n - i));
const attempt = attempts[j];
if (attempt instanceof channel_js_1.Channel) {
if (attempt.pendingWrites > 0) {
return { value: attempt.consumeWrite() };
}
}
else if (attempt instanceof channel_js_1.WriteAttempt) {
if (attempt.channel.cap === 0 && attempt.channel.pendingReads > 0) {
attempt.channel.consumeRead({ value: attempt.value });
return attempt.perform(attempt.value);
}
else if (attempt.channel.pendingWrites < attempt.channel.cap) {
attempt.channel.pushWrite({ value: attempt.value });
return attempt.perform(attempt.value);
}
}
else if (attempt instanceof channel_js_1.ReadAttempt) {
if (attempt.channel.pendingWrites > 0) {
const value = attempt.channel.consumeWrite();
return attempt.perform({ value });
}
}
else {
throw new Error('Invalid attempt.');
}
attempts[j] = attempts[i];
attempts[i] = attempt;
}
return;
}
exports.selectSync = selectSync;
//# sourceMappingURL=select.js.map