Saltar al contenido

Canales

En esta página

Los canales son la forma idiomática de comunicar tareas en Zolo. channel(N) crea un canal con un buffer de capacidad N. ch.send(v) encola un valor; ch.recv() extrae uno y bloquea al llamador mientras el canal esté vacío — por eso los consumidores siempre deben ejecutarse dentro de spawn { ... }.

recv devuelve un Option: usa .is_some() / .unwrap() para inspeccionarlo, o .unwrap_or(defecto) para proporcionar un valor de fallback. Cuando el canal se cierra y el buffer está vacío, recv devuelve nil (opción vacía).

Canal de rendezvous (channel(0)) con dos spawns: el productor cierra, el consumidor comprueba is_some e is_none.

09-channels-basic.zolo
Playground
// Feature: channels — typed CSP-style message passing

// Syntax: `channel(buffer_size)` creates one. `ch.send(v)` enqueues,

// `ch.recv()` dequeues. `recv` returns an `Option` — use `is_some` /

// `unwrap` (or `for x in ch { ... }` which strips Option for you).

// `recv` blocks the caller, so it must run inside a coroutine.

// When to use: producer/consumer pipelines, bounded queues, fan-out

// of work across spawned tasks.


let ch = channel(0)
scope {
    spawn {
        ch.send(10)
        ch.send(20)
        ch.close()
    }
    spawn {
        let a = ch.recv()
        let b = ch.recv()
        let c = ch.recv()
        print(a.is_some())   // expected: true

        print(a.unwrap())    // expected: 10

        print(b.is_some())   // expected: true

        print(b.unwrap())    // expected: 20

        print(c.is_none())   // expected: true   (channel closed, drained)

    }
}

El patrón for x in ch { ... } drena el canal hasta que se cierra, desempaquetando el Option automáticamente. Es la forma más limpia de consumir un stream de mensajes.

Productor envía tres valores y cierra; consumidor usa for x in ch e imprime cada uno.

10-channels-for-in.zolo
Playground
// Feature: receive loop — `for x in ch` until close

// Syntax: `for x in ch { ... }` calls recv internally and exits when

// the channel is closed. The body runs once per received value.

// When to use: streaming consumers, log readers, event drainers —

// anywhere "process every message until the producer stops".


let ch = channel(0)
scope {
  spawn {
    ch.send(1)
    ch.send(2)
    ch.send(3)
    ch.close()
  }

  spawn {
    for x in ch {
      print(x)
    }
  }
}

print("done")
// expected:

//   1

//   2

//   3

//   done

channel(N) con N >= 1 almacena hasta N valores antes de aplicar contrapresión: el productor bloquea en send mientras el buffer está lleno. Esto nivela ráfagas sin crecimiento ilimitado de memoria.

Buffer de tamaño 2: el tercer send espera hasta que el consumidor libera un slot.

11-channels-bounded.zolo
Playground
// Feature: bounded channels — backpressure built in

// Syntax: `channel(N)` reserves a buffer of size N. Sends past

// capacity yield until the consumer drains a slot.

// When to use: rate-limit producers, prevent memory blowups in

// pipelines, smooth bursty workloads with a fixed-size queue.


let ch = channel(2)
scope {
    spawn {
        ch.send("a")
        ch.send("b")
        // The buffer is full; this third send waits until the consumer

        // recvs at least once.

        ch.send("c")
        ch.close()
    }
    spawn {
        print(ch.recv().unwrap())     // expected: a

        print(ch.recv().unwrap())     // expected: b

        print(ch.recv().unwrap())     // expected: c

        print(ch.recv().is_none())    // expected: true

    }
}

Desafío

Modifica el ejemplo básico para usar channel(4) en lugar de channel(0) y observa cómo el productor avanza sin esperar al consumidor.

Buscar en Zolo

9 resultados

enespt-br