Inline class storage

I apologise if that's my search skills that failed me, but I nevertheless couldn't find a direct explanation why one can't manually allocate class instances, so I would like to ask it here.

Basically, sometimes one wants to manually allocate storage for better cache hits and so on, but AFAIK, in Swift, it's only possible to do this with structs via pointer or ManagedBuffer APIs. Attempting to do it with classes would instead store a buffer of essentially pointers instead of the actual storage. Is it possible to eventually have such mechanism for class instances too? Or is it already there, and it's just me not knowing about it?

From my understanding, class storage sometimes does get inlined (if an instance does not outlive a function's scope, for example), but otherwise from what I know, class instances are allocated by the runtime by using the C++'s new operator. Is it ARC that prohibits other mechanisms? Can one hope to eventually have a type akin to Unmanaged<T> that would allow the use custom allocators for class storage?

1 Like

Yes, first of all ARC does not support this. But also it is a matter of semantics. Class instances in Swift are assumed to be individually reference counted, and deinit must be called when reference count drops to zero. So if you are allocating several class instances in a block, you can have a situation when some of the instances are already deinitiazed, but some are still alive and the entire block of memory still needs to be held. Is this the semantics you need?

It is not impossible to decouple object semantical lifetime from memory management. And it is already happening with unowned references - class instance without strong references, but with unowned ones, will be deinitialised, but memory will not be freed until last unowned reference is gone. But that's pretty uncommon use case, and I suspect implementing it may come with a penalty for more common ones. And also implementing it at this stage would be an ABI-breaking change. So, I would not expect this to be implemented in the language runtime in the nearest future.

Yes. My problem is that if some API decides to vend a class type, I'm basically locked into cache-unfriendly heap allocation, and there's no known to me mechanism to allocate the storage of many such instances contiguously if I ever need to iterate through them in a tight loop or perform any offset-based accesses. So right, I'm interested in a very manual way to create a buffer, put my objects into it, set their reference counts to 1 and release them and the buffer whenever I myself decide.

It's unfortunate to hear that this is unrealistic. :confused:

If you're willing to hop another indirection, you can allocate a struct storage (as you outlined above), then (unsafely) reference it using class.

It's sadly the other way around for me: I want to be able to allocate storage that already has been defined as class by API that I don't control (say, UIView). The only imaginable thing that comes close to what I want is to create an object, Unmanaged.passUnretained().toOpaque it, memcpy the storage and Unmanaged.fromOpaque() it back, but even then I don't know neither the size/stride of the storage, nor if it has a value witness table pointer at the -1 offset attached to it. :man_shrugging:t3:

Yea, if you don't know the size of the storage, likely neither does the compiler (classes can be subclassed). So I'm not sure how you could do it. passUnretained would just pass around the references, not the storage.

Rather then trying to solve this technically, it might be more effective to contact API authors and ask them to change it.

Terms of Service

Privacy Policy

Cookie Policy