Resource Acquisition Is Initialization

Resource Acquisition Is Initialization

Resource Acquisition Is Initialization, often referred to by the acronym RAII, is a popular design pattern in many object oriented languages like C++, D and Ada. The technique, invented by Bjarne Stroustrupcite book
title = The Design and Evolution of C++
last = Stroustrup
first = Bjarne
authorlink = Bjarne Stroustrup
year = 1994
publisher = Addison-Wesley
id = ISBN 0-201-54330-3
] , associates acquisition of resources with the initialization of objects that release the resources upon destruction.

RAII involves assigning ownership of a resource to scoped objects for resource managementcite paper
title = Exception Safety: Concepts and Techniques
author = Bjarne Stroustrup
url =
date = April 2001
format = PDF
accessdate = 2007-09-02
] . The acquisition is typically bound to the construction (initialization) and the automatic, deterministic destruction (uninitialization) is used to guarantee the resource is released. Since scoped objects are cleaned up regardless of whether the scope exits through normal use or through an exception, RAII is a key concept for writing exception-safe code [cite book
last = Sutter
first = Herb
authorlink = Herb Sutter
year = 1999
title = Exceptional C++
publisher = Addison-Wesley
id = ISBN 0-201-61562-2
] .

RAII is widely used to ensure exception safety. RAII makes it possible to avoid resource leaks without extensive use of exception handling blocks to release resources before permitting exceptions to propagate.

Language Support

C++ and D allow objects to be allocated on the stack, so the language scoping mechanism ensures that destructors are called when a local object's scope ends. By putting the resource release logic in the destructor, C++'s and D's scoping provide direct support for RAII.

Typical uses

The RAII technique is often used for controlling thread locks in multi-threaded applications. In that use, the object releases the lock, if held, when destroyed. Another typical example is file management, wherein the file class closes the associated file, if open, when destroyed.

The ownership of dynamically allocated memory (such as memoryallocated with new in C++ code) can be controlled withRAII, such that the memory is released when the RAII object isdestroyed. For this purpose, the C++ Standard Library defines. Furthermore, lifetime of sharedobjects can be managed by a smart pointer with shared-ownershipsemantics such as boost::shared_ptr, defined in C++by Boost and marked for inclusion in the new C++0x standard, or by policy based smart pointers such as Loki::SmartPtr from Loki.

Mutability (C++)

In C++, an important consideration of classes that implement RAII is their mutabilitycite book
last = Wilson
first = Matthew
authorlink = Matthew Wilson
year = 2004
title = Imperfect C++
publisher = Addison-Wesley
id = ISBN 0-321-22877-4
] . A class exhibiting "mutable RAII" provides facilitiesfor instances to be assigned a new resource; one that exhibits"immutable RAII" does not. An example of the former is; examples of the latter are the
STLSoft library's stlsoft::scoped_handle and
Boost.SmartPtr's boost::scoped_ptr.

Classes exhibiting "immutable RAII" are considerably easier to implement in C++, since the design need not account for assignment (including copy-assignment), except to explicitly prohibit it. Consider the following RAII class template that illustrates the simplicity of implementing "immutable RAII". Compare this with the implementation of or another "mutable RAII" smart pointer, which will have many more member functions and logic to handle premature release in cases of self-assignment.

template class immutable_scoped_ptr{public: explicit immutable_scoped_ptr(T* t) throw() : t_(t) { }

~immutable_scoped_ptr() throw() { delete t_; }

T& operator *() const throw() { return *t_; }

T* operator ->() const throw() { return t_; }

private: T* const t_;

// prevent copying and assignment; not implemented immutable_scoped_ptr(const immutable_scoped_ptr&); immutable_scoped_ptr& operator= (const immutable_scoped_ptr&);};

C++ example

The following RAII class is a lightweight wrapper of the C standard library file system calls.

class file{public: file (const char* filename) : file_(std::fopen(filename, "w+")) { if (!file_) throw std::runtime_error("file open failure"); }

~file() { if (0 != std::fclose(file_)) // failed to flush latest changes? { // handle it } }

void write (const char* str) { if (EOF = std::fputs(str, file_)) throw std::runtime_error("file write failure"); }

private: std::FILE* file_;

// prevent copying and assignment; not implemented file (const file &); file & operator= (const file &);};

Class file can then be used as follows:void example_usage(){ file logfile("logfile.txt"); // open file (acquire resource) logfile.write("hello logfile!"); // continue using logfile ... // throw exceptions or return without worrying about closing the log; // it is closed automatically when logfile goes out of scope}

This works because the class file encapsulates the management of the FILE* file handle. When objects file are local to a function, C++ guarantees that they are destroyed at the end of the enclosing scope (the function in the example), and the file destructor releases the file by calling std::fclose(file_). Furthermore, file instances guarantee that a file is available by throwing an exception if the file could not be opened when creating the object.

Local variables easily manage multiple resources within a single function: They are destroyed in the reverse order of their construction, and an object is only destroyed if fully constructed. That is, if no exception propagates from its constructor.

Using RAII-enabled resources simplifies and reduces overall code size and helps ensure program correctness.

Resource management without RAII

In Java, objects are not values and must be accessed through references; hence you cannot have automatic variables of objects that "go out of scope." Instead, all objects are dynamically allocated and have indefinite lifetimes, given Java's use of garbage collection which reclaims objects at indeterminate times, if at all. Resources must thus be closed manually by the programmer. The preceding example would be written like this:

void java_example() { // open file (acquire resource) final LogFile logfile = new LogFile("logfile.txt");

try { logfile.write("hello logfile!");

// continue using logfile ... // throw exceptions or return without worrying about closing the log; // it is closed automatically when exiting this block } finally { // explicitly release the resource logfile.close(); The burden of releasing resources falls on the programmer each time a resource is used.

Ruby and Smalltalk do not support RAII, but have a simpler and more flexible pattern that makes use of methods that pass resources to closure blocks. Here is an example in Ruby:"logfile.txt", "w+") do |logfile
logfile.write("hello logfile!")endThe open method ensures that the file handle is closed without special precautions by the code writing to the file. This is similar to Common Lisp's [ 'unwind-protect'] -based macros.

Python's [ 'with' statement] and the in C# and Visual Basic 2005 provide deterministic resource management within a block and do away with the requirement for explicit finally-based cleanup and release.

Perl manages object lifetime by reference counting, making it possible to use RAII in a limited form. Objects that are no longer referenced are immediately released, so a destructor can release the resource at that time. However, object lifetime isn't necessarily bound to any lexical scope. One can store a reference to an object in a global variable, for example, thus keeping the object (and resource) alive indeterminately long. This makes it possible to accidentally leak resources that should have been released at the end of some scope.

C requires significant administrative code since it doesn't support exceptions, try-finally blocks or RAII of any kind. A typical approach is to separate releasing of resources at the end of the function and jump there with gotos in the case of error. This way the cleanup code need not be duplicated.

int c_example() { int retval = 0; // return value 0 is success FILE *f = fopen("logfile.txt", "w+"); if (!f) { retval = -1; goto bailout1; } if (fputs("hello logfile!", f) = EOF) { retval = -2; goto bailout2; }

// continue using the file resource

// Releasing resources (in reverse order) bailout2: if (EOF = fclose(f)) { retval = -3; }

bailout1: return retval;}Variations exist, but the example illustrates the general approach.


External links

*Article " [ The RAII Programming Idiom] " by Wikipedia editor Jon Hanna (Talliesin)
*Wiki [ "Resource Acquisition Is Initialization"] from the Portland Pattern Repository
*Sample Chapter " [ Gotcha #67: Failure to Employ Resource Acquisition Is Initialization] " by Stephen Dewhurst
*Interview " [ A Conversation with Bjarne Stroustrup] " by Bill Venners
*Article " [ The Law of The Big Two] " by Bjorn Karlsson and Matthew Wilson
*Blog Entry " [ RAII in C++] " by Jonathan Dodds
*Article " [ Implementing the 'Resource Acquisition is Initialization' Idiom] " by Danny Kalev
*Article " [ RAII] " by Mike Nordell
*Article " [ RAII, Dynamic Objects, and Factories in C++] " by Roland Pibinger
*Article " [ Managing Dynamic Objects in C++] " by Tom Cargill
*Blog " [ tombarta RAII] "
*Blog Entry " [ RAII C++ Anti-Pattern] "
*Article " [ Smart pointers in C++] " by Julio M. Merino Vidal
*Blog Entry " [ Resource Management: A Critical Look at RAII] " by Michael Feathers

Wikimedia Foundation. 2010.