import Foundation
// AsyncSemaphore Actor
actor AsyncSemaphore {
private var value: Int
private var waiters: [CheckedContinuation<Void, Never>] = []
init(value: Int) {
self.value = value
}
func wait() async {
await withCheckedContinuation { continuation in
if self.value > 0 {
self.value -= 1
continuation.resume()
} else {
self.waiters.append(continuation)
}
}
}
func signal() {
if !waiters.isEmpty {
let continuation = waiters.removeFirst()
continuation.resume()
} else {
self.value += 1
}
}
}
// Image creation simulation
func createImage(index: Int) async {
print("Creating image \(index)")
// Simulate I/O-bound image creation
let startTime = Date()
let waitTime = Double.random(in: 0.75...1.5)
while Date().timeIntervalSince(startTime) < waitTime {
// Busy-wait to simulate I/O-bound work
}
print("Finished creating image \(index)")
}
// Image processing simulation
func processImage(index: Int) async {
print("Processing image \(index)")
// Simulate CPU-bound image processing
let startTime = Date()
let waitTime = Double.random(in: 0.75...2.0)
while Date().timeIntervalSince(startTime) < waitTime {
// Busy-wait to simulate CPU-bound work
}
print("Finished processing image \(index)")
}
func processImages(totalCount: Int, maxConcurrent: Int) async {
let semaphore = AsyncSemaphore(value: maxConcurrent)
await withTaskGroup(of: Void.self) { group in
for i in 0..<totalCount {
group.addTask {
await semaphore.wait()
await createImage(index: i)
await semaphore.signal()
}
}
// Wait for all images to be created
await group.waitForAll()
for i in 0..<totalCount {
group.addTask {
await semaphore.wait()
await processImage(index: i)
await semaphore.signal()
}
}
}
print("All images processed")
}
// Entry point
print("Running Image Processing Example (with concurrency-limiting):")
// Create a semaphore to wait for the async task to complete
let completionSemaphore = DispatchSemaphore(value: 0)
Task {
await processImages(totalCount: 20, maxConcurrent: 4)
completionSemaphore.signal()
}
// Wait for the async task to complete
completionSemaphore.wait()
print("Done")