[swift-users] Chaining struct-mutating funcs

Fritz Anderson fritza at manoverboard.org
Tue Aug 9 20:13:15 CDT 2016

I’m sending directly to those who took time over my question, because, per Michael’s request, I have a minimal case to attach. Phrases in boldface are for skimmability, not shouting. 

Strip out my use case (I’m encouraged that Dave recapitulated exactly what I was asking about). My remaining question is: How do you safely reuse a class reference as the backing store for a struct? Yes, it’s done all the time, but the trick requirement is that I want to chain the funcs that do it; chained value returns are immutable; and as far as I could tell, you can’t get CoW-safe reuse without mutating self. The result is that you are forced to make expensive copies of the backing store every time. Joe’s solution looked promising in that it purported to pass the CoW buffer (if possible) out of the func after doing all the mutation internally.

I couldn’t figure out how the answer Joe gave could work: His code duplicates the struct’s original reference into a copy of the struct, after which he expects the runtime to report (when possible) that no such duplicate exists. I asked how this could be, as my attempt to replicate in a playground showed the reference was never found unique — which is what I had intuitively expected.

He says this fundamental design pattern in Swift works only if you change the semantics of the language by turning on the optimizer. (Sorry to be all Asperger's about it, but nobody corrected me the first time I put it this way.)

I have many, many questions, I might even hazard objections, but they’re moot: Optimized or not, that code never reuses the backing object. 

The attached project was built with Xcode 8.0b5. It uses Joe’s code (except I still must use isUniquelyReferencedNonObjC(_:)). I run addInts(x:, y:) and check two ways whether the reference was found unique. Same result, optimized or not.

It occurred to me that the globals s_x  and s_y might bump the reference count. I removed them and used this instead:

let s_result = addInts(x: S(c: C(value: 99)), y: S(c: C(value: -98)))

Still no unique references.

I recognize I am taking up a lot of god time mere days before a major release, when the likeliest outcome is that I’m a jackass. My concern runs deeper than what’s in this message, but I shouldn't muddy the waters. Those deeper things can go back to the public once I understand the issue better (or you boot me back).


Context (supplementary, no need to spend time)

If seeing what I’m trying to do helps, I’ve attached my attempt. I’m sure there are defects in API style, safety, and correctness. I’d have done more if I hadn’t suspended the project over this issue. Class FloatBuffer is the backing store; ManagedFloatBuffer is the wrapper class that does all the operations. None of the operations are declared mutating. 

Anything that calls (unary|binary)Operator returns a fresh ManagedFloatBuffer every time; structs and their buffers are created and initialized every time — intentionally. It seems to work well under gentle use.

Callers of mutabilityWrapper preserve the receiver’s backing buffer whenever possible and mutate it in-place. Those funcs always return self. These might be a big win; I can’t tell because I’ve never been able to get unique references. Because there’s an allocation (possibly initialization) every time, they are no better than the (unary|binary)Operator funcs. malloc and friends take up a significant amount of time on the scale of vector math.

Both flavors can cascade; the only problem is that the “in-place” methods don’t live up to the name.

	— F

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160809/dd95ed68/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: structs-and-refs.zip
Type: application/zip
Size: 33305 bytes
Desc: not available
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160809/dd95ed68/attachment.zip>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160809/dd95ed68/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ManagedFloatBuffer.swift
Type: application/octet-stream
Size: 23717 bytes
Desc: not available
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160809/dd95ed68/attachment.obj>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160809/dd95ed68/attachment-0002.html>

More information about the swift-users mailing list