CallbackCreate holds a reference to "this" preventing __Delete from executing

Share your ideas as to how the documentation can be improved.
iseahound
Posts: 1444
Joined: 13 Aug 2016, 21:04
Contact:

CallbackCreate holds a reference to "this" preventing __Delete from executing

Post by iseahound » 15 Jun 2022, 22:49

Please mention that if CallbackCreate is used on a class instance method closure (nested method), and that you are creating instances of the class, it will hold a reference to this.

So __Delete cannot be called.

Code: Select all

a := s()

; If 2, is normal. If 3, cannot call __delete.
MsgBox ObjAddRef(ObjPtr(a))

class s {
   __new() {
      pWndProc := CallbackCreate(WindowProc)
      this.carrot := "bunny"
      return this

      WindowProc() {
         this.carrot := "rabbit?" ; is closure now
      }
   }
}
In addition, show that the usage of a "this" variable should be avoided, and replaced with "self" or some other variant to prevent a closure from being formed

Code: Select all

a := s()

; If 2, is normal. If 3, cannot call __delete.
MsgBox ObjAddRef(ObjPtr(a))

class s {
   __new() {
      pWndProc := CallbackCreate(WindowProc)
      this.carrot := "bunny"
      return this

      WindowProc() {
         self := "I got this reference to self from a machine code address"
         self.carrot := "rabbit?"
      }
   }
}

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: CallbackCreate holds a reference to "this" preventing __Delete from executing

Post by Helgef » 16 Jun 2022, 02:24

I do not agree that this is an issue with the documentation on callbackcreate, it is clear,
CallbackCreate wrote: The callback retains a reference to the function object, and releases it when the script calls CallbackFree.
Perhaps the section :arrow: Freeing Objects could have more advanced examples which could easily be overlooked when starting out with closures and/or classes, and such.

Cheers.

lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: CallbackCreate holds a reference to "this" preventing __Delete from executing

Post by lexikos » 03 Jul 2022, 01:28

If this is a shortcoming of the documentation, it is because the topic itself is esoteric and I don't have the words to explain in a way that would be easily understood, or I don't know what it is that others fail to understand. There isn't really much to it; from my perspective, it seems like just a matter of putting more thought into understanding the problem and the logic of your code. I'm not saying it's easy; when I encounter reference-counting problems, I generally have to put real thought into it.

So __Delete cannot be called.
__Delete is a method. If it is defined, it can be called. It shouldn't and won't be called automatically until the object is deleted. What you should be saying is that the object won't be deleted, because the callback has a reference to it.

usage of a "this" variable should be avoided, and replaced with "self" or some other variant to prevent a closure from being formed
I think that if you actually implemented your idea (rather than only assigning a string describing what you intended to demonstrate), you might see why it is no good.

The object can't and must not be deleted, because the callback needs to refer to it. The callback can potentially be called at any time, until the callback itself is deleted. When you create a callback, you must manage its lifetime - it is like calling ObjAddRef on an existing object. After you delete the callback, the object will be deleted. There is not even a circular reference.

If you work around your problem by giving the callback an uncounted reference (perhaps a pointer), the callback will only be safe to execute while you have a definite reference to the object (for instance, while the method is executing). Because it no longer has a reference to the object, you would probably overlook the failure to delete the callback when you're done using it.

I suppose most of the documentation for CallbackCreate was written when functions were static things, and objects didn't exist. It should probably put greater emphasis on managing the lifetime of the callback.

Post Reply

Return to “Suggestions on Documentation Improvements”