Resolve circular reference

  • Thread starter moerchendiser2k3
  • Start date
M

moerchendiser2k3

Hi,

I have a small problem with circular references. I embedded Python
into my app and I have two types which are flagged with
Py_TPFLAGS_BASETYPE so I can inherit Python types from these types.
Lets call my C types A and B.


Here is the dependency:

class Foo(A):
e=Bar()

class Bar(B):
def __init__(self, p):
self.p=p
i=Foo()
j=Bar(i)

Everything works fine, the problem starts when I start to make a
circular reference in Python. In my embedded app I have a reference to
instance A. When I decref this reference its still alive because the
instance j(Bar) makes this object still alive. Is there any chance to
force this? Because without A the instance A shouldnt be alive
anymore. Thanks for any hint!!

Bye
 
M

MRAB

Hi,

I have a small problem with circular references. I embedded Python
into my app and I have two types which are flagged with
Py_TPFLAGS_BASETYPE so I can inherit Python types from these types.
Lets call my C types A and B.


Here is the dependency:

class Foo(A):
e=Bar()

class Bar(B):
def __init__(self, p):
self.p=p
i=Foo()
j=Bar(i)

Everything works fine, the problem starts when I start to make a
circular reference in Python. In my embedded app I have a reference to
instance A. When I decref this reference its still alive because the
instance j(Bar) makes this object still alive. Is there any chance to
force this? Because without A the instance A shouldnt be alive
anymore. Thanks for any hint!!
Force what?

j refers to i, i refers to Foo, Foo refers to A. Therefore A should be
alive.
 
M

moerchendiser2k3

Force what?
j refers to i, i refers to Foo, Foo refers to A. Therefore A should be
alive.


Oh, sorry. Force the deletion of instance Foo(A) and Bar(B).
 
C

Carl Banks

Oh, sorry. Force the deletion of instance Foo(A) and Bar(B).

If you don't want j to keep i alive, you should look at weak
referencing. (Look at the documentation for the weakref module.
Also, this has nothing to do with A and B being C-defined types; this
exact same behavior would happen even with Python types.)


Carl Banks
 
M

moerchendiser2k3

so there is no chance without using weakrefs?
any ideas, tips, workarounds how I might handle this?

bye, moerchendiser2k3
 
C

Carl Banks

so there is no chance without using weakrefs?
any ideas, tips, workarounds how I might handle this?

No, sorry: as long as a reference to an object exists, the object is
never deleted. There is no way to get around this.

Python in general isn't designed to allow for exact control over the
destruction of objects. Even in CPython, which uses reference
counting, there are a bunch of situations where a reference might be
stored to an object that keeps it alive. (Unexpected locations where
a stray reference might exist: an unpickler object, the _ symbol in
the interactive shell.) Other implementations, like Jython and
IronPython, don't use reference counting and don't provide for any
particular time at all for an object to be destroyed.

The recommended way to ensure timely release of resources in Python is
to provide a method (such as close or finalize) to explicity release
the resource--the object then lives on in a zombie state. The with
statement can be used in many cases to avoid the need to call this
method explicitly. For example, if you were to run this code in
Python:

with open(filename) as f:
g = f
print g

It would print <closed file 'whatever' ...>. The object still exists
because there is a reference to it, but the file has been closed.


If you can tell us why it's so important that the object be destroyed
at that given time, even while a reference to it exists, maybe we can
give you better suggestions.


Carl Banks
 
M

moerchendiser2k3

If you can tell us why it's so important that the object be destroyed
at that given time, even while a reference to it exists, maybe we can
give you better suggestions.

Thanks for your answer! In my case the types A and B (in my example
above)
are a dialog and a dialog widget. At a special time I have to close
and
destroy all dialogs but this does not happen because the widget keeps
the dialog alive. I have the reference to the dialog
but after I closed the dialogs I also would like to destroy them
because
they have to free some special ressources.

Thanks a lot!! Bye, moerchendiser2k3
 
S

Stefan Behnel

moerchendiser2k3, 10.01.2011 18:55:
Thanks for your answer! In my case the types A and B (in my example
above)
are a dialog and a dialog widget. At a special time I have to close
and
destroy all dialogs but this does not happen because the widget keeps
the dialog alive. I have the reference to the dialog
but after I closed the dialogs I also would like to destroy them
because they have to free some special ressources.

Objects within a reference cycle will eventually get cleaned up, just not
right away and not in a predictable order.

If you need immediate cleanup, you should destroy the reference cycle
yourself, e.g. by removing the widgets from the dialog when closing it.

Stefan
 
M

moerchendiser2k3

moerchendiser2k3, 10.01.2011 18:55:



Objects within a reference cycle will eventually get cleaned up, just not
right away and not in a predictable order.

If you need immediate cleanup, you should destroy the reference cycle
yourself, e.g. by removing the widgets from the dialog when closing it.

Stefan

The PyWidget type does not own the widget, it just points to it. I
have an
idea, would this fix the problem?

I destroy the internal dictionary of the dialog which points to other
PyObjects?
Then I would cut the dependency.
 
S

Stefan Behnel

moerchendiser2k3, 10.01.2011 22:19:
The PyWidget type does not own the widget, it just points to it. I
have an idea, would this fix the problem?

I destroy the internal dictionary of the dialog which points to other
PyObjects? Then I would cut the dependency.

Sure, that should work.

Stefan
 
M

Magnus Lyckå

Everything works fine, the problem starts when I start to make a
circular reference in Python.

I didn't quite grok your example, but concerning CPython GC & circular
references...
.... def __del__(self):
.... print 'Deleted', self
....
 
H

Hrvoje Niksic

Magnus Lyckå said:

If your method has a __del__ at all, the automatic cyclic collector is
disabled. It detects the cycle, but it only stores the objects in
gc.garbage, to give you a chance to do something about them, such as
break the cycle(s) yourself. For example:
.... def __del__(self):
.... print 'deleted', self
....
a, b = X(), X()
a.cycle = b
b.cycle = a
del a, b
import gc
gc.collect() 4
gc.garbage
del gc.garbage[0].cycle
del gc.garbage[:]
deleted <__main__.X object at 0xb76d980c>
deleted <__main__.X object at 0xb76d84cc>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top