close Warning: Can't synchronize with repository "(default)" (/var/svn/tolp does not appear to be a Subversion repository.). Look in the Trac log for more information.

Opened 15 years ago

Closed 15 years ago

#863 closed defect (remind)

Object decompilation, when a object contains a reference to itself

Reported by: pgea@… Owned by: Víctor de Buen Remiro
Priority: normal Milestone: OOP Implementation
Component: OOP Version:
Severity: major Keywords:
Cc:

Description

El problema surge a la hora de gestionar objetos que contienen otros objetos y se desea que un objeto contenido conozca al objeto que lo contiene.

Para motivar esto podemos considerar una situación interesante que surge cuando se almacenan estructuras similares a grafos. Veamos un ejemplo:

Imaginemos una clase grafo (@Graph) que contiene un conjunto de vértices (@Vertex) y otro de aristas (@Edge). Los objetos aristas, a su vez contienen referencias a los dos vértices que unen.

Imaginemos ahora pues, que queremos desde un objeto vértice conocer todas las aristas que le apuntan. O incluso más queremos eliminarlas todas.
Parece lógico que esta acción implica la colaboración del objeto grafo.
Así si se llamara a un método del vértice GetEdges() éste llamaría a su padre preguntándoselas: algo como parent::GetEdgesWithVertex(él_mismo).
O incluso: parent::RemoveEdgesWithVertex(él_mismo).

El problema al tratar este tipo de referencias, donde el objeto contiene objetos que lo referencian, es que los objetos no se decompilan adecuadamente.

Adjunto un ejemplo sencillo, donde si no se limpia el contenedor (método Clear) no puede decompilarse y compilarse nuevamente.

En MMS esta cuestión se ha tratado usando direcciones de memoria (GetAddressFromObject y GetObjectFromAddress) aunque este modo además de artificial y poco elegante dificulta la copia de los objetos y en ocasiones genera algún error debido a la desaparición de la referencia del objeto cuya dirección se apuntó.

Attachments (2)

ticket_17.ObjectDecompilation.tol (495 bytes) - added by pgea@… 15 years ago.
ticket_17B.ObjectDecompilation.tol (2.0 KB) - added by pgea@… 15 years ago.

Download all attachments as: .zip

Change History (7)

Changed 15 years ago by pgea@…

comment:1 Changed 15 years ago by Víctor de Buen Remiro

Yo creo que lo más apropiado sería definir un destructor en esa clase que llamara al método Clear

comment:2 Changed 15 years ago by pgea@…

Lo había probado pero no funciona.

En el ejemplo bastaría con añadir a @Container el método:

  Real __destroy(Real void) { Clear(?) };

Me da la impresión de que como existen dos referencias al mismo objeto algo falla.
Supongo que el primero en comenzar a destruirse es el exterior pero no lanza el __destroy porque aún queda la copia interior que pasaría a ser la única.
Luego ya no soy capaz de comprender muy bien qué pasa, pero no se llega a destruir el objeto.

comment:3 Changed 15 years ago by pgea@…

Creo que ya lo veo más claro:

Si creo un objeto A que contiene a otro objeto B que a su vez tiene una referencia a A, lo que tengo es lo siguiente: Dos objetos independientes y tres referencias.

Los objetos A y B como entes están en la memoria (objA) y (objB).
Tengo una referencia a A (refA1) que me permite acceder al objeto A (objA).
Desde éste (objA) encuentro una referencia a B (refB1) que me permite acceder
al objeto B (objB).
Desde el objeto B (objB) encuentro una referencia a A (refA2) que permite de nuevo acceder al objeto A (objA).

Cuando se decompila la referencia a A (refA1), la más exterior, el objeto no se destruye, pues aún queda otra referencia (refA2), y sólo se destruye la referencia exterior (refA1).
El problema es que los objetos quedan inaccesibles pues cada uno tiene una referencia al otro, pero ya no queda ninguna referencia útil.

El problema creo que no es nada novedoso y parece que en otros lenguajes ya han implementado un recolector de este tipo de basura. Aunque éste puede que sea algo ineficaz:
http://www.amk.ca/python/2.0/index.html#SECTION000900000000000000000

Parece entonces que la solución más sencilla pasa por evitar crear estas estructuras cíclicas, o intentar usar algún remedio que evite esta situación.

comment:4 Changed 15 years ago by pgea@…

Se me ocurre una solución que permitiría evitar la existencia de referencias cíclicas por ahí sueltas que luego TOL no sabe decompilar.

Se trata de introducir una clase intermediaria que hace de interfaz a la que sufre las referencias cíclicas. Adjunto un ejemplo de cómo sería la implementación al estilo del ejemplo propuesto.

Changed 15 years ago by pgea@…

comment:5 Changed 15 years ago by Víctor de Buen Remiro

Resolution: remind
Status: newclosed

Entiendo que has encontrado una forma bastante razonable de salvar la situación por lo que en principio podemos postergar a resolución de este ticket para otro momento, si es que efectivamente es posible.

Note: See TracTickets for help on using tickets.