Comment libérer un objet C ++ encapsulé lorsqu'un objet Javascript associé est récupéré dans V8?

StackOverflow https://stackoverflow.com/questions/173366

  •  05-07-2019
  •  | 
  •  

Question

La documentation de la V8 explique comment créer un objet Javascript qui encapsule un objet C ++ . L'objet Javascript conserve un pointeur sur une instance d'objet C ++. Ma question est la suivante: supposons que vous créiez l’objet C ++ sur le tas, comment pouvez-vous recevoir une notification lorsque l’objet Javascript est collecté par le gc, de sorte que vous puissiez libérer l’objet C ++ alloué au tas?

Était-ce utile?

La solution

L'astuce consiste à créer un Persistent descripteur (le deuxième point de la référence d'API liée: " MakeWeak() n'est pas conservé sur une pile et n'est supprimé que lorsque vous les supprimez spécifiquement. ... Utilisez un descripteur persistant lorsque vous devez conserver une référence à un objet pour plusieurs appels de fonction ou lorsque la durée de vie du descripteur ne correspond pas aux étendues C ++. & Quot;), puis appelez-la Persistent::MakeWeak, passer une fonction de rappel qui effectuera le nettoyage nécessaire (&); Un descripteur persistant peut être affaibli à l’aide de WeakReferenceCallback pour déclencher un rappel depuis le garbage collector lorsque les seules références à un objet proviennent de descripteurs persistants faibles. & "; C’est-à-dire que tous les &"; poignées & "régulières sont hors de portée et que le ramasse-miettes est sur le point de supprimer l’objet).

La MakeWeak signature de la méthode est:

void MakeWeak(void* parameters, WeakReferenceCallback callback);

Persistent<Object> est défini comme un pointeur à une fonction prenant deux paramètres:

typedef void (*WeakReferenceCallback)(Persistent<Object> object,
                                      void* parameter);

Celles-ci se trouvent dans le fichier d'en-tête v8.h distribué avec V8 en tant qu'API publique.

Vous voudriez que la fonction que vous passez à void* parameter élimine le paramètre d'objet <=> qui lui sera transmis lorsqu'il sera appelé en tant que rappel. Le paramètre <=> peut être ignoré (ou le <=> peut pointer sur une structure C ++ contenant les objets à nettoyer):

void CleanupV8Point(Persistent<Object> object, void*)
{
    // do whatever cleanup on object that you're looking for
    object.destroyCppObjects();
}

Parameter<ObjectTemplate> my_obj(ObjectTemplate::New());

// when the Javascript part of my_obj is about to be collected
// we'll have V8 call CleanupV8Point(my_obj)
my_obj.MakeWeak(NULL, &CleanupV8Point);

Autres conseils

En général, si un langage mal ordonné peut contenir des références à des ressources extérieures au moteur de langage (fichiers, sockets ou, dans votre cas, d'objets C ++), vous devez fournir une méthode 'close' pour libérer cette ressource dès que possible, non. attendez que le GC pense qu'il vaut la peine de détruire votre objet.

cela empire si votre objet C ++ a besoin de beaucoup de mémoire et que l'objet récupéré n'est qu'une référence: vous pouvez allouer des milliers d'objets et le GC ne voit que quelques Ko d'objets minuscules, pas assez pour déclencher la collecte; tandis que la partie C ++ se débat avec des dizaines de mégaoctets d'objets périmés.

Faites tout votre travail dans une portée fermée (d’objet ou de fonction). Ensuite, vous pouvez supprimer en toute sécurité l'objet C ++ lorsque vous êtes sorti de la portée. GC ne vérifie pas l'existence de pointeurs dans les pointeurs.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top