Great that it fixed the leak, thanks for testing!

I've studied my circular reference problem a bit more and I found that
the reference count that keeps __del__ from being called seems to be
on gobject level.  I printed out the reference counts on both gobject
and python objects and it's only the gobject refcounts that get
stepped:


class AnimatedLabel(clutter.Label)
    def __init__(self):
        ...
        self.behaviour = clutter.BehaviourDepth(...)
        self.behaviour.apply(self)   <--- self.__grefcount__ stepped
        ...


Disposing the Behaviour object would unref all applied Actors but the
cyclic reference keeps both objects alive.  One could of course add
something like this on all similar widgets implemented in python, but
it doesn't seem very "pythonic" to me:


    def prepare_for_delete(self):
        self.behaviour = None


By the way, I found a trick to store actor specific Behaviour in
inherited actor itself without creating pygobject level cycle:


class AnimatedLabel(clutter.Label)
    def __init__(self):
        ...
        behaviour = clutter.BehaviourDepth(...)
        behaviour.apply(self)
        self.set_data('behaviour', behaviour)
        ...

    def __del__(self):
        self.get_data('behaviour',).remove(self)
        # or even
        # self.set_data('behaviour', None)


I'm not familiar with gobject/pygobjetc so I don't know if this is
abusing the purpose of set_data()/get_data().  This trick would save
some of the trouble manually managing the lifetime of python-level
widgets and still let me benefit from inheritance...

--
Tero


On Feb 16, 2008 2:10 AM, Kashyap Ashwin <[EMAIL PROTECTED]> wrote:
> Yes, it seems fixed. The #refs now are stable and memory seems to be
> freed. I don't think you need to call gc.collect() for all this to work.
> I tested this briefly.
> Your original problem, where you derive from clutter.Texture is still
> leaking. However, if you convert the inherited class and instead have a
> member variable, the leaks do not happen. In the inherited class,
> __del__ is never called - so it leaks inspite of calling gc.collect()
> every so often!.
> Also, the gstreamer problem with NULL state will still bite you. To fix
> it, in __del__, set state to STATE_NULL.
>
> Here is some a repost of the code that does not to leak for me:
>
> import clutter
> import gc
> import time
> import sys
>
> stage = None
> my_label = None
>
> #gc.set_debug(gc.DEBUG_STATS)
>
> class AnimatedLabel():
>
>     def __init__(self):
>         print 'INIT %s' % self
>         self.label = clutter.Label()
>         self.timeline = clutter.Timeline(duration=1000)
>         self.timeline.set_loop(True)
>         self.alpha = clutter.Alpha(self.timeline, clutter.ramp_func)
>         self.behaviour = clutter.BehaviourDepth(alpha=None,
> depth_start=0, depth_end=200)
>         self.behaviour.apply(self.label)
>         self.timeline.start()
>
>     def __del__(self):
>         print '#alph:', sys.getrefcount(self.alpha)
>         print '#beh:', sys.getrefcount(self.behaviour)
>         print '#tim:', sys.getrefcount(self.timeline)
>         #del self.alpha       # no need
>         #del self.behaviour   # no need
>         print 'DEL %s' % self
>
> def on_key_press_event(a,b):
>     global my_label
>     stage.remove(my_label.label)
>
>     # would do anything to get rid of the old object ;)
>     del my_label
>     my_label = None
>     #print gc.get_objects()[-5:]
>     # print "gc_len:", len(gc.get_objects())
>     # gc.collect()  # no need
>
>     my_label = AnimatedLabel()
>     my_label.label.set_text(time.ctime())
>     my_label.label.set_position(100,100)
>     stage.add(my_label.label)
>     my_label.label.show()
>
>
> stage = clutter.stage_get_default()
> stage.set_size(320,240)
> stage.connect('key-press-event', on_key_press_event)
>
> my_label = AnimatedLabel()
> my_label.label.set_text(time.ctime())
> my_label.label.set_position(100,100)
> stage.add(my_label.label)
> stage.show_all()
>
>
> -Ashwin
>
>
-- 
To unsubscribe send a mail to [EMAIL PROTECTED]

Reply via email to