Implementando a contagem de referência
A contagem de referência requer trabalho por parte do implementador de uma classe e dos clientes que usam objetos dessa classe. Ao implementar uma classe, você deve implementar os métodos AddRef e Release como parte da interface IUnknown. Esses dois métodos têm as seguintes implementações simples:
- AddRef incrementa a contagem de referência interna do objeto.
- A liberação primeiro diminui a contagem de referência interna do objeto e, em seguida, verifica se a contagem de referência caiu para zero. Se tiver, isso significa que ninguém está mais usando o objeto, então a função Release desaloca o objeto.
Uma abordagem de implementação comum para a maioria dos objetos é ter apenas uma implementação desses métodos (junto com QueryInterface), que é compartilhada entre todas as interfaces e, portanto, uma contagem de referência que se aplica ao objeto inteiro. No entanto, da perspectiva de um cliente, a contagem de referências é estrita e claramente uma noção por ponteiro de interface e, portanto, objetos que aproveitam esse recurso construindo, destruindo, carregando ou descarregando dinamicamente partes de sua funcionalidade com base nos ponteiros de interface atualmente existentes podem ser implementados. Estas são coloquialmente chamadas de interfaces de tear-off.
Sempre que um cliente chama um método (ou função de API), como QueryInterface, que retorna um novo ponteiro de interface, o método que está sendo chamado é responsável por incrementar a contagem de referência por meio do ponteiro retornado. Por exemplo, quando um cliente cria um objeto pela primeira vez, ele recebe um ponteiro de interface para um objeto que, do ponto de vista do cliente, tem uma contagem de referência de um. Se o cliente chamar AddRef no ponteiro da interface, a contagem de referência se tornará dois. O cliente deve chamar Release duas vezes no ponteiro da interface para descartar todas as suas referências ao objeto.
Um exemplo de como as contagens de referência são estritamente por ponteiro de interface ocorre quando um cliente chama QueryInterface no primeiro ponteiro para uma nova interface ou a mesma interface. Em qualquer um desses casos, o cliente é obrigado a chamar Release uma vez para cada ponteiro. COM não requer que um objeto retorne o mesmo ponteiro quando solicitado para a mesma interface várias vezes. (A única exceção a isso é uma consulta a IUnknown, que identifica um objeto para COM.) Isso permite que a implementação do objeto gerencie recursos de forma eficiente.
A segurança de threads também é uma questão importante na implementação do AddRef e do Release. Para obter mais informações, consulte Processos, threads e apartamentos.
Tópicos relacionados