Como você liberar um objeto envolto C ++ quando associado objeto Javascript é lixo recolhido em V8?

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

  •  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 ++?

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top