Hey Michel, In that example, it is indeed the reference to the Payload that causes it not to go out of scope. But you can't print it with the function parameter o, because that is not the slice itself, but the pointer to the first byte of the slice. I would either need a runtime call that removed the local reference, the oppositoe of KeepAlive() or there might be some way of using Unsafe on this to walk the array C style, but that just seems like a bad idea.
On Tuesday, December 31, 2019 at 2:53:26 AM UTC-8, Michel Levieux wrote: > > Hi John, > > I'm not sure what I'm about to say (i can't test anything right now), but > in your last example, wouldn't it be that the finalizer is never called > because the function you give it is a closure that holds a reference of > b.Payload itself? Thus the GC would consider b.Payload never unreachable > and never call its finalizer? Have you tried doing the same thing (print > the finalized object) using the function parameter o, rather than an object > of the surrounding scope? > > Hope this helps > > Le lun. 30 déc. 2019 à 17:31, John <johns...@gmail.com <javascript:>> a > écrit : > >> Thank you Keith, that is a very interesting technique, I doubt I would >> have come up with that. >> >> Unfortunately, that lead me to another problem as I needed the finalizer >> to have access to the entire underlying data, which I did not state when I >> wrote my question. >> >> I tried to extend this to provide the whole slice to the finalizer using >> the current scope: >> >> type Blah struct { >> Payload []byte >> } >> >> func do() { >> b := &Blah{Payload: make([]byte, 100)} >> runtime.SetFinalizer(&b.Payload[0], func(o >> *byte){log.Println("finalized"); fmt.Println("b.Payload[1] }) >> ... >> } >> >> That of course created a reference to the slice in the finalizer, which >> then prevents the slice from being GC'd, defeating the purpose. >> >> The more I've dug into this, the more I can see that trying to do this is >> probably not possible, or at best, never going to be safe. It was a nice >> thought experiment though. >> >> Thanks for the help Keith. >> >> On Sunday, December 29, 2019 at 9:16:53 PM UTC-8, Keith Randall wrote: >>> >>> It should work to just set the finalizer on the first byte of an >>> allocation. i.e.: >>> >>> s := make([]byte, N) >>> runtime.SetFinalizer(&s[0], func(b *byte) { ... }) >>> >>> Note that the spec of runtime.SetFinalizer doesn't actually guarantee >>> that this will work. But I think in the current implementation it will. >>> >>> > The argument obj must be a pointer to an object allocated by calling >>> new, by taking the address of a composite literal, or by taking the address >>> of a local variable. >>> >>> The result of make isn't "an object created by calling new", but it it >>> close. >>> >>> On Saturday, December 28, 2019 at 9:27:29 PM UTC-8, John wrote: >>>> >>>> Looking for a little insight on if it is possible to do something: >>>> >>>> Given this type: >>>> >>>> type Blah struct { >>>> Payload []byte >>>> } >>>> >>>> What I'm looking for is to kick off a finalizer when a slice and all >>>> other slices backed by the same array get GC'd. >>>> >>>> In lieu of that, whenver the pointer to the array backing a slice get's >>>> GC'd. I realize that in this case, the slice actually may stay around when >>>> the array is GC'd because an append creates a new array on the slice. >>>> >>>> I don't think the first is possible, as you can't call SetFinalizer() >>>> on non-pointer types. And I can't use any wrappers or pointers to []byte >>>> in >>>> lieu of []byte for my use case. >>>> >>>> I figure there is a way to use: >>>> >>>> hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b.Payload)) >>>> >>>> to set a finalizer on the underlying arrray. >>>> >>>> But I'm not sure exactly how to convert the hdr.Data into the specific >>>> array type pointer to use in SetFinalizer(). It may not be possible. >>>> >>>> To save some time on a few questions: I'm aware of the flaws of >>>> SetFinalizer(), just looking to see if this can actually be done. >>>> >>>> Thanks for any help. >>>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golan...@googlegroups.com <javascript:>. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/fb37ba35-9104-4278-96f3-92045a4ddb45%40googlegroups.com >> >> <https://groups.google.com/d/msgid/golang-nuts/fb37ba35-9104-4278-96f3-92045a4ddb45%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/b9679b24-e1db-41ee-9b51-437bc69f4fce%40googlegroups.com.