Last active
December 18, 2020 04:55
-
-
Save DougGregor/59efedbf3e1cd047b04db6ff5e5a5737 to your computer and use it in GitHub Desktop.
Actor counters example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if canImport(Darwin) | |
import Darwin | |
#elseif canImport(Glibc) | |
import Glibc | |
#endif | |
actor class Counter { | |
private var value = 0 | |
private let scratchBuffer: UnsafeMutableBufferPointer<Int> | |
init(maxCount: Int) { | |
scratchBuffer = .allocate(capacity: maxCount) | |
} | |
deinit { | |
scratchBuffer.deallocate() | |
} | |
func next() async -> Int { | |
let current = value | |
// Make sure we haven't produced this value before | |
assert(scratchBuffer[current] == 0) | |
scratchBuffer[current] = 1 | |
value = value + 1 | |
return current | |
} | |
} | |
func worker( | |
identity: Int, counters: [Counter], numIterations: Int | |
) async { | |
for i in 0..<numIterations { | |
let counterIndex = Int.random(in: 0 ..< counters.count) | |
let counter = counters[counterIndex] | |
let nextValue = await counter.next() | |
print("Worker \(identity) calling counter \(counterIndex) produced \(nextValue)") | |
} | |
} | |
func runTest(numCounters: Int, numWorkers: Int, numIterations: Int) async { | |
// Create counter actors. | |
var counters: [Counter] = [] | |
for i in 0..<numCounters { | |
counters.append(Counter(maxCount: numWorkers * numIterations)) | |
} | |
// Create a bunch of worker threads. | |
var workers: [Task.Handle<Void>] = [] | |
for i in 0..<numWorkers { | |
workers.append( | |
Task.runDetached { | |
usleep(UInt32.random(in: 0..<100) * 1000) | |
await worker( | |
identity: i, counters: counters, numIterations: numIterations | |
) | |
} | |
) | |
} | |
// Wait until all of the workers have finished. | |
for worker in workers { | |
await try! worker.get() | |
} | |
print("DONE!") | |
} | |
runAsyncAndBlock { | |
await runTest(numCounters: 10, numWorkers: 100, numIterations: 1000) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment