(Am I not holding this right? I hope I'm mistaken...)
Per [SE-410], Synchronization Atomic in Swift 6 is ~Copyable.
But atomics are often used in teams, e.g., producer-consumer pairs. Building a library to produce validly-configured teams (to make their use correct-by-construction), I'd like the client to provide an atomic value and the library would return the team members e.g., the producer and consumer. But ~Copyable seems to make it impossible to produce distinct team members, since it can only be consumed once.
(At best I can create one component as a god-class knowing everything about all team members, possibly including client-specific per-state tracking, and showing distinct faces via (slow) protocols - yuck.)
I understand how ~Copyable move-only types can help in other situations to maintain singular ownership, but isn't the goal of an atomic to be used from multiple contexts?
So what can I do to make code like the following work in the current 6.0 toolchains? Am I missing some way to copy refer to the same underlying atomic? (~Copyable requires any container to be ~Copyable.)
enum MagicLib {
static func demo() {
let a = Atomic(0)
let rw = rw(a)
// now go do something with them...
_ = consume rw.read
_ = consume rw.write
}
static func rw(_ a: consuming Atomic<Int>) -> RW {
// error here: consumed twice
RW(read: Read(a: a), write: Write(a: a))
}
struct RW: ~Copyable {
let read: Read
let write: Write
}
struct Read: ~Copyable {
public let a: Atomic<Int>
public func read() -> Int {
a.load(ordering: .sequentiallyConsistent) + 1
}
}
struct Write: ~Copyable {
public let a: Atomic<Int>
public func write(_ a: Int) {
self.a.store(a - 1, ordering: .sequentiallyConsistent)
}
}
}
[SE-410 acceptance] https://forums.swift.org/t/accepted-with-modifications-se-0410-atomics/69244