#13394: Write a WeakValueDictionary with safer key removal
-------------------------------+--------------------------------------------
       Reporter:  nbruin       |         Owner:  rlm     
           Type:  enhancement  |        Status:  new     
       Priority:  major        |     Milestone:  sage-5.4
      Component:  memleak      |    Resolution:          
       Keywords:               |   Work issues:          
Report Upstream:  N/A          |     Reviewers:          
        Authors:               |     Merged in:          
   Dependencies:               |      Stopgaps:          
-------------------------------+--------------------------------------------

Comment (by nbruin):

 The standard Python `WeakValueDictionary` is built on top of a normal
 dictionary, built on top of a normal dictionary. Let's say we have
 {{{
 W = WeakValueDictionary()
 }}}
 There is an underlying `D = dict`. If we do
 {{{
 W[k] = v
 }}}
 then it really executes
 {{{
 D[k] = KeyedRef(v, k, remove_callback)
 }}}
 This is a weak reference to v, so v can still get collected. If it does,
 the callback can ensure that
 {{{
 del D[k]
 }}}
 gets executed. This locates the entry by computing the hash of `h`,
 finding the right bucket and finding an equal key by comparison. When we
 create the entry, we have better lookup information, though: We already
 have `hash(k)` and `id(v)`. These two don't necessarily pin down the entry
 in the dictionary, but in our applications they do and for a
 `WeakValueDictionary` identical `v` would be the same (dead) `KeyedRef`
 anyway, so it wouldn't hurt to remove them all. We need one more method on
 our dictionary:
 {{{
 D.remove_entry_by_hash_and_value_id(h,i):
     """
     remove all entries { k : v } from the dictionary that have
     hash(k) == h   and  id(v) == i
     """
 }}}
 Then the callback can be
 {{{
 function remove(ref):
     D.remove_entry_by_hash_and_value_id(hash(ref.key),id(ref))
 }}}
 and the `KeyedRef` that gets stored would be
 {{{
 KeyedRef(v,hash(k),remove)
 }}}
 (normal precautions to put the dict reference in a closure or a class
 should apply here in defining `remove`)

 Or one could just immediately integrate the `KeyedRefs` in the design. See
 also #13387 for discussions about dictionary designs.

 In either case, the main effect is that removal does not cause any hashing
 or comparison methods to be called on `k` anymore.

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/13394#comment:2>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sage-trac?hl=en.

Reply via email to