UNPKG

@prelude/channel

Version:

Channel module.

87 lines 3.2 kB
"use strict"; 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