# Sincronización de hilos

Cuando estés lo suficientemente avanzado en live-coding con un número de funciones e hilos simultáneamente, notarás que es muy fácil cometer un error en uno de los hilos y eso lo mata. Eso no es gran cosa, porque puedes fácilmente recomenzar el hilo con apretar Run. Sin embargo, cuando recomiences el hilo estará out of time con los hilos actuales.

## Tiempo heredado

Como discutíamos anteriormente, nuevos hilos creados con `in_thread` heredan todos los seteos del hilo padre. Esto incluye el tiempo actual, lo que significa que los hilos estarán siempre en el tiempo con los demás cuando comenzados simultáneamente.

Sin embargo, cuando comienzas un hilo aparte, comienza con su propio tiempo que difícilmente estará sincronizado con alguno de los otros que estén siendo corridos.

## Cue y Sync (funciones)

Sonic Pi provee una solución a este problema con las funciones `cue` y `sync`.

`cue` permite enviar mensajes de pulso a todos los otros hilos, los cuales, en principio no están interesados e ignoran estos mensajes. Sin embargo. puedes registrar fácilmente su interés con la función `sync`.

Lo importante de notar es que `sync` es similar a `sleep` en que para el hilo actual por un tiempo. Sin embargo, con `sleep` tu especificas cuánto tiempo va a esperar, en cambio con `sync` no sabes cuánto tiempo esperará - ya que `sync` espera por el siguiente `cue` de otro hilo.

Exploremos esto en más detalle:

    in_thread do
      loop do
        cue :tick
        sleep 1
      end
    end
    in_thread do
      loop do
        sync :tick
        sample :drum_heavy_kick
      end
    end

Aquí tenemos dos hilos - uno actuando como un metrónomo, no haciendo sonidos sino que enviando `:tick` mensajes de pulso. El segundo hilo está sincronizandose con los mensajes de `tick` y cuando recibe uno, hereda el tiempo del hilo de `cue` y continúa tocando.

El resultado es que escuchamos el sample de `:drum_heavy_kick` exactamente cuando el otro hilo envía el mensaje `:tick`, aunque ambos hilos no comenzaron su ejecución al mismo tiempo:

    in_thread do
      loop do
        cue :tick
        sleep 1
      end
    end
    sleep(0.3)
    in_thread do
      loop do
        sync :tick
        sample :drum_heavy_kick
      end
    end

Esa llamada `sleep` típicamente haría que el segundo hilo vaya fuera de fase con el primero. Sin embargo, por estar usando `cue` y `sync`, sincronizamos ambos hilos automáticamente.

## Nombres de Cue

Eres libre de utilizar cualquier nombre que quieras a los mensajes de `cue` - no sólo `:tick`. Sólo debes asegurarte que los otros hilos estén `sync` sincronizándose en el nombre correctoe - de otro modo se quedarán esperando por siempre (o hasta presionar el botón de Parar)

Juguemos con unos cuantos nombres para `cue`:

    in_thread do
      loop do
        cue [:foo, :bar, :baz].choose
        sleep 0.5
      end
    end
    in_thread do
      loop do
        sync :foo
        sample :elec_beep
      end
    end
    in_thread do
      loop do
        sync :bar
        sample :elec_flip
      end
    end
    in_thread do
      loop do
        sync :baz
        sample :elec_blup
      end
    end

Aquí tenemos un `cue` principal bucleado, el cual envía aleatoriamente uno de los nombres de pulso `:foo`, `:bar` o `:baz`. Después tenemos también tres bucles de hilos sincronizándose entre ellos independientemente y tocando un sampleo diferente. El efecto es que escuchamos un sonido cada 0.5 pulsos que cada uno de los hilos está aleatoriamente sincronizándose `sync` con el hilo de `cue` y toca su sampleo.

Por supuesto que esto también funciona si ordenas los hilos en reversa, ya que los hilos `sync` siempre esperarán al siguiente `cue`.