Canales y Corrutinas
Canales y Corrutinas
Sección titulada «Canales y Corrutinas»Canales estilo Go para comunicación entre corrutinas. Crear canales con o sin buffer, enviar y recibir valores, y coordinar entre procesos concurrentes usando sentencias select.
El global channel siempre esta disponible.
Crear Canales
Sección titulada «Crear Canales»Los canales sin buffer (tamano 0) requieren que tanto el emisor como el receptor esten listos antes de que la transferencia complete. Los canales con buffer permiten que los envios completen inmediatamente mientras haya espacio disponible:
-- Sin buffer: sincroniza emisor y receptorlocal sync_ch = channel.new()
-- Con buffer: encolar hasta 10 mensajeslocal work_queue = channel.new(10)| Parámetro | Tipo | Descripción |
|---|---|---|
size | integer | Capacidad del buffer (por defecto: 0 para sin buffer) |
Devuelve: channel
Enviar Valores
Sección titulada «Enviar Valores»Enviar un valor al canal. Bloquea hasta que un receptor este listo (sin buffer) o haya espacio en el buffer (con buffer):
-- Enviar trabajo a un pool de trabajadoreslocal jobs = channel.new(100)for i, task in ipairs(tasks) do jobs:send(task) -- Bloquea si buffer llenoendjobs:close() -- Senalar que no hay mas trabajo| Parámetro | Tipo | Descripción |
|---|---|---|
value | any | Valor a enviar |
Devuelve: boolean
Genera error si el canal esta cerrado.
Recibir Valores
Sección titulada «Recibir Valores»Recibir un valor del canal. Bloquea hasta que un valor este disponible o el canal este cerrado:
-- Trabajador consumiendo de cola de trabajoswhile true do local job, ok = work:receive() if not ok then break -- Canal cerrado, no mas trabajo end process(job)endDevuelve: any, boolean
value, true- Recibio un valornil, false- Canal cerrado y vacio
Cerrar Canales
Sección titulada «Cerrar Canales»Cerrar el canal. Los emisores pendientes obtienen un error, los receptores pendientes obtienen nil, false. Genera error si ya esta cerrado:
local results = channel.new(10)
-- Productor llena resultadosfor _, item in ipairs(data) do results:send(process(item))endresults:close() -- Senalar completacionSeleccionar de Multiples Canales
Sección titulada «Seleccionar de Multiples Canales»Esperar en multiples operaciones de canal simultaneamente. Esencial para manejar multiples fuentes de eventos, implementar timeouts y construir sistemas responsivos:
local result = channel.select(cases)| Parámetro | Tipo | Descripción |
|---|---|---|
cases | table | Array de casos select |
default | boolean | Si true, devuelve inmediatamente cuando ningun caso este listo |
Devuelve: table con campos: channel, value, ok, default
Patrón de Timeout
Sección titulada «Patrón de Timeout»Esperar resultado con timeout usando time.after().
local time = require("time")
local result_ch = worker:response()local timeout = time.after("5s")
local r = channel.select { result_ch:case_receive(), timeout:case_receive()}
if r.channel == timeout then return nil, errors.new("TIMEOUT", "Operation timed out")endreturn r.valuePatrón Fan-in
Sección titulada «Patrón Fan-in»Fusionar multiples fuentes en un manejador.
local events = process.events()local inbox = process.inbox()local shutdown = channel.new()
while true do local r = channel.select { events:case_receive(), inbox:case_receive(), shutdown:case_receive() }
if r.channel == shutdown then break elseif r.channel == events then handle_event(r.value) else handle_message(r.value) endendVerificacion No Bloqueante
Sección titulada «Verificacion No Bloqueante»Verificar si hay datos disponibles sin bloquear.
local r = channel.select { ch:case_receive(), default = true}
if r.default then -- Nada disponible, hacer algo maselse process(r.value)endCrear Casos Select
Sección titulada «Crear Casos Select»Crear casos para usar con channel.select:
-- Caso send - completa cuando el canal puede aceptar valorch:case_send(value)
-- Caso receive - completa cuando hay valor disponiblech:case_receive()Patrón de Pool de Trabajadores
Sección titulada «Patrón de Pool de Trabajadores»local work = channel.new(100)local results = channel.new(100)
-- Crear trabajadoresfor i = 1, num_workers do process.spawn("app.workers:processor", "app:processes", work, results)end
-- Alimentar trabajofor _, item in ipairs(items) do work:send(item)endwork:close()
-- Recolectar resultadoslocal processed = {}while #processed < #items do local result, ok = results:receive() if not ok then break end table.insert(processed, result)endErrores
Sección titulada «Errores»| Condición | Tipo | Reintentable |
|---|---|---|
| Enviar en canal cerrado | error de runtime | no |
| Cerrar canal cerrado | error de runtime | no |
| Caso invalido en select | error de runtime | no |
Vea También
Sección titulada «Vea También»- Gestión de Procesos - Creacion de procesos y comunicación
- Cola de Mensajes - Mensajeria basada en colas
- Funciones - Invocacion de funciones