Aquisição de Recurso é Inicialização
Aquisição de Recurso é Inicialização (conhecido pelo acrônimo RAII para o termo em língua inglesa Resource Acquisition Is Initialization) é um padrão de projeto de software para C++ e D que combina a aquisição e liberação de recursos com inicialização e destruição de objetos.
O RAII atribui a propriedade de um recurso para objetos com escopo para o gerenciamento de memória1 . A aquisição é tipicamente associada a construção, e a destruição automática por perda de escopo é usada para garantir a liberação do recurso. Já que por escopo do objeto, a destruição é realizada independentemente de tratamento de exceções, a técnica RAII é um conceito chave na escrita de código seguro quanto a exceções2 .
Índice |
Uso [editar]
A técnica RAII é geralmente usadas para controlar a aquisição de um mutex em aplicações multitarefa. Outro uso são operações em arquivos. Um fluxo de dados para um determinado arquivo é aberto durante a construção do objeto, e o fechamento do arquivo é feito automaticamente na destruição do objeto de fluxo.
RAII é também usado para assegurar segurança quanto a exceções, tornando possível evitar vazamento de memória sem uso complexo de blocos try/catch.
Exemplo [editar]
A seguinte classe RAII é uma leve camada superior para as chamadas de gerenciamento de arquivos à biblioteca padrão do C.
#include <cstdio> class file { public: file( const char* filename ) : m_file_handle(std::fopen(filename, "w+")) { if( !m_file_handle ) throw std::runtime_error("file open failure") ; } ~file() { if( std::fclose(m_file_handle) != 0 ) { // lida-se com erros do sistema de arquivos, fclose() pode falhar } } void write( const char* str ) { if( std::fputs(str, m_file_handle) == EOF ) throw std::runtime_error("falha na escrita") ; } private: std::FILE* m_file_handle ; // atribuição e cópia não implementados, prevenindo o uso file( const file & ) ; file & operator=( const file & ) ; } ;
Pode-se usar a classe acima da seguinte forma:
void example_usage() { // abre o arquivo (adquire o recurso) file logfile("logfile.txt") ; logfile.write("hello logfile!") ; // continua usado logfile ... // lança exceções ou retorna sem se preocupar em fechar o recurso // ele é fechado automaticamente com a perda de escopo }
A essência do idioma RAII é que a classe file encapsula o gerenciamento do recurso FILE*.
Uso e alternativas em outras linguagens [editar]
Objetos Java são destruídos automaticamente em tempos indeterminados pelo coletor de lixo. Os recursos então devem ser manualmnete fechados pelo programador. O exemplo anterior deve ser escrito da seguinte maneira em Java:
void java_example() { // abre o arquivo (adquire o recurso) LogFile logfile = new LogFile("logfile.txt") ; try { logfile.write("hello logfile!") ; // continua usado logfile ... // lança exceções ou retorna sem se preocupar em fechar o recurso // ele é fechado automaticamente com a perda de escopo } finally { // fechamento explícito do recurso logfile.close(); } }
A responsabilidade de liberar o recurso recai sobre o programador em cada ponto onde o recurso é usado, e não de forma genérica em um local único.
Referências
- ↑ Bjarne Stroustrup (abril de 2001). Exception Safety: Concepts and Techniques (PDF).
- ↑ Herb Sutter. Exceptional C++. [S.l.]: Addison-Wesley, 1999. ISBN 0-201-61562-2
- Bjarne Stroustrup. resource acquisition is initialization (em inglês). Glossário de Bjarne Stroustrup.