Resource Acquisition Is Initialization |
Resource Acquisition Is Initialization (often referred to by the acronym RAII) is a popular programming technique in C plus plus and D programming language. The technique combines acquisition and release of resources with initialization and uninitialization of Variables.
The acquisition is bound to the construction (initialization) whereas the release is bound to the destruction (uninitialization) of the variable. Since a destructor of an automatic variable is called when leaving its scope, it can be guaranteed that the resource is released as soon as the variable s life time ends. This is also true for cases when an exception occurs. Thus, RAII is a key concept for writing exception aware code.
=Example=
Here is an example (in CPlusPlus) : class LogFile { public : LogFile(const char* fileName) : m_file( OpenFile(fileName) ) // initialize data member with the file handle { if( m_file == INVALID_HANDLE ) throw FileFailedToOpen(); } // handle errors automatically ~LogFile() { CloseFile(m_file); } void write(const char* logLine) { WriteFile( m_file, logLine ); } private : FILE_HANDLE m_file; //NB: in C++, a copy-constructor and assignment operator // should be provided, according to the Rule of Three of C++. };
This simple RAII class can be used like this : bool functionA() { LogFile log( Output log of functionA ); log.write( fun Step5 succeeded ); // The function can throw exceptions and return // without worrying about closing the log: if( ... ) throw FunctionAFailure(); // or return false return true; }
Without using RAII, each function using an output log would have to manage the FILE_HANDLE resource explicitly. For example, the equivalent implementation of functionA without using RAII would be: bool functionB() { try { FILE_HANDLE log = OpenFile( Output log of functionA ); // EXTRA CODE: explicit error checking: if( log == INVALID_HANDLE ) return false; WriteFile( log, fun Step5 succeeded ); // if the function needs to check for an error and abort accordingly: if( error ) { // EXTRA CODE: release the acquired resources CloseFile(log); return false; // or throw an exception } // EXTRA CODE: the resource needs to be closed explicitly CloseFile(log); // explicitly release the resource return true; } catch (...) { // An exception was thrown during the execution of the function // Time to cleanup the resources CloseFile(log); // Now handle the exception, or re-throw it, or return false } }
The essence of the RAII idiom is that the class LogFile encapsulates the management of an operating-system resource, the FILE_HANDLE . It guarantees that the resource will properly be disposed of at function exit. Furthermore, LogFile instances guarantee that a valid log file is available (by throwing an exception if the file could not be opened).
There s also a big problem in the presence of exceptions: in functionB , if more than one resource were allocated, but an exception was to be thrown between their allocations, there s no general way to know which resources need to be released in the final catch block - and releasing a not-allocated resource is usually a bad thing. RAII takes care of this problem; the automatic variables are destructed in the reverse order of their construction, and an object is only destructed if it was fully constructed (no exception was thrown inside its constructor). So functionB can never be as safe as functionA without special coding for each situation - like checking for invalid-default values, or nesting try-catch blocks.
This frees functionA from explicitly managing the resource as would otherwise be required. When several function use LogFile , this simplifies and reduces overall code size, and helps ensure program correctness.
Languages that do not support RAII, such as Java, provide an alternative solution to ensure that a resource will be released, with try-finally blocks. This allows to write correct code, but does not fully encapsulate the management of resources, as each and every function using LogFile may have to explicitly demand the destruction of the log file with a try-finally block.
=Typical Uses=
The RAII technique is typically used for controlling thread locks in multi-threaded applications. Another typical example of RAII is file operations, e.g. the C Plus Plus standard library s file-streams. An input file stream is opened in the object s constructor, and it is closed upon destruction of the object. Since C++ allows objects to be allocated on the Stack (computing), C++ s scoping mechanism can be used to control file access.
RAII is also used (as shown in the example above) to ensure exception safety. It is a very useful technique to avoid resource leaks without giving too much work to the developer, and is widely used in the software industry.
Furthermore the ownership of dynamically allocated memory (with new) can be controlled with RAII technique. For this purpose, the C++ Standard Library defines auto_ptr.
=Limitations=
RAII can only be used in languages that provide a deterministic destructor. In garbage-collected languages like Java_programming_language or C_sharp, the garbage collector is responsible for the destruction of objects and it is thus impossible to know when the destructor will be called. The language in which the RAII technique can mostly be seen is C++.
=External links=
*Article [http://www.hackcraft.net/raii/ The RAII Programming Idiom] by *[http://c2.com/cgi/wikiInitializationIsResourceAcquisition Descriptions from Portland Pattern Repository] *Sample Chapter [http://awprofessional.com/articles/article.aspp=30642&seqNum=8 Gotcha #67: Failure to Employ Resource Acquisition Is Initialization] by Stephen Dewhurst *Article [http://artima.com/intv/modern3.html A Conversation with Bjarne Stroustrup] by Bill Venners *Article [http://artima.com/cppsource/bigtwo3.html The Law of The Big Two] by Bjorn Karlsson and Matthew Wilson *[http://jrdodds.blogs.com/blog/2004/08/raii_in_c.html RAII in C++] by Jonathan Dodds *Article [http://gethelp.devx.com/techtips/cpp_pro/10min/2001/november/10min1101.asp Implementing the Resource Acquisition is Initialization Idiom] by Danny Kalev *Article [http://sourceforge.net/docman/display_doc.phpdocid=8673&group_id=9028 RAII] by Mike Nordell *Article [http://www.codeproject.com/cpp/RAIIFactory.asp RAII, Dynamic Objects, and Factories in C++] by Roland Pibinger|
|