Re: Weak callbacks?
That example looks to me like it could be implemented with WeakMap instead of WeakRef. Am I missing something? On Thu Nov 07 2013 at 2:43:45 PM, K. Gadd k...@luminance.org wrote: I'll try and restate an example I used before. Let's say you're building a somewhat simple tab-based application, where each tab represents a different 'mode'. In this case, you need a higher level coordinating object that manages the tab bar, and it needs to own references to all of the active modes in order to manage the tabs. Similarly, each mode may need to have a reference to the coordinator in order to interact with it - like by setting the title of the tab, or opening a new tab containing another mode - and it may need to have references to other modes in order to communicate (like if one tab opens a tab containing related information). In a model like that, you can trivially end up with object cycles. All the references (going in every direction) are strong, so to successfully collect a mode you need to ensure that every reference to it from live objects is released. This is problematic because it means that, for example: If Mode A opens a new tab containing Mode B, and Mode A wants to respond to things happening in Mode B, Mode A now has to register some sort of event listener on Mode B. This means that Mode A and Mode B have now formed a strong cycle: Mode B's event listener list contains a strong reference to Mode A (to fire the event notification), and Mode A has a strong reference to Mode B in order to be able to respond to those events. Now, if you close Mode B, the coordinator gets rid of the tab and drops its strong references to Mode B - the tab is 'gone' - but there's no trivial way to ensure that everyone else holding a reference to it is dead. If multiple tabs interact in this way it's possible for a huge graph of objects to be hanging off one live tab. Eventually, if you close enough tabs you might 'free' the graph, but if you aren't careful the coordinator itself can end up keeping dead tabs alive, with things like event listener lists. In the real apps I've worked on like this, the solution was some form of weak references - making event listeners own weak self-references instead of strong self-references, so that in normal circumstances event subscriptions expire along with the subscriber, along with using weak references directly in cases like 'tab a spawns tab b' in order to ensure that you aren't keeping an object alive just to monitor it. IIRC, cycles like this are already common in some DOM scenarios, where event subscription and such result in big graphs of objects hanging off a single live object? I've certainly run into it in a few cases, where an event listener hanging off an audio element caused a huge graph of objects to leak, and I had to manually remove the event listeners at an appropriate time (and finding an appropriate time can be difficult!) On Thu, Nov 7, 2013 at 2:33 PM, Mark S. Miller erig...@google.com wrote: Could you give an example, hopefully simple, of such a problem you can solve better with GC + weakmaps + weakrefs but without finalization, vs just GC + weakmaps ? Thanks. On Thu, Nov 7, 2013 at 1:46 PM, K. Gadd k...@luminance.org wrote: When I talk about the importance of weak references I am *not* talking about the importance of finalization for managing native/remote resources; that's an important consideration but it's a separate one. When I talk about why weak references are important, I mean for the purposes of building large applications without creating uncollectable cycles in object graphs. Doing this without weak references is *very* difficult in some scenarios, and in other scenarios requires manual management of all object lifetimes (addref/release style, or having a single lifetime owner that 'deletes' an object on demand). That's the sort of obstacle that factors into a developer's choice of language and toolset. I've seen this particular concern with ES crop up in the past on real projects, and I've seen firsthand how difficult it is to avoid uncollectable cycles in a language environment without any sort of weak reference mechanism. Leaking large uncollectable cycles can have catastrophic consequences in multimedia applications and games, where those cycles might be retaining images or sounds or other huge game assets. On Thu, Nov 7, 2013 at 9:19 AM, Terrence Cole tc...@mozilla.com wrote: On 11/06/2013 07:37 PM, K. Gadd wrote: Generally speaking, all the discussions on this list about WRs so far have not suggested that there is any way to introduce WeakRefs without making GC behavior observable in some fashion. WeakRefs functionally make GC observable because when you try to get at the target of the weakref, you either get it or you don't. Once you introduce the ability to get back 'null' when asking for the target of a WR (or any similar failure case), you can use
Re: Weak callbacks?
Ah, sorry, I misread your description of the relationships. Yeah, that would be hard to do with WeakMaps. On Thu Nov 07 2013 at 3:02:02 PM, K. Gadd k...@luminance.org wrote: I am not aware of any way to implement my described scenario using WeakMaps without having the same cycle collection issues. I haven't seen any examples of WeakMap used for this in the wild either. On Thu, Nov 7, 2013 at 2:48 PM, felix lee feli...@gmail.com wrote: That example looks to me like it could be implemented with WeakMap instead of WeakRef. Am I missing something? On Thu Nov 07 2013 at 2:43:45 PM, K. Gadd k...@luminance.org wrote: I'll try and restate an example I used before. Let's say you're building a somewhat simple tab-based application, where each tab represents a different 'mode'. In this case, you need a higher level coordinating object that manages the tab bar, and it needs to own references to all of the active modes in order to manage the tabs. Similarly, each mode may need to have a reference to the coordinator in order to interact with it - like by setting the title of the tab, or opening a new tab containing another mode - and it may need to have references to other modes in order to communicate (like if one tab opens a tab containing related information). In a model like that, you can trivially end up with object cycles. All the references (going in every direction) are strong, so to successfully collect a mode you need to ensure that every reference to it from live objects is released. This is problematic because it means that, for example: If Mode A opens a new tab containing Mode B, and Mode A wants to respond to things happening in Mode B, Mode A now has to register some sort of event listener on Mode B. This means that Mode A and Mode B have now formed a strong cycle: Mode B's event listener list contains a strong reference to Mode A (to fire the event notification), and Mode A has a strong reference to Mode B in order to be able to respond to those events. Now, if you close Mode B, the coordinator gets rid of the tab and drops its strong references to Mode B - the tab is 'gone' - but there's no trivial way to ensure that everyone else holding a reference to it is dead. If multiple tabs interact in this way it's possible for a huge graph of objects to be hanging off one live tab. Eventually, if you close enough tabs you might 'free' the graph, but if you aren't careful the coordinator itself can end up keeping dead tabs alive, with things like event listener lists. In the real apps I've worked on like this, the solution was some form of weak references - making event listeners own weak self-references instead of strong self-references, so that in normal circumstances event subscriptions expire along with the subscriber, along with using weak references directly in cases like 'tab a spawns tab b' in order to ensure that you aren't keeping an object alive just to monitor it. IIRC, cycles like this are already common in some DOM scenarios, where event subscription and such result in big graphs of objects hanging off a single live object? I've certainly run into it in a few cases, where an event listener hanging off an audio element caused a huge graph of objects to leak, and I had to manually remove the event listeners at an appropriate time (and finding an appropriate time can be difficult!) On Thu, Nov 7, 2013 at 2:33 PM, Mark S. Miller erig...@google.com wrote: Could you give an example, hopefully simple, of such a problem you can solve better with GC + weakmaps + weakrefs but without finalization, vs just GC + weakmaps ? Thanks. On Thu, Nov 7, 2013 at 1:46 PM, K. Gadd k...@luminance.org wrote: When I talk about the importance of weak references I am *not* talking about the importance of finalization for managing native/remote resources; that's an important consideration but it's a separate one. When I talk about why weak references are important, I mean for the purposes of building large applications without creating uncollectable cycles in object graphs. Doing this without weak references is *very* difficult in some scenarios, and in other scenarios requires manual management of all object lifetimes (addref/release style, or having a single lifetime owner that 'deletes' an object on demand). That's the sort of obstacle that factors into a developer's choice of language and toolset. I've seen this particular concern with ES crop up in the past on real projects, and I've seen firsthand how difficult it is to avoid uncollectable cycles in a language environment without any sort of weak reference mechanism. Leaking large uncollectable cycles can have catastrophic consequences in multimedia applications and games, where those cycles might be retaining images or sounds or other huge game assets. On Thu, Nov 7, 2013 at 9:19 AM, Terrence Cole tc...@mozilla.com wrote: On 11/06/2013 07:37 PM, K. Gadd wrote: Generally