Deprecating ManagedBufferPointer

The purpose of ManagedBufferPointer is to create a buffer with a custom class-metadata to be able to implement a custom deinit (e.g. to destroy the tail allocated elements).
It was used in Array (before I replaced it with the new tail-allocated-array-built-ins). But now it’s not used anymore in the standard library.

As a replacement for ManagedBufferPointer one can just derive a class from ManagedBuffer and implement the deinit in the derived class.

final class MyBuffer : ManagedBuffer<MyHeader, MyElements> {
  deinit {
    // do whatever needs to be done
  }
}

// creating MyBuffer:
let b = MyBuffer.create(minimumCapacity: 27, makingHeaderWith: { myb in return MyHeader(...) })

IMO ManagedBuffer is much cleaner than ManagedBufferPointer (it doesn’t need this custom bufferClass to be passed to the constructor). Also ManagedBufferPointer doesn’t use SIL tail-allocated arrays internally. Although this is not something visible to the programmer, it makes life easier for the compiler.

So I suggest that we deprecate ManagedBufferPointer.

Erik

+1. I haven’t found use for it, and I don’t think there is one outside of stdlib.

~Robert Widmann

···

On Oct 10, 2016, at 6:12 PM, Erik Eckstein via swift-evolution <swift-evolution@swift.org> wrote:

The purpose of ManagedBufferPointer is to create a buffer with a custom class-metadata to be able to implement a custom deinit (e.g. to destroy the tail allocated elements).
It was used in Array (before I replaced it with the new tail-allocated-array-built-ins). But now it’s not used anymore in the standard library.

As a replacement for ManagedBufferPointer one can just derive a class from ManagedBuffer and implement the deinit in the derived class.

final class MyBuffer : ManagedBuffer<MyHeader, MyElements> {
  deinit {
    // do whatever needs to be done
  }
}

// creating MyBuffer:
let b = MyBuffer.create(minimumCapacity: 27, makingHeaderWith: { myb in return MyHeader(...) })

IMO ManagedBuffer is much cleaner than ManagedBufferPointer (it doesn’t need this custom bufferClass to be passed to the constructor). Also ManagedBufferPointer doesn’t use SIL tail-allocated arrays internally. Although this is not something visible to the programmer, it makes life easier for the compiler.

So I suggest that we deprecate ManagedBufferPointer.

Erik
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

+1

ManagedBuffer has been really useful a couple of times, but I never found a use for ManagedBufferPointer. I can’t even say I’m entirely sure what need it was originally designed to fulfill.

···

On 2016-10-11, at 00:12, Erik Eckstein via swift-evolution <swift-evolution@swift.org> wrote:

The purpose of ManagedBufferPointer is to create a buffer with a custom class-metadata to be able to implement a custom deinit (e.g. to destroy the tail allocated elements).
It was used in Array (before I replaced it with the new tail-allocated-array-built-ins). But now it’s not used anymore in the standard library.

As a replacement for ManagedBufferPointer one can just derive a class from ManagedBuffer and implement the deinit in the derived class.

final class MyBuffer : ManagedBuffer<MyHeader, MyElements> {
  deinit {
    // do whatever needs to be done
  }
}

// creating MyBuffer:
let b = MyBuffer.create(minimumCapacity: 27, makingHeaderWith: { myb in return MyHeader(...) })

IMO ManagedBuffer is much cleaner than ManagedBufferPointer (it doesn’t need this custom bufferClass to be passed to the constructor). Also ManagedBufferPointer doesn’t use SIL tail-allocated arrays internally. Although this is not something visible to the programmer, it makes life easier for the compiler.

So I suggest that we deprecate ManagedBufferPointer.

Erik
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

+1

ManagedBuffer has been really useful a couple of times, but I never
found a use for ManagedBufferPointer. I can’t even say I’m entirely
sure what need it was originally designed to fulfill.

The real need is/was to be able to do the same kind of storage
management in classes not derived from ManagedBuffer. This can be
important for bridging, where the buffers of various native swift
containers need to be derived from, e.g., NSString or NSArray. That is,
however, an extremely stdlib-specifc need.

···

on Tue Oct 11 2016, Károly Lőrentey <swift-evolution@swift.org> wrote:

On 2016-10-11, at 00:12, Erik Eckstein via swift-evolution > <swift-evolution@swift.org> wrote:

The purpose of ManagedBufferPointer is to create a buffer with a custom class-metadata to be able

to implement a custom deinit (e.g. to destroy the tail allocated elements).

It was used in Array (before I replaced it with the new tail-allocated-array-built-ins). But now

it’s not used anymore in the standard library.

As a replacement for ManagedBufferPointer one can just derive a class from ManagedBuffer and implement the deinit in the derived class.

final class MyBuffer : ManagedBuffer<MyHeader, MyElements> {
  deinit {
    // do whatever needs to be done
  }
}

// creating MyBuffer:
let b = MyBuffer.create(minimumCapacity: 27, makingHeaderWith: { myb in return MyHeader(...) })

IMO ManagedBuffer is much cleaner than ManagedBufferPointer (it doesn’t need this custom

bufferClass to be passed to the constructor). Also ManagedBufferPointer doesn’t use SIL
tail-allocated arrays internally. Although this is not something visible to the programmer, it makes
life easier for the compiler.

So I suggest that we deprecate ManagedBufferPointer.

Erik
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
-Dave

I created a proposal: Proposal for removing ManagedBufferPointer by eeckstein · Pull Request #545 · apple/swift-evolution · GitHub

···

On Oct 11, 2016, at 11:32 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Tue Oct 11 2016, Károly Lőrentey <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

+1

ManagedBuffer has been really useful a couple of times, but I never
found a use for ManagedBufferPointer. I can’t even say I’m entirely
sure what need it was originally designed to fulfill.

The real need is/was to be able to do the same kind of storage
management in classes not derived from ManagedBuffer. This can be
important for bridging, where the buffers of various native swift
containers need to be derived from, e.g., NSString or NSArray. That is,
however, an extremely stdlib-specifc need.

On 2016-10-11, at 00:12, Erik Eckstein via swift-evolution >> <swift-evolution@swift.org> wrote:

The purpose of ManagedBufferPointer is to create a buffer with a custom class-metadata to be able

to implement a custom deinit (e.g. to destroy the tail allocated elements).

It was used in Array (before I replaced it with the new tail-allocated-array-built-ins). But now

it’s not used anymore in the standard library.

As a replacement for ManagedBufferPointer one can just derive a class from ManagedBuffer and implement the deinit in the derived class.

final class MyBuffer : ManagedBuffer<MyHeader, MyElements> {
deinit {
   // do whatever needs to be done
}
}

// creating MyBuffer:
let b = MyBuffer.create(minimumCapacity: 27, makingHeaderWith: { myb in return MyHeader(...) })

IMO ManagedBuffer is much cleaner than ManagedBufferPointer (it doesn’t need this custom

bufferClass to be passed to the constructor). Also ManagedBufferPointer doesn’t use SIL
tail-allocated arrays internally. Although this is not something visible to the programmer, it makes
life easier for the compiler.

So I suggest that we deprecate ManagedBufferPointer.

Erik
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

--
-Dave

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

A bit late to this game, because I didn’t fully understand the “point” of ManagedBuffer(Pointer). After a good week of messing around with these in Dictionary/Array/String, I now have Opinions.

I agree ManagedBufferPointer is largely unnecessary. However it’s seeming a lot like ManagedBuffer (and its equivalents) are suboptimal for the standard library’s purposes too!

In particular, pretty much every one of these buffers that I see wants to be a subclass of some NS* collection so that it can be toll-free bridged into objective C. This means that all those types are forced to directly drop down to allocWithTailElems, rather than using a nice abstraction that does it for them. Array does this right now, and I’ve got a PR up for review that’s doing the same thing to the HashedCollections. It’s an outstanding bug that String isn’t doing this (forcing its buffer to be wrapped in another class to be bridged).

I don’t really feel any pain from directly using allocWithTailElems, it’s a great API. It just leaves me at a loss for when I’d reach for ManagedBuffer at all, as it’s very limited.

···

On Oct 13, 2016, at 3:11 PM, Erik Eckstein via swift-evolution <swift-evolution@swift.org> wrote:

I created a proposal: Proposal for removing ManagedBufferPointer by eeckstein · Pull Request #545 · apple/swift-evolution · GitHub

On Oct 11, 2016, at 11:32 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

on Tue Oct 11 2016, Károly Lőrentey <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

+1

ManagedBuffer has been really useful a couple of times, but I never
found a use for ManagedBufferPointer. I can’t even say I’m entirely
sure what need it was originally designed to fulfill.

The real need is/was to be able to do the same kind of storage
management in classes not derived from ManagedBuffer. This can be
important for bridging, where the buffers of various native swift
containers need to be derived from, e.g., NSString or NSArray. That is,
however, an extremely stdlib-specifc need.

On 2016-10-11, at 00:12, Erik Eckstein via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The purpose of ManagedBufferPointer is to create a buffer with a custom class-metadata to be able

to implement a custom deinit (e.g. to destroy the tail allocated elements).

It was used in Array (before I replaced it with the new tail-allocated-array-built-ins). But now

it’s not used anymore in the standard library.

As a replacement for ManagedBufferPointer one can just derive a class from ManagedBuffer and implement the deinit in the derived class.

final class MyBuffer : ManagedBuffer<MyHeader, MyElements> {
deinit {
   // do whatever needs to be done
}
}

// creating MyBuffer:
let b = MyBuffer.create(minimumCapacity: 27, makingHeaderWith: { myb in return MyHeader(...) })

IMO ManagedBuffer is much cleaner than ManagedBufferPointer (it doesn’t need this custom

bufferClass to be passed to the constructor). Also ManagedBufferPointer doesn’t use SIL
tail-allocated arrays internally. Although this is not something visible to the programmer, it makes
life easier for the compiler.

So I suggest that we deprecate ManagedBufferPointer.

Erik
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

--
-Dave

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

A bit late to this game, because I didn’t fully understand the “point” of ManagedBuffer(Pointer). After a good week of messing around with these in Dictionary/Array/String, I now have Opinions.

I agree ManagedBufferPointer is largely unnecessary. However it’s seeming a lot like ManagedBuffer (and its equivalents) are suboptimal for the standard library’s purposes too!

In particular, pretty much every one of these buffers that I see wants to be a subclass of some NS* collection so that it can be toll-free bridged into objective C. This means that all those types are forced to directly drop down to allocWithTailElems, rather than using a nice abstraction that does it for them. Array does this right now, and I’ve got a PR up for review that’s doing the same thing to the HashedCollections. It’s an outstanding bug that String isn’t doing this (forcing its buffer to be wrapped in another class to be bridged).

I don’t really feel any pain from directly using allocWithTailElems, it’s a great API. It just leaves me at a loss for when I’d reach for ManagedBuffer at all, as it’s very limited.

I think we can implement a replacement for ManagedBufferPointer. But it would have a different API. Something like that:

public struct ManagedBufferPointer2<StorageClass: AnyObject, Element> {

  public init(minimumCapacity: Int,
              initWith factory: (StorageClass) throws -> ()
  ) rethrows {
    buffer = Builtin.allocWithTailElems_1(
         StorageClass.self, minimumCapacity._builtinWordValue, Element.self)
    try factory(buffer)
  }
  // ...
  let buffer: StorageClass
}

···

On Oct 19, 2016, at 3:28 PM, Alexis <abeingessner@apple.com> wrote:

On Oct 13, 2016, at 3:11 PM, Erik Eckstein via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I created a proposal: Proposal for removing ManagedBufferPointer by eeckstein · Pull Request #545 · apple/swift-evolution · GitHub

On Oct 11, 2016, at 11:32 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

on Tue Oct 11 2016, Károly Lőrentey <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

+1

ManagedBuffer has been really useful a couple of times, but I never
found a use for ManagedBufferPointer. I can’t even say I’m entirely
sure what need it was originally designed to fulfill.

The real need is/was to be able to do the same kind of storage
management in classes not derived from ManagedBuffer. This can be
important for bridging, where the buffers of various native swift
containers need to be derived from, e.g., NSString or NSArray. That is,
however, an extremely stdlib-specifc need.

On 2016-10-11, at 00:12, Erik Eckstein via swift-evolution >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The purpose of ManagedBufferPointer is to create a buffer with a custom class-metadata to be able

to implement a custom deinit (e.g. to destroy the tail allocated elements).

It was used in Array (before I replaced it with the new tail-allocated-array-built-ins). But now

it’s not used anymore in the standard library.

As a replacement for ManagedBufferPointer one can just derive a class from ManagedBuffer and implement the deinit in the derived class.

final class MyBuffer : ManagedBuffer<MyHeader, MyElements> {
deinit {
   // do whatever needs to be done
}
}

// creating MyBuffer:
let b = MyBuffer.create(minimumCapacity: 27, makingHeaderWith: { myb in return MyHeader(...) })

IMO ManagedBuffer is much cleaner than ManagedBufferPointer (it doesn’t need this custom

bufferClass to be passed to the constructor). Also ManagedBufferPointer doesn’t use SIL
tail-allocated arrays internally. Although this is not something visible to the programmer, it makes
life easier for the compiler.

So I suggest that we deprecate ManagedBufferPointer.

Erik
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

--
-Dave

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

May be totally wrong about this but I always thought that ManagedBuffer(Pointer) would be really useful in conjunction w/ Metal. In particular, MTLBuffer gives you a region of memory that is in common configurations shared btwn the CPU and GPU. I believe the idea is you write your vertex data or textures or whatever into that region, which you then associate with a particular command you issue to the GPU.

-Colin

···

On Oct 19, 2016, at 6:28 PM, Alexis via swift-evolution <swift-evolution@swift.org> wrote:

A bit late to this game, because I didn’t fully understand the “point” of ManagedBuffer(Pointer). After a good week of messing around with these in Dictionary/Array/String, I now have Opinions.

I agree ManagedBufferPointer is largely unnecessary. However it’s seeming a lot like ManagedBuffer (and its equivalents) are suboptimal for the standard library’s purposes too!

In particular, pretty much every one of these buffers that I see wants to be a subclass of some NS* collection so that it can be toll-free bridged into objective C. This means that all those types are forced to directly drop down to allocWithTailElems, rather than using a nice abstraction that does it for them. Array does this right now, and I’ve got a PR up for review that’s doing the same thing to the HashedCollections. It’s an outstanding bug that String isn’t doing this (forcing its buffer to be wrapped in another class to be bridged).

I don’t really feel any pain from directly using allocWithTailElems, it’s a great API. It just leaves me at a loss for when I’d reach for ManagedBuffer at all, as it’s very limited.

On Oct 13, 2016, at 3:11 PM, Erik Eckstein via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I created a proposal: Proposal for removing ManagedBufferPointer by eeckstein · Pull Request #545 · apple/swift-evolution · GitHub

On Oct 11, 2016, at 11:32 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

on Tue Oct 11 2016, Károly Lőrentey <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

+1

ManagedBuffer has been really useful a couple of times, but I never
found a use for ManagedBufferPointer. I can’t even say I’m entirely
sure what need it was originally designed to fulfill.

The real need is/was to be able to do the same kind of storage
management in classes not derived from ManagedBuffer. This can be
important for bridging, where the buffers of various native swift
containers need to be derived from, e.g., NSString or NSArray. That is,
however, an extremely stdlib-specifc need.

On 2016-10-11, at 00:12, Erik Eckstein via swift-evolution >>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The purpose of ManagedBufferPointer is to create a buffer with a custom class-metadata to be able

to implement a custom deinit (e.g. to destroy the tail allocated elements).

It was used in Array (before I replaced it with the new tail-allocated-array-built-ins). But now

it’s not used anymore in the standard library.

As a replacement for ManagedBufferPointer one can just derive a class from ManagedBuffer and implement the deinit in the derived class.

final class MyBuffer : ManagedBuffer<MyHeader, MyElements> {
deinit {
   // do whatever needs to be done
}
}

// creating MyBuffer:
let b = MyBuffer.create(minimumCapacity: 27, makingHeaderWith: { myb in return MyHeader(...) })

IMO ManagedBuffer is much cleaner than ManagedBufferPointer (it doesn’t need this custom

bufferClass to be passed to the constructor). Also ManagedBufferPointer doesn’t use SIL
tail-allocated arrays internally. Although this is not something visible to the programmer, it makes
life easier for the compiler.

So I suggest that we deprecate ManagedBufferPointer.

Erik
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

--
-Dave

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Just for posterity's sake, ManagedBufferPointer still has a use case. It's exactly the scenario I described here:

My family of managed buffers needs a common base class so I can implement type-erased operations. Thus, I can't use ManagedBuffer itself.

1 Like

Are you still of the same opinion? I wonder why Deque's implementation uses ManagedBufferPointer...

No -- this thread is from 2016; few opinions survive that long. :older_man:t2:

Deque uses ManagedBufferPointer so that it can implement a shared empty singleton with type punning. This is roughly the same use case that Dave mentioned three years ago.

ManagedBuffer and ManagedBufferPointer both have unnecessarily unpleasant interfaces, and we can do (and Swift programmers deserve) so much better.

But of these two types, ManagedBufferPointer is probably sitting ever so slightly closer to what would be a better replacement. One big contributor to ManagedBuffer's unpleasantness is the way it pollutes the member namespace of the class -- even clobbering desirable names, such as capacity. In data structure internals, we often cannot avoid dealing with references to the storage object, and these prominent, non-hidable members are inviting accidental misuse, or layering violations.

(Note: at this point, I think it'd be best to wait with the overhaul until non-copyable types (and, probably more crucially, related language improvements such as borrowing/consuming) are usable, and until we have gained enough experience with them to learn their limits. It would be a shame to add alternative API only to regret and rework it again soon after. Meanwhile, specialized packages can experiment with alternative formulations to propose later.)

9 Likes