Come liberare un oggetto C ++ incartato quando un oggetto Javascript associato è garbage collection in V8?

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

  •  05-07-2019
  •  | 
  •  

Domanda

La documentazione di V8 spiega come creare un oggetto Javascript che avvolge un oggetto C ++ . L'oggetto Javascript mantiene un puntatore a un'istanza di oggetto C ++. La mia domanda è, diciamo che crei l'oggetto C ++ nell'heap, come puoi ricevere una notifica quando l'oggetto Javascript viene raccolto da gc, così puoi liberare l'oggetto C ++ allocato nell'heap?

È stato utile?

Soluzione

Il trucco è creare un Persistent handle (secondo punto elenco dal riferimento all'API collegata: " MakeWeak() gli handle non sono mantenuti su uno stack e vengono eliminati solo quando vengono rimossi in modo specifico. ... Utilizzare un handle persistente quando è necessario mantenere un riferimento a un oggetto per più di una chiamata di funzione o quando la durata dell'handle non corrisponde agli ambiti C ++. & Quot;) e chiamare Persistent::MakeWeak su di esso, passando una funzione di callback che eseguirà la pulizia necessaria (" Un handle persistente può essere indebolito, usando WeakReferenceCallback, per attivare un callback dal garbage collector quando i soli riferimenti a un oggetto provengono da handle persistenti deboli. " - cioè quando tutti gli handle " normali " sono usciti dall'ambito e quando il garbage collector sta per eliminare l'oggetto).

La firma del metodo MakeWeak è:

void MakeWeak(void* parameters, WeakReferenceCallback callback);

Dove Persistent<Object> è definito come un puntatore a funzione che accetta due parametri:

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

Questi si trovano nel file di intestazione v8.h distribuito con V8 come API pubblica.

Si desidera che la funzione che si passa a void* parameter ripulisca il parametro <=> oggetto che gli verrà passato quando viene chiamato come callback. Il parametro <=> può essere ignorato (oppure <=> può puntare a una struttura C ++ che contiene gli oggetti che devono essere ripuliti):

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

Altri suggerimenti

In generale, se un linguaggio raccolto in modo errato può contenere riferimenti a risorse esterne al motore del linguaggio (file, socket o, nel caso specifico, oggetti C ++), è necessario fornire un metodo "close" per rilasciare tale risorsa al più presto, no punto in attesa che il GC ritenga che valga la pena distruggere il tuo oggetto.

peggiora se il tuo oggetto C ++ ha fame di memoria e l'oggetto garbage collection è solo un riferimento: potresti allocare migliaia di oggetti e il GC vede solo pochi KB di piccoli oggetti, non abbastanza per innescare la raccolta; mentre il lato C ++ è alle prese con decine di megabyte di oggetti stantii.

Esegui tutto il tuo lavoro in un ambito chiuso (di oggetto o funzione). Quindi puoi rimuovere in modo sicuro l'oggetto C ++ quando sei uscito dall'ambito. GC non controlla i puntatori per l'esistenza di oggetti appuntiti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top