Table of Contents
Commit 2008-04-08
Modifs
Mailleur Gen4
- Possibilité de mailler des aspérités microscopiques (stage Arcelor): certaines tolérances dans la détection de lignes parallèles n'étaient pas adimensionnelles.
Opérateurs Vecteur → Scalaire
- utilisation de compteurs de références unifiés (SWIG/python/C++) pour ces objets simples. L'idée est de remplacer progressivement le mécanisme utilisé actuellement (
DISOWN
) au profit de celui-ci.
Petite explication sur la gestion mémoire Python/C++
Initialement
Tout d'abord, considérons aucun mécanisme de gestion de mémoire. On va créer un objet SumOperator
et le passer à un autre objet:
sum = SumOperator() valuesmanager.add(1, extractor, sum)
Dans ce cas, l'objet appartient plutôt à python qu'au au C++. Tout va bien fonctionner tant que python garde une référence vers sum
. Par contre, si python détruit sum
(ou si le C++ le fait), ça risque de planter de l'autre côté.
Au début, on a utilisé cette manière de faire en déclarant implicitemenet que python gérait l'objet. Autrement dit, le C++ ne détruit jamais l'objet, et tout va bien.
Cependant, si ces opérations se passent dans une fonction, il y a un problème:
def buildCurves(): sum = SumOperator() valuesmanager.add(1, extractor, sum)
à la sortie de la fonction, python va détruire sum
et le C++ aura en main une référence invalide. On ne peut pas non plus écrire ceci (pourtant très clair et concis):
valuesmanager.add(1, extractor, SumOperator())
L'objet temporaire va être détruit dès la sortie de la fonction par python…
Les fonctions (PieceWiseLinearFunction
& co) ont longtemps été gérées comme ça. c'est pour ça qu'il fallait toujours garder une ref python sur elles (et qu'on les définisaient en début de fichier, hors de toute fonction, comme variable globale du module).
Utilisation explicite de ''thisown''
Pour s'en sortir, on peut indiquer de manière explicite que python ne gère plus l'objet:
def buildCurves(): sum = SumOperator() valuesmanager.add(1, extractor, sum) sum.thisown=0
Ca marche mais on risque un memory leak (si le C++ ne libère pas la mémoire) ou le plantage (si on oublie le thisown
). Actuellement, les fenêtres VizWin
sont toujours gérées de cette manière…
Utilisation implicite de DISOWN
Pour que python ne détruise plus la référence, il est possible de faire en sorte que le C++ s'accapare la référence en utilisant le mécanisme DISOWN
de SWIG:
En gros, tout objet passé comme argument DISOWN
n'est plus détruit par python. On peut donc (on doit) le détruire en C++. Ceci permet de résoudre les deux problèmes précédents.
Cependant, on ne peut toujours pas écrire ceci:
sum = SumOperator() valuesmanager.add(1, extractor1, sum) valuesmanager.add(2, extractor2, sum)
En effet, dans ce cas, le C++ va détruire 2x l'objet sum
(avec un beau plantage à la sortie de Metafor).
Autre problème: si jamais on fait un valuesmanager.clear()
, on se retrouve avec une référence python (sum
) qui pointe vers un objet invalide (puisque le C++ l'a supprimé)
Actuellement, l'objet AleMethod
est géré de cette manière.
Compteurs de référence + DISOWN
L'idée qui nous est venue est donc de compter les références en C++. Pour ce faire, on dérive l'objet d'une classe (RefCounted
) qui compte le nombre de fois que l'objet est référencé. ceci résout le problème des deux courbes utilisant le même opérateur… mais pas celui de la référence invalide lors du valuesmanager.clear()
Actuellement, Luc est passé sur pas mal de trucs récemment (en particulier les fonctions d'évolution) pour utiliser cette manière de faire.
Solution "singleton"
Cette solution ne fonctionne qu'avec des objets très particuliers comme par exemple les opérateurs. Il suffit de déclarer les opérateurs comme singleton:
sum = SumOperator.getInstance() valuesmanager.add(1, extractor1, sum)
Ca résout tous les problèmes mais c'est très laid (et c'est inutilisable pour la majorité des classes). Bref, ça n'existe plus! ouf!
Solution ultime
C'est la solution implémentée dans ce commit. Il s'agit de supprimer le DISOWN
et de dire à SWIG d'utiliser le mécanisme de compteurs de références, même en python, et de manière implicite! (trop fort SWIG!).
Dans ce cas, tout est possible. En pratique, un objet géré de cette manière est libéré quand toutes les références vers lui sont supprimées, qu'elles soient python ou C++.
Un objet de ce type réagit exactement comme un objet codé en python pur; ce qui facilite la compréhension du mécanisme par l'utilisateur (encore faut-il avoir compris le mécanisme de python…).
En résumé:
- avant:
valuesmanager.add(1, extractor, SumOperator.getInstance())
- maintenant:
valuesmanager.add(1, extractor, SumOperator())
Projet
Fichiers ajoutés/supprimés
— Romain BOMAN 2008/04/08 11:53