Como você liberar um objeto envolto C ++ quando associado objeto Javascript é lixo recolhido em V8?
-
05-07-2019 - |
Pergunta
documentação do V8 explica como criar um objeto Javascript que envolve um objeto C ++ . O objecto Javascript segura a um ponteiro para uma instância do objecto C ++. A minha pergunta é, vamos dizer que você criar o objeto C ++ na pilha, como você pode obter uma notificação quando o objeto Javascript é recolhido pelo gc, para que possa libertar da pilha alocada objeto C ++?
Solução
O truque é criar um identificador Persistent
(segundo ponto do-linked a referência API:. "Alças Persistent
não são realizadas em uma pilha e só são excluídos quando você especificamente removê-los ... Use uma conexão persistente quando você precisa manter uma referência a um objeto para mais de uma chamada de função, ou quando vidas punho não correspondem a C escopos ++. "), e MakeWeak()
chamada nele, passando uma função de retorno de chamada que vai fazer a limpeza necessária (" a persistente punho pode ser feito fraco, usando Persistent::MakeWeak
, para desencadear uma chamada de retorno a partir do coletor de lixo quando as únicas referências a um objeto são de fracos alças persistentes." - isto é, quando todos os 'pegas regulares' ter ido fora do escopo e quando o coletor de lixo está prestes a excluir o objeto).
A assinatura do método Persistent::MakeWeak
é:
void MakeWeak(void* parameters, WeakReferenceCallback callback);
Onde WeakReferenceCallback
é definido como uma função de ponteiro-para-tomar dois parâmetros:
typedef void (*WeakReferenceCallback)(Persistent<Object> object,
void* parameter);
Estes são encontrados no arquivo de cabeçalho v8.h distribuído com V8 como a API pública.
Você iria querer a função que você passar para MakeWeak
para limpar o parâmetro de objeto Persistent<Object>
que serão passados ??a ele quando ele é chamado como um callback. O parâmetro void* parameter
pode ser ignorada (ou o void* parameter
pode apontar para uma estrutura de C ++ que contém os objetos que precisam de limpeza para cima):
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);
Outras dicas
Em geral, se uma linguagem de coleta de lixo pode conter referências a recursos externos do motor idioma (arquivos, soquetes, ou no seu caso C ++ objetos), você deve fornecer um método 'fechar' para liberar esse recurso o mais rápido possível, não ponto de esperar até que o GC acha que vale a pena destruir seu objeto.
fica pior se o objeto do C ++ é uma memória de fome e o objeto coleta de lixo é apenas uma referência: você pode alocar milhares de objetos, eo GC só vê objetos minúsculos a poucos de KB, não o suficiente para coleta de gatilho; enquanto o lado do C ++ está lutando com dezenas de megabytes de objetos antigos.
Faça todo o seu trabalho em algum espaço fechado (de objeto ou função). Depois, você pode remover com segurança o objeto C ++ quando você foi fora do escopo. O GC não verificar ponteiros para a existência de objetos pontiagudos.