Ticket #715: trac_715_safer.patch
File trac_715_safer.patch, 8.1 KB (added by , 9 years ago) 


sage/structure/coerce.pxd
# HG changeset patch # User Simon King <simon.king@unijena.de> # Date 1345718778 7200 # Node ID 9cc4d78afa2a1d5dcddcf9118c006dc37295c623 # Parent 3cc26d30933504b7957811be2b5ee8b7ac9a3dac #715: Fix some issues pointed out by the reviewer. Remove TripleDictIter. diff git a/sage/structure/coerce.pxd b/sage/structure/coerce.pxd
a b 4 4 from parent cimport Parent 5 5 from sage.categories.action cimport Action 6 6 7 from coerce_dict cimport TripleDict , TripleDictIter7 from coerce_dict cimport TripleDict 8 8 9 9 cdef class CoercionModel_cache_maps(CoercionModel): 10 10 # This MUST be a mapping to tuples, where each 
sage/structure/coerce_dict.pxd
diff git a/sage/structure/coerce_dict.pxd b/sage/structure/coerce_dict.pxd
a b 7 7 cdef get(self, object k1, object k2, object k3) 8 8 cdef set(self, object k1, object k2, object k3, value) 9 9 10 cdef class TripleDictIter:11 cdef TripleDict pairs12 cdef buckets, bucket_iter13 14 10 cdef class TripleDictEraser: 15 11 cdef TripleDict D 
sage/structure/coerce_dict.pyx
diff git a/sage/structure/coerce_dict.pyx b/sage/structure/coerce_dict.pyx
a b 10 10 11 11 include "../ext/python_list.pxi" 12 12 13 from sage.misc.constant_function import ConstantFunction14 13 from weakref import KeyedRef 15 14 16 15 ############################################ … … 183 182 ... 184 183 KeyError: 'a' 185 184 186 The following illustrates why even sizes are bad:: 185 The following illustrates why even sizes are bad (setting the threshold 186 zero, so that no beneficial resizing happens):: 187 187 188 sage: L = TripleDict(4, L )188 sage: L = TripleDict(4, L, threshold=0) 189 189 sage: L.stats() 190 190 (0, 250.25, 1001) 191 191 sage: L.bucket_lens() … … 240 240  Simon King, 201201 241 241 """ 242 242 243 def __init__(self, size, data=None, threshold=0 ):243 def __init__(self, size, data=None, threshold=0.7): 244 244 """ 245 245 Create a special dict using triples for keys. 246 246 … … 302 302 sage: L.stats() # random 303 303 (0, 0.03325573661456601, 1) 304 304 305 sage: L = TripleDict(1) 305 In order to have a test that isn't random, we use parameters 306 that should not be used in real applications:: 307 308 sage: L = TripleDict(1, threshold=0) 306 309 sage: for i in range(100): L[i,i,i] = None 307 310 sage: L.stats() 308 311 (100, 100.0, 100) … … 329 332 EXAMPLES:: 330 333 331 334 sage: from sage.structure.coerce_dict import TripleDict 332 sage: L = TripleDict(37 )335 sage: L = TripleDict(37, threshold=0) 333 336 sage: for i in range(100): L[i,i,i] = None 334 337 sage: L.bucket_lens() # random 335 338 [3, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 3, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4] 336 339 sage: sum(L.bucket_lens()) 337 340 100 338 341 339 sage: L = TripleDict(1) 342 In order to have a test that isn't random, we use parameters 343 that should not be used in real applications:: 344 345 sage: L = TripleDict(1, threshold=0) 340 346 sage: for i in range(100): L[i,i,i] = None 341 347 sage: L.bucket_lens() 342 348 [100] … … 439 445 if <size_t>tmp == h2: 440 446 tmp = <object>PyList_GET_ITEM(bucket, i+2) 441 447 if <size_t>tmp == h3: 448 # Test whether the old references are still active 449 r1,r2,r3 = <tuple>(self._refcache[h1,h2,h3]) 450 if (isinstance(r1,KeyedRef) and r1() is None) or \ 451 (isinstance(r2,KeyedRef) and r2() is None) or \ 452 (isinstance(r3,KeyedRef) and r3() is None): 453 del bucket [i:i+4] 454 self._size = 1 455 break 442 456 bucket[i+3] = value 443 457 return 444 458 PyList_Append(bucket, h1) … … 484 498 except (TypeError,ValueError): 485 499 raise KeyError, k 486 500 try: 501 r1,r2,r3 = self._refcache[<size_t><void *>k1,<size_t><void *>k2,<size_t><void *>k3] 502 except KeyError: 503 raise KeyError, k 504 if (isinstance(r1,KeyedRef) and r1() is None) or \ 505 (isinstance(r2,KeyedRef) and r2() is None) or \ 506 (isinstance(r3,KeyedRef) and r3() is None): 507 raise KeyError, k 508 try: 487 509 del self._refcache[<size_t><void *>k1,<size_t><void *>k2,<size_t><void *>k3] 488 510 except KeyError: 511 # This is to cope with a potential racing condition  if garbage 512 # collection and weakref callback happens right between the 513 # "if (isinstance(r1,..." and the "del", then the previously 514 # existing entry might already be gone. 489 515 raise KeyError, k 490 516 cdef size_t h = (<size_t><void *>k1 + 13*<size_t><void *>k2 ^ 503*<size_t><void *>k3) 491 517 cdef Py_ssize_t i … … 547 573 sage: list(L.iteritems()) 548 574 [((1, 2, 3), None)] 549 575 """ 550 return TripleDictIter(self) 576 cdef list bucket 577 cdef size_t i, h1,h2,h3 578 # We test whether the references are still valid. 579 # However, we must not delete them, since we are 580 # iterating. 581 for bucket in self.buckets: 582 for i from 0<=i<len(bucket) by 4: 583 h1,h2,h3 = bucket[i:i+3] 584 try: 585 r1,r2,r3 = self._refcache[h1,h2,h3] 586 except KeyError: 587 # That can only happen under a race condition. 588 # Anyway, it means the item is not there. 589 continue 590 if isinstance(r1, KeyedRef): 591 r1 = r1() 592 if r1 is None: 593 continue 594 if isinstance(r2, KeyedRef): 595 r2 = r2() 596 if r2 is None: 597 continue 598 if isinstance(r3, KeyedRef): 599 r3 = r3() 600 if r3 is None: 601 continue 602 yield (r1,r2,r3), <object>PyList_GET_ITEM(bucket,i+3) 551 603 552 604 def __reduce__(self): 553 605 """ … … 566 618 """ 567 619 return TripleDict, (len(self.buckets), dict(self.iteritems()), self.threshold) 568 620 569 cdef class TripleDictIter:570 def __init__(self, pairs):571 """572 EXAMPLES::573 574 sage: from sage.structure.coerce_dict import TripleDict, TripleDictIter575 sage: L = TripleDict(31)576 sage: L[1,2,3] = None577 sage: L.iteritems().next()578 ((1, 2, 3), None)579 """580 self.pairs = pairs581 self.buckets = iter(self.pairs.buckets)582 583 def __iter__(self):584 """585 EXAMPLES::586 587 sage: from sage.structure.coerce_dict import TripleDict, TripleDictIter588 sage: L = TripleDict(31)589 sage: L[1,2,3] = None590 sage: iter(L.iteritems()).next()591 ((1, 2, 3), None)592 """593 return self594 595 def __next__(self):596 """597 EXAMPLES::598 599 sage: from sage.structure.coerce_dict import TripleDict, TripleDictIter600 sage: L = TripleDict(31)601 sage: L[1,2,3] = None602 sage: L[3,2,1] = None603 sage: sorted(L.iteritems())604 [((1, 2, 3), None), ((3, 2, 1), None)]605 """606 while self.bucket_iter is None:607 self.bucket_iter = self.buckets.next()608 self.bucket_iter = iter(self.bucket_iter)609 cdef size_t k1,k2,k3610 try:611 k1 = self.bucket_iter.next()612 k2 = self.bucket_iter.next()613 k3 = self.bucket_iter.next()614 value = self.bucket_iter.next()615 return ((<object><PyObject *>k1, <object><PyObject *>k2,616 <object><PyObject *>k3), value)617 except StopIteration:618 self.bucket_iter = None619 return self.next()620 621 622 621 cdef long next_odd_prime(long n): 623 622 if n % 2 == 0: 624 623 n = 1