Skip to content

A Counting Semaphore for Swift Concurrency

License

Notifications You must be signed in to change notification settings

colemancda/Semaphore

 
 

Repository files navigation

Semaphore

Semaphore is an object that controls access to a resource across multiple execution contexts through use of a traditional counting semaphore.

Unlike DispatchSemaphore, Semaphore does not block any thread. Instead, it suspends Swift concurrency tasks.

Usage

You can use a semaphore to suspend a task and resume it later:

let semaphore = Semaphore(value: 0)

Task {
    // Suspends the task until a signal occurs.
    await semaphore.wait()
    await doSomething()
}

// Resumes the suspended task.
semaphore.signal()

You can use a semaphore in order to make sure an actor's methods can't run concurrently:

actor MyActor {
    private let semaphore = Semaphore(value: 1)
    
    func serializedMethod() async {
        // Makes sure no two tasks can execute self.serializedMethod() concurrently. 
        await semaphore.wait()
        defer { semaphore.signal() }
        
        await doSomething()
        await doSomethingElse()
    }
}

The wait() method has a waitUnlessCancelled() variant that throws CancellationError if the task is cancelled before a signal occurs.

For a nice introduction to semaphores, see The Beauty of Semaphores in Swift 🚦. The article discusses DispatchSemaphore, but it can easily be ported to Swift concurrency: see the demo playground of this package.

About

A Counting Semaphore for Swift Concurrency

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Swift 100.0%