Aquisição de Recurso é Inicialização

Origem: Wikipédia, a enciclopédia livre.
Ir para: navegação, pesquisa

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ória[1] . 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ções[2] .

Uso[editar | editar código-fonte]

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 | editar código-fonte]

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 | editar código-fonte]

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 ...   
 
    } 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

  1. Bjarne Stroustrup (abril de 2001). Exception Safety: Concepts and Techniques (PDF).
  2. Herb Sutter. Exceptional C++. [S.l.]: Addison-Wesley, 1999. ISBN 0-201-61562-2.