~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_static_tuple_pyx.pyx

Things are ~ working again.

Man this is getting messy, I may have to change my mind again.

I tried to export the StaticTuple type only through _static_tuple_pyx.pyx
by using a little bit of trickery. However, you end up with a circular
import issue, and also I forgot to track down one place where I needed
to rename '_static_tuple_c' => '_static_tuple_type_c'.

The idea was that _static_tuple_type.c would *only* define the type,
and not any extra info. This way the code could be compiled with either
cython or pyrex and still get the 'better' StaticTuple object.

It ended up, overall, just being a multi-hour mess trying to get the
dependencies sorted out. By using a .pxd file, at least the basic
circular import problem was sorted out.

However at this point, you *have* to import _static_tuple_pyx before
_static_tuple_type_c or you get a segfault, and you have to import the
latter if you want to get direct access to the class.

So at this point I feel like I either need to:
 1) Go back to the way it was, and get rid of the circular import
 2) Finish the rest of the steps, bring everything into Cython
    and say 'if you want the memory improvements, then you have
    to compile with cython.'

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
    PyObject *Py_NotImplemented
26
26
    void Py_INCREF(PyObject *)
27
27
    void Py_DECREF(PyObject *)
 
28
    ctypedef struct PyVarObject:
 
29
        pass
28
30
    ctypedef struct PyTypeObject:
29
31
        hashfunc tp_hash
30
32
        richcmpfunc tp_richcompare
31
33
 
32
34
    PyTypeObject *Py_TYPE(PyObject *)
 
35
    PyVarObject * _PyObject_NewVar(PyTypeObject *, Py_ssize_t) except NULL
33
36
        
34
37
    void *PyMem_Malloc(size_t nbytes)
35
38
    void PyMem_Free(void *)
40
43
_dummy_obj = object()
41
44
_dummy = <PyObject *>_dummy_obj
42
45
 
43
 
 
44
46
cdef inline int _is_equal(PyObject *this, long this_hash, PyObject *other):
45
47
    cdef long other_hash
46
48
    cdef PyObject *res
546
548
        key[0] = table[i]
547
549
    return 1
548
550
 
 
551
 
 
552
cdef StaticTuple _empty_tuple
 
553
def _get_empty_tuple():
 
554
    """Return the 'empty tuple'
 
555
 
 
556
    This is the singleton StaticTuple that has no content.
 
557
    """
 
558
    return _empty_tuple
 
559
 
 
560
 
 
561
cdef api StaticTuple StaticTuple_New(Py_ssize_t size):
 
562
    """Create a new StaticTuple object with the number of slots specified."""
 
563
    cdef PyObject *tmp
 
564
    cdef StaticTuple stuple
 
565
 
 
566
    if size < 0:
 
567
        raise ValueError('size must be > 0')
 
568
 
 
569
    if (size == 0 and _empty_tuple is not None):
 
570
        return _empty_tuple
 
571
    # Note that we use PyObject_NewVar because we want to allocate a variable
 
572
    # width entry. However we *aren't* truly a PyVarObject because we don't
 
573
    # use a long for ob_size. Instead we use a plain 'size' that is an int,
 
574
    # and will be overloaded with flags in the future.
 
575
    # As such we do the alloc, and then have to clean up anything it does
 
576
    # incorrectly. Consider switching to PyObject_MALLOC directly
 
577
    tmp = <PyObject *>_PyObject_NewVar(<PyTypeObject*>StaticTuple, size)
 
578
    stuple = <StaticTuple>tmp
 
579
    Py_DECREF(tmp) # The cast to <StaticTuple> causes an INCREF
 
580
    stuple.size = size;
 
581
    stuple.flags = 0;
 
582
    stuple._unused0 = 0
 
583
    stuple._unused1 = 0
 
584
    if size > 0:
 
585
        memset(stuple.items, 0, sizeof(PyObject *) * size)
 
586
    return stuple
 
587
 
 
588
cdef api int StaticTuple_CheckExact(object s):
 
589
    return isinstance(s, StaticTuple)
 
590
 
 
591
 
 
592
cdef api StaticTupleInterner _interned_tuples
 
593
def _get_interned_tuples():
 
594
    """Get a copy of the _interned_tuples object.
 
595
 
 
596
    Note that this object should *never* be mutated. Doing so could cause
 
597
    segfaults, etc.
 
598
    """
 
599
    return _interned_tuples
 
600
 
 
601
 
 
602
cdef api StaticTuple StaticTuple_Intern(StaticTuple self):
 
603
    if _interned_tuples is None:
 
604
        return self
 
605
    if self.flags & STATIC_TUPLE_INTERNED_FLAG:
 
606
        return self
 
607
    # StaticTupleInterner_Add returns whatever object is present at self
 
608
    # or the new object if it needs to add it.
 
609
    # 
 
610
    unique_key = _interned_tuples.add(self)
 
611
    if unique_key is not self:
 
612
        # There was already a key here, just return it
 
613
        return unique_key
 
614
    # This is now interned, mark it as such, and adjust the refcount
 
615
    self.flags |= STATIC_TUPLE_INTERNED_FLAG
 
616
    Py_DECREF(<PyObject *>self)
 
617
    return self
 
618
 
 
619
 
 
620
_interned_tuples = StaticTupleInterner()
 
621
_empty_tuple = _interned_tuples.add(StaticTuple())
 
622
_empty_tuple.flags |= STATIC_TUPLE_ALL_STRING
 
623