Concurrency

Concurrency lives in the thread module. It is VM-based: each spawned function runs in its own isolated VM with a copy of the current globals. That isolation is what keeps concurrent work safe — tasks don’t share mutable state unless you opt in through the runtime store.

import thread

Spawning goroutines

import thread

thread.core.spawn(fn() {
    println("running in the background")
})

Other thread.core helpers: sleep(ms), cpus(), goroutines().

Async futures

Run work and await its result:

import thread
import time

let future = thread.async.run(fn() {
    time.timer.sleep(100)
    return "done"
})

println(thread.async.await(future))   // "done"

Channels

Typed message passing between tasks:

import thread

let ch = thread.channel.new(10)        // buffered channel, capacity 10

thread.core.spawn(fn() {
    thread.channel.send(ch, "hello from goroutine")
})

let msg = thread.channel.recv(ch)
println(msg)

Channel functions: new(capacity), send, recv, recvTimeout(id, ms), close, len, cap.

Locks & primitives

The thread module also provides the usual primitives:

Sub-modulePurpose
thread.mutexMutual-exclusion lock (lock, unlock, tryLock)
thread.rwlockReader/writer lock
thread.semaphoreBounded concurrency (acquire, release)
thread.atomicAtomic integer (load, store, add, cas)
thread.poolWorker pool (submit, wait)
thread.schedulerRun a set of functions in sequence
import thread

let mu = thread.mutex.new()

fn safeIncrement() {
    thread.mutex.lock(mu)
    // ... modify shared state ...
    thread.mutex.unlock(mu)
}

Sharing state across VMs

Because spawned tasks (and HTTP requests) run in isolated VMs, share data through the global store in runtime.core:

import runtime
import thread

runtime.core.share("counter", "0")

fn worker() {
    let val = toInt(runtime.core.fetch("counter"))
    runtime.core.share("counter", toString(val + 1))
}

thread.core.spawn(worker)
thread.core.spawn(worker)

Guard read-modify-write sequences with a thread.mutex when correctness under contention matters.