2008-10-06 7 views
23

Die Dokumentation von V8 erklärt how to create a Javascript object that wraps a C++ object. Das JavaScript-Objekt enthält einen Zeiger auf eine C++ - Objektinstanz. Meine Frage ist, sagen wir, Sie erstellen das C++ - Objekt auf dem Heap, wie können Sie eine Benachrichtigung erhalten, wenn das Javascript-Objekt von der GC gesammelt wird, so dass Sie das Heap zugeordneten C++ - Objekt freigeben können?Wie befreit man ein umschlossenes C++ - Objekt, wenn das assoziierte Javascript-Objekt in V8 gesammelt wird?

Antwort

22

Der Trick ist, einen Persistent Griff (zweiter Punkt aus der Linked-API-Referenz zu erzeugen. "Persistent Griffe sind nicht auf einem Stapel gehalten und werden nur gelöscht, wenn Sie sie gezielt entfernen ... Verwenden Sie eine persistente wenn Sie einen Verweis auf ein Objekt für mehr als einen Funktionsaufruf behalten müssen oder wenn die Zugriffszeiten nicht C++ - Bereichen entsprechen. "), und rufen Sie MakeWeak() darauf an, übergeben Sie eine Rückruffunktion, die die erforderliche Bereinigung durchführt (" A persistentes Handle kann mit Persistent::MakeWeak schwach gemacht werden, um einen Rückruf vom Garbage Collector auszulösen, wenn die einzigen Verweise auf ein Objekt aus schwachen persistenten Handles stammen. "- Das heißt, wenn alle" normalen "Handles den Gültigkeitsbereich verlassen haben der Garbage Collector wird das Objekt löschen).

Die Persistent::MakeWeak Methodensignatur ist:

void MakeWeak(void* parameters, WeakReferenceCallback callback); 

Wo WeakReferenceCallback als Zeiger-to-Funktion nimmt zwei Parameter definiert ist:

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

Diese sind in der Header-Datei gefunden v8.h verteilten mit V8 als öffentliche API.

Sie möchten, dass die Funktion, die Sie an MakeWeak übergeben, den Objektparameter bereinigt, der an ihn übergeben wird, wenn er als Rückruf aufgerufen wird. Der void* parameter Parameter kann ignoriert werden (oder die void* parameter auf eine C++ Struktur zeigen kann, die die Objekte enthält, die brauchen Reinigung):

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); 
+0

Wie machst du das für einen Local ? Ich versuche es aus meinem Konstruktor FunctionTemplate heraus zu tun. Ich kann mir keine Syntax ausdenken, die mich nicht anschreien würde. Versuchte .MakeWeak, aber das existiert nicht, versuchte Persistent :: New, aber es wollte einen Zeiger auf mein Objekt und mein Compiler würde mich nicht einen Zeiger auf ein lokales Objekt erstellen lassen. – xaxxon

+0

@xaxxon: Ich werde der Erste sein, der zugibt, dass ich keine Erfahrung mit der V8-Javascript-Engine habe (ich konnte zufällig die Antwort auf diese Frage aus der Dokumentation vor sechs Jahren finden). Ich ** denke ** die Antwort auf Ihre Frage ist das Beispiel auf https://developers.google.com/v8/embed?csw = 1 # dynamisch, aber es ist auch möglich, dass Sie eine Frage haben, die sich lohnt, selbst zu fragen. –

+0

Danke. Ich habe es schließlich herausgefunden. https://code.google.com/p/chromium/codesearch#chromium/src/v8/src/d8.cc&l=1064 beginnend um Linie 1400 – xaxxon

0

Wenn eine von Garbage Collection erfasste Sprache Referenzen auf Ressourcen außerhalb der Sprachengine (Dateien, Sockets oder in Ihrem Fall C++ - Objekte) enthalten kann, sollten Sie eine 'close'-Methode bereitstellen, um diese Ressource so schnell wie möglich freizugeben. Kein Punkt wartet, bis der GC denkt, dass es sich lohnt, dein Objekt zu zerstören.

wird es schlimmer, wenn Ihr C++ - Objekt speicherhungrig ist und das Garbage-Collected-Objekt nur eine Referenz ist: Sie können Tausende von Objekten zuweisen, und der GC sieht nur ein paar KB winziger Objekte, nicht genug, um die Sammlung auszulösen ; während die C++ - Seite mit einigen zehn Megabytes veralteter Objekte zu kämpfen hat.

+2

, deshalb, V8 die Funktion gibt es :: AdjustAmountOfExternalAllocatedMemory() ... Auf diese Weise können Sie Sag V8, dass dein Objekt hungrig ist ... :-) – nalply

0

Machen Sie alle Ihre Arbeit in einem geschlossenen Bereich (von Objekt oder Funktion). Dann können Sie das C++ - Objekt sicher entfernen, wenn Sie den Gültigkeitsbereich verlassen haben. GC überprüft keine Zeiger auf das Vorhandensein von spitzen Objekten.

Verwandte Themen