Hi Karoy,
I remain super excited about this, I have use-case that I'd love to adopt this in now, I wish it were already shipping . I hope it can fit into the preview package someday.
Here are my thoughts w.r.t. the "2020-03-30/2" version. I'm sorry but I haven't read all the upthread comments:
-
Thank you for splitting the background information out to a separate file, it makes it much easier to read the proposal. I appreciate it!
-
I agree that Atomics should be a separate module but included as part of the standard compiler distro like the Swift module.
-
I love unification under a new singular
UnsafeAtomic
generic type, this is great. -
I think the name should still capture that it is reference-y. Something like
UnsafeAtomicPointer
orUnsafeAtomicReference
orUnsafePointerToAtomic
seems like it would make more room for the ownership-enabled future where we could have a non-reference version of the same thing. -
This naming issue is even more pressing if you intend to introduce a pattern that is followed by higher level types like mutexes etc. It is practical to use an extra layer of pointer indirection in the immediate future, but we really need to be set up to be able to eliminate this in the future.
-
I have a couple of concerns about
UnsafeAtomicLazyReference
: the notion of "lazily initializable but otherwise read-only" is orthogonal from the idea of atomics, and orthogonal from the idea of an object reference, why tie all of these together? In terms of rationale, why can't this be done with the existing types? Could this type be split out to a smaller and more focused proposal? -
Perhaps this is just a writing thing but I'd recommend the " The Atomics Module" section include a few examples using optionals and IUOs with the pointer type. If this isn't supported, it should be.
-
Did you consider a design that makes the unsafe pointer shenanigans be owned by the caller? This could be an optional different mode, but it would mean that pretty much everything would be exposed as a static member as well as an instance member. For example, your AtomicCounter example has a separately allocated atomic, which is unnecessarily wasteful. It would be great if it could be written as something like this instead:
class AtomicCounter {
private var _value = 0
init() {
UnsafeAtomic<Int>.initialize(address: &_value, to: 0)
}
deinit {
_value.destroy(address: &_value)
}
func increment() {
UnsafeAtomic<Int>.wrappingIncrement(address: &_value, by: 1, ordering: .relaxed)
}
func get() -> Int {
UnsafeAtomic<Int>.load(address: &_value, ordering: .relaxed)
}
}
This API is yuckier to use of course, but is an acceptable loss to get better performance in the low-level code that this API is designed for, and it seems to compose directly on top of your existing protocol design. Ownership should come along and make this much nicer some day, and people who don't mind the indirection can use the API as proposed.
Overall, I'm really excited to see progress in this area, thank you for driving this forward!!
-Chris