Semaphore
A Semaphore from std/sync limits the number of concurrent accesses to a resource. sem_new(n) creates a semaphore with n permits, sem_acquire takes a permit (blocking if none available), and sem_release returns one.
Code
// Semaphore — limiting concurrent access to a resource
// Semáforo — limitar acceso concurrente a un recurso
import "std/sync"
var sem: Semaphore = sem_new(2)
var done: WaitGroup = wg_new()
fn access_resource() -> int {
sem_acquire(sem)
print("acquired (count: " + int_to_string(sem_count(sem)) + ")")
sleep(50)
sem_release(sem)
print("released")
wg_done(done)
return 0
}
fn main() -> int {
// Allow at most 2 concurrent accesses
wg_add(done, 5)
var i: int = 0
while i < 5 {
thread_spawn(access_resource)
i = i + 1
}
wg_wait(done)
print("all done")
return 0
}
Output
acquired (count: 1) acquired (count: 0) released released acquired (count: 1) acquired (count: 0) released released acquired (count: 1) released all done
Explanation
sem_new(2) creates a semaphore with 2 permits. At most 2 threads can hold a permit simultaneously. When a third thread calls sem_acquire, it blocks until one of the first two calls sem_release.
Five threads compete for the semaphore. sem_count returns the number of remaining permits, which drops to 0 when both are taken. After sleeping 50ms (simulating work), each thread releases its permit and signals the WaitGroup.
This pattern is useful for rate-limiting access to external resources like database connections, file descriptors, or API endpoints where you want controlled concurrency rather than full mutual exclusion.