[swift-corelibs-dev] driving writev(2) from DispatchData
Johannes Weiss
johannesweiss at apple.com
Tue Apr 25 06:25:52 CDT 2017
Hi swift-corelibs-dev,
I recently found myself with a DispatchData and wanted to use writev(2). So what I need was basically an array of pointers and lengths, not necessarily contiguous. That's exactly what DispatchData is so I thought it should be quite straightforward.
Obviously I need a guarantee that the pointers to the storage of all the DispatchData 'chunks' are all valid until writev returns.
I first checked the C API because it's documented and dispatch_data_apply seems to give me the guarantees that I need:
<quote source="man dispatch_data_apply">
The dispatch_data_apply() function provides read access to represented memory without requiring it to be mapped as a
single contiguous region. It traverses the memory regions represented by the data argument in logical order, invokes
the specified applier block for each region and returns a boolean indicating whether traversal completed success-
fully. The applier block is passed the following arguments for each memory region and returns a boolean indicating
whether traversal should continue:
dispatch_data_t rgn data object representing the region
size_t offset logical position of the region in data
const void *loc memory location of the region
size_t size extent of the region
The rgn data object is released by the system when the applier block returns. The associated memory location loc is
valid only as long as rgn has not been deallocated; if loc is needed outside of the applier block, the rgn object
must be retained in the block.
</quote>
Ie. to guarantee that all the `loc`s I get are still valid, I just need to make sure that all the `rgn`s I get are retained until writev returns. Easy!
Now I wanted to switch to Swift and unfortunately saw that DispatchData.enumerateBytes doesn't give me access to the region so I can't retain it :(.
So how can I achieve that, is it guaranteed that it's good enough to retain the overall DispatchData? Or in code, is this guaranteed to be correct?
extension DispatchData {
func writeVector(fileDescriptor: Int32) -> ssize_t {
var iobufs: [iovec] = []
self.enumerateBytes { (buf, _, _) in
var iobuf = iovec()
iobuf.iov_base = UnsafeMutableRawPointer(mutating: buf.baseAddress!)
iobuf.iov_len = buf.count
iobufs.append(iobuf)
}
return writev(fileDescriptor, iobufs, Int32(iobufs.count))
}
}
Many thanks,
Johannes
More information about the swift-corelibs-dev
mailing list