ibex10
1
I am using a semaphore and a Task to hibernate, that is, to pause the execution, in the non-async send function below. I do this because sending takes variable time in real life.
actor DeviceProxy {
var state = State ()
// non-reentrant, there are no suspension points
func enqueue (seq: Int msg: Message) {
let pstate = state
send (msg)
state.inspect (seq, pstate)
assert (pstate == state)
state.counter += 1
}
// Simulate sending
// non-reentrant, there are no suspension points
func send (_ msg: Message) {
// simulate real-life, sending takes variable time
let sem = DispatchSemaphore (value: 0)
Task {
let range = 0...7
let s = Int.random (in: range)
await hibernate (seconds: s)
sem.signal()
}
sem.wait()
}
}
func hibernate (seconds: Int) async {
let s = UInt64 (1_000_000_000 * seconds)
try! await Task.sleep (nanoseconds: s)
}
struct State {
var counter = 0
func inspect (_ seq: Int, _ before: State) {
let ss = String (format: "%2d", seq)
let bs = String (format: "%2d", before.counter)
let cs = String (format: "%2d", counter)
print (ss, "state: before", bs, "after", cs, before.counter != counter ? "changed" : "")
}
static func == (_ u: State, _ v: State) -> Bool {
u.counter == v.counter
}
}
I have a feeling that this is not the right way to go. How would this be done correctly?
vns
2
If that's a test code, Thread.sleep might be fine, as I understand that's the intention anyway. Less intrusive than a semaphore at least.