[Xcb] [PATCH 7/7] Avoid reference cycles in response instances.

Alex Plotnick shrike at netaxs.com
Wed Feb 29 08:59:57 PST 2012


The issue is with fields that use self as the parent buffer; we end
up with cycles that the GC can't collect, since buffer objects aren't
GC-aware.

Also took the opportunity to replace separate "count" variables with
offsets wherever possible, and skip size calculations entirely for
fixed-size Unions.
---
 src/py_client.py |   67 ++++++++++++++++++++++++++++-------------------------
 1 files changed, 35 insertions(+), 32 deletions(-)

diff --git a/src/py_client.py b/src/py_client.py
index 961c60c..d897ecd 100755
--- a/src/py_client.py
+++ b/src/py_client.py
@@ -300,7 +300,6 @@ def _py_type_alignsize(field):
         
 def _py_complex(self, name):
     need_alignment = False
-    _py('        count = 0')
 
     for field in self.fields:
         if field.auto:
@@ -315,33 +314,33 @@ def _py_complex(self, name):
 
         (format, size, list) = _py_flush_format()
         if len(list) > 0:
-            _py('        (%s,) = unpack_from(\'%s\', self, count)', list, format)
+            _py('        (%s,) = unpack_from(\'%s\', parent, offset)', list, format)
         if size > 0:
-            _py('        count += %d', size)
+            _py('        offset += %d', size)
 
         if need_alignment:
-            _py('        count += xcb.type_pad(%d, count)', _py_type_alignsize(field))
+            _py('        offset += xcb.type_pad(%d, offset)', _py_type_alignsize(field))
         need_alignment = True
 
         if field.type.is_list:
-            _py('        self.%s = xcb.List(self, count, %s, %s, %d)', _n(field.field_name), _py_get_expr(field.type.expr), field.py_listtype, field.py_listsize)
-            _py('        count += len(self.%s.buf())', _n(field.field_name))
+            _py('        self.%s = xcb.List(parent, offset, %s, %s, %d)', _n(field.field_name), _py_get_expr(field.type.expr), field.py_listtype, field.py_listsize)
+            _py('        offset += len(self.%s.buf())', _n(field.field_name))
         elif field.type.is_container and field.type.fixed_size():
-            _py('        self.%s = %s(self, count, %s)', _n(field.field_name), field.py_type, field.type.size)
-            _py('        count += %s', field.type.size)
+            _py('        self.%s = %s(parent, offset, %s)', _n(field.field_name), field.py_type, field.type.size)
+            _py('        offset += %s', field.type.size)
         else:
-            _py('        self.%s = %s(self, count)', _n(field.field_name), field.py_type)
-            _py('        count += len(self.%s)', _n(field.field_name))
+            _py('        self.%s = %s(parent, offset)', _n(field.field_name), field.py_type)
+            _py('        offset += len(self.%s)', _n(field.field_name))
 
     (format, size, list) = _py_flush_format()
     if len(list) > 0:
         if need_alignment:
-            _py('        count += xcb.type_pad(4, count)')
-        _py('        (%s,) = unpack_from(\'%s\', self, count)', list, format)
-        _py('        count += %d', size)
+            _py('        offset += xcb.type_pad(4, offset)')
+        _py('        (%s,) = unpack_from(\'%s\', parent, offset)', list, format)
+        _py('        offset += %d', size)
 
     if self.fixed_size() or self.is_reply:
-        if len(self.fields) > 0:
+        if self.fields and not all(field.auto or field.type.is_pad for field in self.fields):
             _py_popline()
 
 def py_struct(self, name):
@@ -359,11 +358,12 @@ def py_struct(self, name):
     else:
         _py('    def __init__(self, parent, offset):')
         _py('        xcb.Struct.__init__(self, parent, offset)')
+        _py('        base = offset')
 
     _py_complex(self, name)
 
     if not self.fixed_size():
-        _py('        xcb._resize_obj(self, count)')
+        _py('        xcb._resize_obj(self, offset - base)')
 
 def py_union(self, name):
     '''
@@ -380,25 +380,28 @@ def py_union(self, name):
     else:
         _py('    def __init__(self, parent, offset):')
         _py('        xcb.Union.__init__(self, parent, offset)')
-
-    _py('        count = 0')
+        _py('        size = 0')
 
     for field in self.fields:
         if field.type.is_simple:
-            _py('        self.%s = unpack_from(\'%s\', self)', _n(field.field_name), field.type.py_format_str)
-            _py('        count = max(count, %s)', field.type.size)
+            _py('        self.%s = unpack_from(\'%s\', parent, offset)', _n(field.field_name), field.type.py_format_str)
+            if not self.fixed_size():
+                _py('        size = max(size, %s)', field.type.size)
         elif field.type.is_list:
-            _py('        self.%s = xcb.List(self, 0, %s, %s, %s)', _n(field.field_name), _py_get_expr(field.type.expr), field.py_listtype, field.py_listsize)
-            _py('        count = max(count, len(self.%s.buf()))', _n(field.field_name))
+            _py('        self.%s = xcb.List(parent, offset, %s, %s, %s)', _n(field.field_name), _py_get_expr(field.type.expr), field.py_listtype, field.py_listsize)
+            if not self.fixed_size():
+                _py('        size = max(size, len(self.%s.buf()))', _n(field.field_name))
         elif field.type.is_container and field.type.fixed_size():
-            _py('        self.%s = %s(self, 0, %s)', _n(field.field_name), field.py_type, field.type.size)
-            _py('        count = max(count, %s)', field.type.size)
+            _py('        self.%s = %s(parent, offset, %s)', _n(field.field_name), field.py_type, field.type.size)
+            if not self.fixed_size():
+                _py('        size = max(size, %s)', field.type.size)
         else:
-            _py('        self.%s = %s(self, 0)', _n(field.field_name), field.py_type)
-            _py('        count = max(count, len(self.%s))', _n(field.field_name))
+            _py('        self.%s = %s(parent, offset)', _n(field.field_name), field.py_type)
+            if not self.fixed_size():
+                _py('        size = max(size, len(self.%s))', _n(field.field_name))
 
     if not self.fixed_size():
-        _py('        xcb._resize_obj(self, count)')
+        _py('        xcb._resize_obj(self, size)')
 
 def _py_reply(self, name):
     '''
@@ -409,8 +412,8 @@ def _py_reply(self, name):
     _py_setlevel(0)
     _py('')
     _py('class %s(xcb.Reply):', self.py_reply_name)
-    _py('    def __init__(self, parent):')
-    _py('        xcb.Reply.__init__(self, parent)')
+    _py('    def __init__(self, parent, offset=0):')
+    _py('        xcb.Reply.__init__(self, parent, offset)')
 
     _py_complex(self, name)
     
@@ -537,8 +540,8 @@ def py_event(self, name):
     _py_setlevel(0)
     _py('')
     _py('class %s(xcb.Event):', self.py_event_name)
-    _py('    def __init__(self, parent):')
-    _py('        xcb.Event.__init__(self, parent)')
+    _py('    def __init__(self, parent, offset=0):')
+    _py('        xcb.Event.__init__(self, parent, offset)')
 
     _py_complex(self, name)
 
@@ -556,8 +559,8 @@ def py_error(self, name):
     _py_setlevel(0)
     _py('')
     _py('class %s(xcb.Error):', self.py_error_name)
-    _py('    def __init__(self, parent):')
-    _py('        xcb.Error.__init__(self, parent)')
+    _py('    def __init__(self, parent, offset=0):')
+    _py('        xcb.Error.__init__(self, parent, offset)')
 
     _py_complex(self, name)
 
-- 
1.7.6



More information about the Xcb mailing list