Skip to content

Instantly share code, notes, and snippets.

@amomchilov
Forked from CentrumGuy/PointerIssue.swift
Last active November 12, 2022 13:07
Show Gist options
  • Save amomchilov/a664fbd2bb0da47a219f826f2a35703e to your computer and use it in GitHub Desktop.
Save amomchilov/a664fbd2bb0da47a219f826f2a35703e to your computer and use it in GitHub Desktop.
import Dispatch
import Foundation
// The Weak struct is the weak wrapper
struct Weak<T: AnyObject> {
weak var object: T?
}
// Stand-in for AUGraphAddRenderNotify
func call(
cCallback: @escaping @convention(c) (UnsafeMutableRawPointer) -> Void,
inRefCon: UnsafeMutableRawPointer
) {
cCallback(inRefCon) // call once immediately
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
cCallback(inRefCon) // call once after deallocation of the TestObject
}
}
// A callback that's guarenteed to not capture a TestObject
let theCallBack: @convention(c) (UnsafeMutableRawPointer) -> Void = { rawPointer in
print("Running callback")
let weakWrapperPointer = rawPointer.assumingMemoryBound(to: Weak<TestObject>.self)
let weakWrapper = weakWrapperPointer.pointee
if let object = weakWrapper.object {
print(object.value)
}
}
// TestObject represents the AudioPlayer class
class TestObject {
let value = "test"
init () {
print("init")
// Create a wrapper for this object
let weakWrapper = Weak<TestObject>(object: self)
// Create the wrapper pointer
let size = MemoryLayout<Weak<TestObject>>.size
let weakWrapperPointer = UnsafeMutableRawPointer.allocate(byteCount: size, alignment: 1)
weakWrapperPointer.storeBytes(of: weakWrapper, as: Weak<TestObject>.self)
// This is the problem. I can't figure out how to get this to work without crashing
call(cCallback: theCallBack, inRefCon: weakWrapperPointer)
}
deinit {
print("deinit")
}
}
// Create a test object, which immediately gets deallocated (represents the AudioPlayer)
_ = TestObject()
RunLoop.main.run(until: Date().addingTimeInterval(2))
print("The end")
@amomchilov
Copy link
Author

@mori-nobuteru if I understand correctly, you’re passing in a strong reference to a WeakVar object (now a class), whereas I was passing in a a raw pointer to the struct.

I like your approach better! It involves one more reference counted object, but it’s semantics are clearer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment