New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SR-3087] No way to arbitrarily initialise an Array's storage #45677
Comments
Just a clarification: this is not really about pre-allocated storage, but about being able to tell the array "please allocate the memory and let me (unsafely) initialize the elements" |
Okay, updated the description. It would be nice to be able to wrap a contiguously-stored block of elements as a bona-fida Array, though. Ensuring no other mutation-enabling pointers to the memory exist would be an issue, though - is that something which could be achievable with a memory-ownership model? |
You could imagine a way for a ContigiouslyStored to guarantee its buffer-pointer will have capacity for n elements, and that n elements will be initialised after mutating. protocol UnsafelyInitialisable: ContiguouslyStored {
// - The given buffer pointer promises to have capacity for at least `count` elements
// - The `perform` closure promises that `count` elements will be initialised when it returns
mutating func withUnsafeMutableBufferPointer<T>(count: Int, perform: (UnsafeMutableBufferPointer<Element>)->T) -> T
} It fits the requirement that we initialise the type's native buffer in-place, not copying from an existing buffer. Not making it an initialiser means we could also unsafely re-initialise slices of an Array, possibly changing its length. |
This might need a new builtin that produces an indeterminate (undef) of some trivial type. By extension it could produce an indeterminate tuple of trivial types. |
One extension to the stdlib I could imagine being helpful is a way to "unpack" an UnsafeMutableBufferPointer<T> for the case when T.stride != T.size. For example, it might be cool to initialise an Array directly from a file: var a = Array<T>()
a.withUnsafeMutableBufferPointer(count: 3) { ptr in
let r = read(fd, UnsafeRawPointer(ptr.baseAddress), MemoryLayout<T>.size * 3)
guard r == (MemoryLayout<T>.size * 3) else { throw OhNoError }
ptr.unpack(count: 3) // Iterates backwards from (MemoryLayout<T>.size * n), moving items to (MemoryLayout<T>.stride * n).
}
// Go walking off in to the sunshine with an Array<T>... |
Additional Detail from JIRA
md5: 78d2891e46bb0f408db15202b1a1b736
relates to:
Issue Description:
The standard library does not currently expose a way to allocate an Array's storage and (unsafely) initialise its elements, as we can with UnsafeMutablePointer.
An example use-case is to implement a concurrent map. See: https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20161024/003769.html
Even though we expose a UMP from Array, it cannot be used to unsafely initialise the Array elements.
The workaround at the moment is to allocate a UMP, initialise its elements unsafely, and then copy the contents in to an Array via the Array(Sequence) constructor, which is less than optimal.
The text was updated successfully, but these errors were encountered: