[swift-users] Implicitly capture a mutating self

Richard Wei rxrwei at gmail.com
Fri Dec 16 14:10:39 CST 2016


`sync` is not escaping. Shadow copy causes the device memory to make a copy, which can’t be a solution either. I’ll file a radar.

> Note that, independently, this part looks fishy:
> 
>> try! fill<<<(blockSize, blockCount)>>>[
>>            .pointer(to: &self)
> 
> UnsafePointers formed by passing an argument inout are not valid after the called function returns, so if this function is forming and returning a pointer, it will likely result in undefined behavior. You should use `withUnsafePointer(&self) { p in ... }` to get a usable pointer.

This part is a semi-"type safe” wrapper to CUDA kernel launcher. The purpose is to make explicit which argument gets passed to the kernel as a pointer; in this case, self is a `DeviceArray`. `.pointer` is a factory method under `KernelArgument`. Since most arguments to the kernel are passed in by pointers, IMO using a bunch of `withUnsafe...` clauses would only make it look unnecessarily clumsy.

-Richard

> On Dec 16, 2016, at 12:41, Joe Groff <jgroff at apple.com> wrote:
> 
> 
>> On Dec 15, 2016, at 11:46 PM, Richard Wei via swift-users <swift-users at swift.org> wrote:
>> 
>> Hi,
>> 
>> Swift 3.0.2 seems to have broken my code due to mutating self capture. But I have to pass inout self to the closure. Any workaround?
>> 
>>    let blockSize = min(512, count)
>>    let blockCount = (count+blockSize-1)/blockSize
>>    device.sync { // Launch CUDA kernel
>>        try! fill<<<(blockSize, blockCount)>>>[
>>            .pointer(to: &self), .value(value), .value(Int64(count))
>>        ]
>>    }
> 
> This looks like a compiler bug. Assuming `sync`'s closure is not @escaping, it should be allowed to capture self. If you haven't yet, would you be able to file a bug at bugs.swift.org? Does making a shadow copy work as a workaround, something like:
> 
> var tmpSelf = self
> device.sync {... &tmpSelf ...}
> self = tmpSelf
> 
> Note that, independently, this part looks fishy:
> 
>> try! fill<<<(blockSize, blockCount)>>>[
>>            .pointer(to: &self)
> 
> UnsafePointers formed by passing an argument inout are not valid after the called function returns, so if this function is forming and returning a pointer, it will likely result in undefined behavior. You should use `withUnsafePointer(&self) { p in ... }` to get a usable pointer.
> 
> -Joe



More information about the swift-users mailing list