iosswiftpointerscore-audioraw-pointer

Create a Weak UnsafeMutableRawPointer


So I'm trying to use the CoreAudio method AUGraphAddRenderNotify(...) but I need a reference to the class that created this notification within the notification block. Because this is a C function, I can't simply add a [weak self] in closure capture. Looking at the Documentation, the last parameter of this method is allowed to be an UnsafeMutableRawPointer that will be passed in during the execution of the block as the first parameter. Following this suggestion, here is the code that I have:

let selfPointer = Unmanaged.passUnretained(self).toOpaque()
AUGraphAddRenderNotify(graph, { (audioPlayerPointer, _, _, _, _, _) -> OSStatus in
    let audioPlayer = Unmanaged<AudioPlayer>.fromOpaque(audioPlayerPointer).takeUnretainedValue()
    ...

    return noErr
}, selfPointer)

Here is my question: I need to figure out how I can safely get the value behind this pointer (accounting for nil). More specifically, I want to safely access the audioPlayer and make sure that it hasn't been deallocated by the time I use it. Currently, everything works just fine until the audioPlayer gets deallocated and then my app crashes. I know that I can use AUGraphRemoveRenderNotify(...) to stop the notification before the object gets deallocated but unfortunately this method is not what I'm looking for. How can I check if the object that the pointer is pointing to has already been deallocated?

Thanks in advance!


Solution

  • Weak references don't really work like that

    Interestingly, weak references don't actually point to the target object that they model. They point to side tables, whose lifetime is different from the target object.

    Since these side table entries aren't exposed to "user land" Swift code, you can't make a raw pointer to them, and so you can't really deal with weak references in this way.

    Alternate ideas

    I have a few ideas of what you can do instead, though I haven't tried them.

    1. You can exploit UnsafeMutableRawPointer pointer to pass in a Weak<T> wrapper, like:

      struct Weak<T: AnyObject> {
          wear var object: T?
      }
      

    Though I think it'll have to be a class, in this case.

    1. or for some other mechanism, such as passing in a closure (which weakly captures the object)