Resource management (computing): Difference between revisions

Content deleted Content added
top: wording, link
merge RAII discussion, clarify what is OO
Line 54:
The above techniques – unwind protection (<code>finally</code>) and some form of encapsulation – are the most common approach to resource management, found in various forms in C#, [[Common Lisp]], Java, Python, Ruby, and [[Scheme (programming language)|Scheme]], among others; they date to the late 1970s in the NIL dialect of Lisp; see [[#History|history]]. There are many variations in the implementation, and there are also significantly different [[#Approaches|approaches]].
 
== Approaches ==
=== Unwind protection ===
The most common approach to resource management across languages is to use aunwind <code>finally</code> clauseprotection, which is called when execution exits a scope – by execution running off the end of the block, returning from within the block, or an exception being throw. This works for stack-managed resources, and is implemented in many languages, including C#, Common Lisp, Java, Python, Ruby, and Scheme. The main problems with this approach is that the release code (most commonly in thea <code>finally</code> clause) may be very distant from the acquisition code (it lacks ''adjacency''), and that the acquisition and release code must always be paired by the caller (it lacks ''encapsulation''). These can be remedied either functionally, by using closures/callbacks/coroutines (Common Lisp, Ruby, Scheme), or by using an object that handles both the acquisition and release, and adding a language construct to call these methods when control enters and exits a scope (C# <code>using</code>, Java <code>try</code>-with-resources, Python <code>with</code>); see below.
 
An alternative, more imperative approach, is to write asynchronous code in [[direct style]]: acquire a resource, and then in the next line have a ''deferred'' release, which is called when the scope is exited – synchronous acquisition followed by asynchronous release. This originated in C++ as the ScopeGuard class, by [[Andrei Alexandrescu]] and Petru Marginean in 2000,
<ref>"[http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758 Generic: Change the Way You Write Exception-Safe Code — Forever]", by [[Andrei Alexandrescu]] and Petru Marginean, December 01, 2000, ''Dr. Dobb's''</ref> with improvements by Joshua Lehrer,<ref>[http://jlehrer.privatedns.org:8000/scopeguard.html ScopeGuard 2.0], Joshua Lehrer</ref> and has direct language support in D via the <code>scope</code> keyword ([http://dlang.org/statement.html#ScopeGuardStatement ScopeGuardStatement]), where it is one approach to [[exception safety]], in addition to RAII (see below).<ref>D: [http://dlang.org/exception-safe.html Exception Safety]</ref> It has also been included in Go, as the <code>[http://golang.org/ref/spec#Defer_statements defer]</code> statement.<ref>[http://blog.golang.org/defer-panic-and-recover Defer, Panic, and Recover], Andrew Gerrand, ''The Go Blog,'' 4 August 2010</ref> This approach lacks encapsulation – one must explicitly match acquisition and release – but avoids having to create an object for each resource (code-wise, avoid writing a class for each type of resource).
 
=== Object-oriented programming ===
ManyIn [[object-oriented programming]], many garbage-collected languages, including [[Java (programming language)|Java]], [[C Sharp (programming language)|C#]] and [[Python (programming language)|Python]], support various forms of the [[dispose pattern]] to simplify cleanup of resources. This results in simpler code and can serve as an alternative to RAII for "shallow" resources.
 
In C++, the usual approach to resource management is [[Resource Acquisition Is Initialization]] (RAII), which ties resource management to the lifetime of an object. This has the advantage that it can also be used for heap-managed resources.
 
The compositional properties of RAII, however, differ significantly from scope bound resources in that it allows for full [[Encapsulation (object-oriented programming)|encapsulation]] of the resources behind an abstraction. With the dispose pattern for resource management, "being a resource" becomes a property that is [[transitive relation|transitive]] to composition. That is, any object that is composed using a resource that requires resource management effectively itself becomes a resource that requires resource management.
 
This limitation is typically encountered whenever developing custom classes. Custom classes in C# and Java have to explicitly implement the <code>dispose</code> method in order to be dispose-compatible for the client code. The <code>dispose</code> method has to contain explicit closing of all child resources belonging to the class. This limitation does not exist in C++ with RAII, where the destructor of custom classes automatically destructs all child resources recursively without requiring any explicit code.
 
=== Structured programming ===
In [[structured programming]], stack resource management is done simply by nesting code sufficiently to handle all cases. This requires only a single return at the end of the code, and can result in heavily nested code if many resources must be acquired, which is considered an [[anti-pattern]] by some – the ''[http://c2.com/cgi/wiki?ArrowAntiPattern Arrow Anti Pattern],''<ref>[http://blog.codinghorror.com/flattening-arrow-code/ Flattening Arrow Code], Jeff Atwood, 10 Jan 2006</ref> due to the triangular shape from the successive nesting.
 
=== Cleanup clause ===
One other approach, which allows early return but consolidates cleanup in one place, is to have a single exit return of a function, preceded by cleanup code, and to use [[goto]] to jump to the cleanup before exit. This is infrequently seen in modern code, but occurs in some uses of C.
 
== Resource management without RAII ==
 
=== The dispose pattern ===
Many garbage-collected languages, including [[Java (programming language)|Java]], [[C Sharp (programming language)|C#]] and [[Python (programming language)|Python]], support various forms of the [[dispose pattern]] to simplify cleanup of resources. This results in simpler code and can serve as an alternative to RAII for "shallow" resources.
 
The compositional properties of RAII, however, differ significantly from scope bound resources in that it allows for full [[Encapsulation (object-oriented programming)|encapsulation]] of the resources behind an abstraction. With the dispose pattern for resource management, "being a resource" becomes a property that is [[transitive relation|transitive]] to composition. That is, any object that is composed using a resource that requires resource management effectively itself becomes a resource that requires resource management.
 
This limitation is typically encountered whenever developing custom classes. Custom classes in C# and Java have to explicitly implement the <code>dispose</code> method in order to be dispose-compatible for the client code. The <code>dispose</code> method has to contain explicit closing of all child resources belonging to the class. This limitation does not exist in C++ with RAII, where the destructor of custom classes automatically destructs all child resources recursively without requiring any explicit code.
 
==See also==