Commit e95a78ad authored by scoder's avatar scoder Committed by GitHub

Merge pull request #511 from klaussfreire/master

Add no_gc directive to fully disable GC
parents d142afbf 264ae3f5
...@@ -116,6 +116,7 @@ directive_defaults = { ...@@ -116,6 +116,7 @@ directive_defaults = {
'internal' : False, 'internal' : False,
'profile': False, 'profile': False,
'no_gc_clear': False, 'no_gc_clear': False,
'no_gc': False,
'linetrace': False, 'linetrace': False,
'emit_code_comments': True, # copy original source code into C code comments 'emit_code_comments': True, # copy original source code into C code comments
'annotation_typing': False, # read type declarations from Python function annotations 'annotation_typing': False, # read type declarations from Python function annotations
...@@ -246,6 +247,7 @@ directive_scopes = { # defaults to available everywhere ...@@ -246,6 +247,7 @@ directive_scopes = { # defaults to available everywhere
'inline' : ('function',), 'inline' : ('function',),
'staticmethod' : ('function',), # FIXME: analysis currently lacks more specific function scope 'staticmethod' : ('function',), # FIXME: analysis currently lacks more specific function scope
'no_gc_clear' : ('cclass',), 'no_gc_clear' : ('cclass',),
'no_gc' : ('cclass',),
'internal' : ('cclass',), 'internal' : ('cclass',),
'autotestdict' : ('module',), 'autotestdict' : ('module',),
'autotestdict.all' : ('module',), 'autotestdict.all' : ('module',),
......
...@@ -1889,7 +1889,7 @@ class CClassScope(ClassScope): ...@@ -1889,7 +1889,7 @@ class CClassScope(ClassScope):
def needs_gc(self): def needs_gc(self):
# If the type or any of its base types have Python-valued # If the type or any of its base types have Python-valued
# C attributes, then it needs to participate in GC. # C attributes, then it needs to participate in GC.
if self.has_cyclic_pyobject_attrs: if self.has_cyclic_pyobject_attrs and not self.directives.get('no_gc', False):
return True return True
base_type = self.parent_type.base_type base_type = self.parent_type.base_type
if base_type and base_type.scope is not None: if base_type and base_type.scope is not None:
......
...@@ -118,7 +118,7 @@ optimization = _Optimization() ...@@ -118,7 +118,7 @@ optimization = _Optimization()
overflowcheck.fold = optimization.use_switch = \ overflowcheck.fold = optimization.use_switch = \
optimization.unpack_method_calls = lambda arg: _EmptyDecoratorAndManager() optimization.unpack_method_calls = lambda arg: _EmptyDecoratorAndManager()
final = internal = type_version_tag = no_gc_clear = _empty_decorator final = internal = type_version_tag = no_gc_clear = no_gc = _empty_decorator
def inline(f, *args, **kwds): def inline(f, *args, **kwds):
......
...@@ -514,6 +514,21 @@ which makes it impossible to clean up the cursor. ...@@ -514,6 +514,21 @@ which makes it impossible to clean up the cursor.
Using the ``no_gc_clear`` decorator this can not happen anymore because the Using the ``no_gc_clear`` decorator this can not happen anymore because the
references of a cursor object will not be cleared anymore. references of a cursor object will not be cleared anymore.
In rare cases, extension types can be guaranteed not to participate in cycles,
but the compiler won't be able to prove this. This would be the case if
the class can never reference itself, even indirectly.
In that case, you can manually disable cycle collection by using the
``no_gc`` decorator, but beware that doing so when in fact the extension type
can participate in cycles could cause memory leaks ::
@cython.no_gc
cdef class UserInfo:
cdef str name
cdef tuple addresses
If you can be sure addresses will contain only references to strings,
the above would be safe, and it may yield a significant speedup, depending on
your usage pattern.
Public and external extension types Public and external extension types
==================================== ====================================
......
"""
Check that the @cython.no_gc decorator disables generation of the
tp_clear and tp_traverse slots, that is, disables cycle collection.
"""
cimport cython
from cpython.ref cimport PyObject, Py_TYPE
# Force non-gc'd PyTypeObject when safety is guaranteed by user but not provable
cdef extern from *:
ctypedef struct PyTypeObject:
void (*tp_clear)(object)
void (*tp_traverse)(object)
def is_tp_clear_null(obj):
return (<PyTypeObject*>Py_TYPE(obj)).tp_clear is NULL
def is_tp_traverse_null(obj):
return (<PyTypeObject*>Py_TYPE(obj)).tp_traverse is NULL
@cython.no_gc
cdef class DisableGC:
"""
An extension type that has tp_clear and tp_traverse methods generated
to test that it actually clears the references to NULL.
>>> uut = DisableGC()
>>> is_tp_clear_null(uut)
True
>>> is_tp_traverse_null(uut)
True
"""
cdef public object requires_cleanup
def __cinit__(self):
self.requires_cleanup = (
"Tuples to strings don't really need cleanup, cannot take part of cycles",)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment