--
← Back to blog
Concurrency in NSL: Async, Channels, and Parallelism

Concurrency in NSL: Async, Channels, and Parallelism

Async / Await

Define async procedures and await their results:

async :: fetch_data(url) ->
    let response = http.get(url)
    return json.parse(response.body)

let data = await fetch_data("https://api.example.com/users")
print(data)

Wait with Timeout

let result = wait fetch_data(url) within 5s

If the operation does not complete within 5 seconds, it times out.

Parallel Execution

Run multiple tasks concurrently and wait for all to complete:

let results = wait all [
    fetch_data("https://api.example.com/users"),
    fetch_data("https://api.example.com/posts"),
    fetch_data("https://api.example.com/comments")
]
let [users, posts, comments] = results

Race

Wait for the first task to complete:

let fastest = wait any [
    fetch_from_server_a(),
    fetch_from_server_b()
]

Spawn

Launch a task that runs in the background:

let task = spawn heavy_computation(data)
# ... do other work ...
let result = await task

Channels

Communicate between concurrent tasks with typed channels:

let ch = channel of [string]()

# Producer
spawn fn() =>
    send "hello" to ch
    send "world" to ch

# Consumer
let msg1 = receive from ch
let msg2 = receive from ch
print(f"{msg1} {msg2}")  # "hello world"

Select (Channel Multiplexing)

Wait on multiple channels simultaneously:

let data_ch = channel of [string]()
let done_ch = channel of [bool]()

select
    case msg = receive from data_ch
        print(f"Got data: {msg}")
    case receive from done_ch
        print("Done!")
    otherwise
        print("No messages ready")

Parallel Block

Run a set of tasks in parallel:

parallel
    process_chunk(data[0..100])
    process_chunk(data[100..200])
    process_chunk(data[200..300])

Synchronized Execution

sync
    # This block runs atomically
    balance -= amount
    log_transaction(amount)
All Posts