Eric Snow added the comment:

It turns out the problem was that the odict resize mechanism was not getting 
triggered in all the cases that it should have been.  dict resizes after a 
certain number of insertions, whether or not previous deletions have cleared 
out space.  odict only resizes its fast lookup table when it needs to do a fast 
node lookup and only when the current dict keys size does not match the current 
size of the odict fast lookup table.

This bug is the consequence of a corner case which odict did not handle 
correctly.  When you delete an item and then insert another, the resulting size 
of the dict keys is the same as the it was before the deletion.  However, the 
insertion may have triggered a resize.  This matters because when a resize 
happens the keys are re-inserted into the hash table.  If it so happens that 
they key you just removed was in a slot that would have otherwise been occupied 
by another key (i.e. there was an earlier collision) then upon resizing that 
other key will be moved to its preferred slot.

Here's a patch that changes odict to rely on the pointer value of dict's 
ma_keys (rather than on ma_keys.dk_size) to indicate the need for a resize.  
This works because dict creates a new keys struct every time it resizes.

I'll point out that one alternative would be to track a "state" counter on dict 
that increments each time there's a resize.  Then odict could check that rather 
than the ma_keys pointer value.

----------
keywords: +patch
stage:  -> patch review
type:  -> behavior
Added file: http://bugs.python.org/file40126/odict-correct-resize.diff

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue24667>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to