Content deleted Content added
m →Basic techniques: type hint |
m Task 70: Update syntaxhighlight tags - remove use of deprecated <source> tags |
||
Line 36:
==Basic techniques==
The basic approach to resource management is to acquire a resource, do something with it, then release it, yielding code of the form (illustrated with opening a file in Python):
<
def work_with_file(filename: str):
f = open(filename)
...
f.close()
</syntaxhighlight>
This is correct if the intervening <code>...</code> code does not contain an early exit (<code>return</code>), the language does not have exceptions, and <code>open</code> is guaranteed to succeed. However, it causes a resource leak if there is a return or exception, and causes an incorrect release of unacquired resource if <code>open</code> can fail.
Line 47:
The resource leak can be resolved in languages that support a <code>finally</code> construction (like Python) by placing the body in a <code>try</code> clause, and the release in a <code>finally</code> clause:
<
def work_with_file(filename: str):
f = open(filename)
Line 54:
finally:
f.close()
</syntaxhighlight>
This ensures correct release even if there is a return within the body or an exception thrown. Further, note that the acquisition occurs ''before'' the <code>try</code> clause, ensuring that the <code>finally</code> clause is only executed if the <code>open</code> code succeeds (without throwing an exception), assuming that "no exception" means "success" (as is the case for <code>open</code> in Python). If resource acquisition can fail without throwing an exception, such as by returning a form of <code>null</code>, it must also be checked before release, such as:
<
def work_with_file(filename: str):
f = open(filename)
Line 64:
if f:
f.close()
</syntaxhighlight>
While this ensures correct resource management, it fails to provide adjacency or encapsulation. In many languages there are mechanisms that provide encapsulation, such as the <code>with</code> statement in Python:
<
def work_with_file(filename: str):
with open(filename) as f:
...
</syntaxhighlight>
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, [[Scheme (programming language)|Scheme]], and [[Smalltalk]],{{sfn|Beck|1997|37–39}} among others; they date to the late 1970s in the [[NIL (programming language)|NIL]] dialect of Lisp; see {{section link|Exception handling|History}}. There are many variations in the implementation, and there are also significantly different [[#Approaches|approaches]].
Line 115:
Both are commonly found. For example, in the [[Java Class Library]], <code>[https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html#close-- Reader#close()]</code> closes the underlying stream, and these can be chained. For example, a <code>[https://docs.oracle.com/javase/8/docs/api/java/io/BufferedReader.html BufferedReader]</code> may contain a <code>[https://docs.oracle.com/javase/8/docs/api/java/io/InputStreamReader.html InputStreamReader]</code>, which in turn contains a <code>[https://docs.oracle.com/javase/8/docs/api/java/io/FileInputStream.html FileInputStream]</code>, and calling <code>close</code> on the <code>BufferedReader</code> in turn closes the <code>InputStreamReader</code>, which in turn closes the <code>FileInputStream</code>, which in turn releases the system file resource. Indeed, the object that directly uses the resource can even be anonymous, thanks to encapsulation:
<
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)))) {
// Use reader.
}
// reader is closed when the try-with-resources block is exited, which closes each of the contained objects in sequence.
</syntaxhighlight>
However, it is also possible to manage only the object that directly uses the resource, and not use resource management on wrapper objects:
<
try (FileInputStream stream = new FileInputStream(fileName)))) {
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
Line 130:
// stream is closed when the try-with-resources block is exited.
// reader is no longer usable after stream is closed, but so long as it does not escape the block, this is not a problem.
</syntaxhighlight>
By contrast, in Python, a [https://docs.python.org/2/library/csv.html#csv.reader csv.reader] does not own the <code>file</code> that it is reading, so there is no need (and it is not possible) to close the reader, and instead the <code>file</code> itself must be closed.<ref>[https://stackoverflow.com/questions/3216954/python-no-csv-close Python: No csv.close()?]</ref>
<
with open(filename) as f:
r = csv.reader(f)
Line 140:
# f is closed when the with-statement is exited, and can no longer be used.
# Nothing is done to r, but the underlying f is closed, so r cannot be used either.
</syntaxhighlight>
In [[.NET]], convention is to only have direct user of resources be responsible: "You should implement IDisposable only if your type uses unmanaged resources directly."<ref name="idisposable">{{cite web |url=https://msdn.microsoft.com/en-us/library/system.idisposable(v=vs.110).aspx |title=IDisposable Interface |accessdate=2016-04-03}}</ref>
|