2017-08-19 4 views
2

Ma classe ressemble à ceci:Comment puis-je obtenir le garbage collector Lisp pour supprimer la mémoire étrangère C++ allouée dans mes emplacements de classe?

(defclass matrix() 
    ((rows :initarg :rows :initform 2) 
    (cols :initarg :cols :initform 2) 
    (matrix :accessor matrix))) 

J'ai une spécialisation de la méthode instance d'initialisation qui crée l'objet pour la fente de la matrice en appelant une bibliothèque C++. J'ai une fonction matrix-destroy qui va libérer la mémoire allouée en C++.

Ce que je veux, c'est que le garbage collector puisse appeler matrix-destroy sur l'emplacement matriciel. Existe-t-il une manière idiomatique de le faire en langage courant?

+3

Vous pouvez définir un finaliseur pour l'objet. Comment cela se passe dépend de la mise en œuvre de Lisp, mais vous pouvez utiliser la [Trivial Garbage] (https://common-lisp.net/project/trivial-garbage/) pour le faire de manière portable. – jkiiski

+0

@jkiiski avez-vous un lien vers un exemple de code utilisant des ordures triviales? Je viens de vérifier sa documentation et il semble rare. En fait, je viens de vérifier l'index de Common Lisp Recipies et il y a une discussion sur les finaliseurs donc je vais le lire, mais un lien serait bien. – mcheema

+3

SBCL manuel a un court [exemple] (http://www.sbcl.org/manual/#Garbage-Collection) pour savoir comment l'utiliser. Fondamentalement, il suffit d'appeler 'FINALIZE' sur l'objet après l'avoir créé (assurez-vous de ne pas faire référence à l'objet lui-même dans la fonction de finalisation.) Vous pouvez vous référer à la poignée étrangère). Vous pouvez également voir [cl-sdl2] (https://github.com/lispgames/cl-sdl2), qui utilise des finaliseurs pour libérer des surfaces/textures/etc. (voir ['SDL-COLLECT'] (https://github.com/lispgames/cl-sdl2/blob/master/src/sdl2.lisp) pour l'emplacement du finaliseur). – jkiiski

Répondre

3

Pour exécuter une fonction après que le garbage collector a collecté un objet, vous devez définir un finaliseur pour cet objet. La norme Common Lisp n'inclut pas les finaliseurs, mais les implémentations les fournissent. Il existe une bibliothèque de compatibilité appelée Trivial Garbage que vous pouvez utiliser pour les définir de manière portative.

La définition d'un finaliseur se fait simplement en appelant FINALIZE sur l'objet auquel vous souhaitez attacher le finaliseur. La fonction de finalisation ne doit contenir aucune référence à l'objet lui-même, car cela empêcherait sa collecte. Vous devez également garder à l'esprit que le finaliseur peut être exécuté à tout moment dans n'importe quel thread, il doit donc être réentrant et ne pas dépendre d'un environnement dynamique spécifique.

Le manuel SBCL contient un court exemple de finaliseurs dans 7.4 Garbage Collection. Vous pouvez également voir un projet existant qui les utilise, tel que cl-sdl2, qui les utilise pour libérer des surfaces SDL, des textures et autres. Voir SDL-COLLECT pour l'emplacement du finaliseur et CREATE-RGB-SURFACE pour un exemple d'où SDL-COLLECT est appelé.