Hello, Is there any way which can protect object n...
# getting-started
t
Hello, Is there any way which can protect object not be destroyed by garbage collection in kotlin native?
v
No idea about Kt/N, but if it works like the Java GC, which I assume, keep a strong reference to the instance and it will not be garbage collected, as it is no garbage.
t
how to keep strong reference?
v
Just a normal reference. Dunno whether weak refs even exist in Kt/N. In Java you can with those reference an instance without it being blocker from garbage collection. Useful for caches fire example.
t
okay. thanks. let me try
but any normal reference is a strong reference
👌 1
l
You can also use .pin and .unpin, which exist in case you want to pass an object to C for some reason (it also makes sure the GC doesn't move the object).
e
use
usePinned
instead of manually pinning and unpinning
l
If you need it in a scope, then yes. There are times though, where you need it to be long-lived. I had one use case where Kotlin created a CVariable that it had to share with a C library. I had to pin it early to make sure the GC wouldn’t move it when the C library needed to access it. In cases like that, it’s useful to pin the variable when it’s created and unpin when you’re ready to free.
e
in most cases, if something is primarily used over a long period in C, I would allocate it in a memory arena instead
l
That’s fair. Thinking back, there was once when I was using PackageKit, where I needed a variable to get accessed in a callback. I had to pin the variable and pass the address to the opaque param of the C method, then use the get() method of Pinned to get the original Kotlin object. Since a staticCFunction can’t capture, this is needed in that case.
e
you could possibly turn that callback into a
suspendCoroutine
, and then
usePinned
would work across it
Copy code
value.usePinned { pinned ->
    suspendCoroutine { cont ->
        someCFunctionWithCallback(
            staticCFunction { pinned, etc -> cont.resume(pinned.get() to etc) },
            pinned,
...or something along those lines
l
That ought to be possible (would have to pin the continuation, though to pass it through to the opaque).
That snippet captures cont, which doesn’t work with staticCFunction. This is why C methods with callbacks typically have an opaque parameter that just passes a void* when the callback runs.
e
ah yes, you'd need to wrap that too
l
That’s even more fun, since only one opaque is provided. You’d have to create a class or a struct to pin.
e
you could pin
Pair(value, cont)
right?
l
I think so. You’d have to pin both value and cont.
e
but I suppose it isn't particularly useful since
usePinned
inside the
suspendCoroutine
block doesn't help
l
I wouldn’t usePinned inside the suspendCoroutine. I’d think it would be easier to create a suspend method that hides that this is a C callback (with the appropriate pinning and unpinning internally). Once you have that, then usePinned should work fine calling your suspend function.
e
yep, you'd want to create a wrapper around it. although it may end up like
staticCFunction
, where you want
N
overloads each with different number of parameters for convenience
l
You’d need to create the wrapper for each specific C method. I don’t think there’s an easy way to generalize this (except maybe some codegen).
Either way, I’d say with regards to usePinned vs pin/unpin. If you can easily get a scope where the object is pinned at the start, and doesn’t need to be pinned after (and has no async code), usePinned is great. If you can’t make that guarantee, pin/unpin is what you’ll need.
e
I was mostly trying to point out that coroutines use compiler to rewrite a "scope" into something that carries over across different native call frames
👍 1