Complete
over 3 years ago

By design. 

weak() doesn't work or bug in simulator/ActiveMemory

this

code

class Cone
{
	var x;
	
	function initialize(parent)
	{
		x	= parent.weak().get();
	} 
}

class Ctwo
{
	var xs;
	
	function initialize()
	{
		xs = new[2];
		
		xs[0] = new Cone(self);
		xs[1] = new Cone(self);
	}
}

var t = new Ctwo();

in ActiveMemory I can see:

- t Obj #187 Circular Reference!
-- xs Obj #188
--- [0] Obj #189
----x Obj #187 Circular Reference!
...

  • I didn't make this up:) I simple took code and try it to run and I have shown in memory monitor circular ref so resign. I can't attach screenshot here.

    But yes, probably if I modify code to put in mContext a weak and change line to mCallback.get().invoke(code, data, mContext); there will be no circular ref. But it doesn't matter anymore because I've made my own workaround for this bug.

  • No. That code does not generate a circular reference.

    It creates an opportunity for a developer to create a circular reference, but it leaves to the developer using it to not make that mistake.

    The mContext variable is untyped, so it could be anything. There is only a reference cycle if the context parameter provided to WebRequestDelegate.initialize() is a strong reference to an object that holds a reference back to the WebRequestDelegate. You are free to pass a WeakReference and use that to get a strong reference inside your 3 parameter callback if that suits the needs of your application, but honestly that is not how the class was intended to be used.

    The WebRequestDelegate is supposed to be transient; you create one per request and let it go out of scope after the request is made. When the system invokes the callback, it releases its reference to the Lang.Method that was passed to Communications.makeWebRequest(), which in turn releases the reference to the WebRequestDelegate itself. Assuming no other strong references to the delegate exist, it is destroyed and deallocated immediately after the user callback is invoked.

    If you look at the full example provided there, that is exactly how the WebRequestDelegate is used. A temporary delegate with context is created on line 24, a request is made using the delegate on line 36, and the local variable goes out of scope on line 37.

  • Clarification is only necessary if something is not documented properly or unlogical. 

    If I knew how it was designed I don't need clarification it is understandable in no time and the same decision to not touch such solution.

    But of course thanks for info.

  • I've resigned at all from this solution because:

    1. It's not completely useful for me, for me should be like I have described, removing circular for small scope I can replace by parameter of function
    function(parent)
    {
      praent.foo();
    }

    2. Invoke is very slow.

    3. Consumes a lot of resources

    BTW Travis, your workaround for, not fixed for years error, connected with :context in makeWebRequest  described in

    https://forums.garmin.com/developer/connect-iq/f/discussion/6866/context-not-passed-in-when-makewebrequest-encounters-system-level-errors

    generates circular reference too. It means that is impossible to holding reference to own function.

  • Thanks for the detailed clarification !