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

Comment (by SimonKing):

 Here is an example concerning "garbage collection during iteration".
 Features of the example:
 - Many hash collisions
 - Reference cycles, so that Python's cyclic garbage collector comes into
 play
 - The garbage collection is postponed until after the first iteration.

 First, with `weakref.WeakValueDictionary`:
 {{{
 sage: class Cycle(object):
 ....:     def __init__(self, n):
 ....:         self.n = n
 ....:         self.ref = self
 ....:     def __cmp__(self, other):
 ....:         c = cmp(type(self),type(other))
 ....:         if c:
 ....:             return c
 ....:         return cmp(self.n, other.n)
 ....:     def __repr__(self):
 ....:         return "Cyc(%s)"%self.n
 ....:
 sage: class Keys(object):
 ....:     def __init__(self, n):
 ....:         self.n = n
 ....:     def __hash__(self):
 ....:         return self.n%5
 ....:     def __cmp__(self, other):
 ....:         c = cmp(type(self),type(other))
 ....:         if c:
 ....:             return c
 ....:         return cmp(self.n, other.n)
 ....:     def __repr__(self):
 ....:         return "Key(%s)"%self.n
 ....:
 sage: C = [Cycle(n) for n in range(100)]
 sage: K = [Keys(n) for n in range(100)]
 sage: import gc
 sage: import sage.misc.weak_dict
 sage: import weakref
 sage: D = weakref.WeakValueDictionary()
 sage: for k,c in zip(K,C):
 ....:     D[k] = c
 ....:
 sage: del c
 sage: gc.disable()
 sage: del C
 sage: for k,c in D.iteritems():
 ....:     print k,c
 ....:     gc.enable()
 ....:     _ = gc.collect()
 ....:
 Key(0) Cyc(0)
 Traceback (most recent call last):
 ...
 RuntimeError: dictionary changed size during iteration
 }}}

 And with `sage.misc.weak_dict.WeakValueDictionary`:
 {{{
 sage: D = sage.misc.weak_dict.WeakValueDictionary(zip(K,C))
 sage: len(D)
 100
 sage: gc.disable()
 sage: del C
 sage: for k,c in D.iteritems():
 ....:     print k,c
 ....:     gc.enable()
 ....:     _ = gc.collect()
 ....:
 Key(0) Cyc(0)
 Traceback (most recent call last):
 ...
 IndexError: list index out of range
 }}}

 So, there is an error, too. Perhaps one could improve the error message.

--
Ticket URL: <http://trac.sagemath.org/ticket/13394#comment:15>
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 unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to