Skip to content

Instantly share code, notes, and snippets.

@atrick
Last active October 5, 2017 06:12
Show Gist options
  • Save atrick/59dd12c24b742ca7c29a2b04cd0dd637 to your computer and use it in GitHub Desktop.
Save atrick/59dd12c24b742ca7c29a2b04cd0dd637 to your computer and use it in GitHub Desktop.

SE-0184 Part 2 (recomend splitting into a follow-up proposal): Buffer Full vs. Partial Initialization.

Buffer Memory State

struct UnsafeMutableBufferPointer<Element> 
{
    func initialize<S : Sequence>(from: S) -> (S.Iterator, Index) where S.Element == Element

// Amended: Remove the `at` label on all buffer APIs. Only support full initialization/assignment/deinitialization.
// Amended: Remove the unsafe overloads. Source is a Sequence.
// precondition: self.count == number of elements
+++ func initializeAll<S : Sequence>(from:S) where S.Element == Element
+++ func assignAll<S : Sequence>(from:S) where S.Element == Element

+++ func moveInitializeAll(from:UnsafeMutableBufferPointer<Element>)
+++ func moveAssignAll(from:UnsafeMutableBufferPointer<Element>)

// Note: There are many alternative names for these `All` APIs. We
// will bike-shed this on the public evolution list.

// Amended: Remove both the `at` and `count` arguments.
+++ func deinitializeAll()

// Note: I've added the `All` suffix here for clarity, but it's likely
// that we don't need it. It does serve two purposes: avoid confusion
// with the Swift 3/4 APIs that partially initialize, and avoid
// confusion with the non-buffer APIs.
// However, we need this buffer API to be identical to its slice API--they
// will both conform to the same protocol. We really don't need the `All`
// suffix on the Slice API.

--- func initialize<S: Sequence>(from source: S) -> (S.Iterator, Index)
---    where S.Element == Element
+++ func initializeAtStart<S: Sequence>(from source: S) -> (S.Iterator, Index)
+++    where S.Element == Element

// Note: Many alternative names for "initializeAtStart" have been suggested.
// We haven't settled.
}

struct UnsafeMutableRawBufferPointer 
{
    func initializeMemory<S: Sequence>(
      as: S.Element.Type, from: S
    ) -> (unwritten: S.Iterator, initialized: UnsafeMutableBufferPointer<S.Element>)

// Amended: Remove the `atByteOffset` label on all buffer APIs. Only support full initialization/assignment/deinitialization.
// Amended: Remove the unsafe overloads. Source is a Sequence.
// Amended: Rename to `initializeAllMemory` to avoid a conflict with the old partial `initializeMemory(from:)`.
// precondition: self.count == MemoryLayout<T>.stride * number of elements
+++ func initializeAllMemory<S: Sequence>(as:S.Element.Type, from:S) -> UnsafeMutableBufferPointer<T>

+++ func moveInitializeAllMemory<T>(as:T.Type, from:UnsafeMutableBufferPointer<T>) -> UnsafeMutableBufferPointer<T> 

// Add a precondition: self.count == source.count
// Add an overload for UnsafeMutableRawBufferPointer source.
+++ func copyAllMemory(from:UnsafeRawBufferPointer)
+++ func copyAllMemory(from:UnsafeMutableRawBufferPointer)

// Note: If we keep the `All` names for initialize/assign, then this could also be `copyAllMemory(from:)`.

--- func initializeMemory<S: Sequence>(
---   as type: S.Element.Type, from source: S
--- ) -> (unwritten: S.Iterator, initialized: UnsafeMutableBufferPointer<S.Element>)
+++ func initializeMemoryAtStart<S: Sequence>(
+++   as type: S.Element.Type, from source: S
+++ ) -> (unwritten: S.Iterator, initialized: UnsafeMutableBufferPointer<S.Element>)

}

Amendment: Introduce the following extensions on MutableRandomAccessSlice. (Note: in practice this will involve introducing a protocol that MutableRandomAccessSlice conforms to and provides enough accessors to perform initialization and assignment).

extension MutableRandomAccessSlice where Base == UnsafeMutableBufferPointer<Element> {
+++ func initialize(repeating:Element)
+++ func assign(repeating:Element)

+++ func initializeAll<S : Sequence>(from:S) where S.Element == Element
+++ func assignAll<S : Sequence>(from:S) where S.Element == Element

+++ func moveInitializeAll(from:UnsafeMutableBufferPointer<Element>)
+++ func moveAssignAll(from:UnsafeMutableBufferPointer<Element>)

// Note: we would like to drop the `All` prefix but this needs to be identical to the buffer API.

+++ func deinitializeAll()

+++ func withMemoryRebound<T, Result>
+++ (to:T.Type, _ body:(UnsafeMutableBufferPointer<T>) -> Result)
}

extension MutableRandomAccessSlice where Base == UnsafeMutableRawBufferPointer {
+++ func initializeAllMemory<S: Sequence>(as:S.Element.Type, from:S) -> UnsafeMutableBufferPointer<T>

+++ func moveInitializeAllMemory<T>(as:T.Type, from:UnsafeMutableBufferPointer<T>) -> UnsafeMutableBufferPointer<T> 

+++ func copyAllMemory(from:UnsafeRawBufferPointer)
+++ func copyAllMemory(from:UnsafeMutableRawBufferPointer)

+++ func deinitializeAll()

+++ func withMemoryRebound<T, Result>
+++ (to:T.Type, _ body:(UnsafeMutableBufferPointer<T>) -> Result)
}

Source compatibility

  • rename copyBytes(from:) to copyMemory(from:)

This change is source breaking but can be trivially automigrated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment