In
computer programming
Computer programming is the process of performing a particular computation (or more generally, accomplishing a specific computing result), usually by designing and building an executable computer program. Programming involves tasks such as anal ...
, resource management refers to techniques for managing
resources
Resource refers to all the materials available in our environment which are technologically accessible, economically feasible and culturally sustainable and help us to satisfy our needs and wants. Resources can broadly be classified upon their ...
(components with limited availability).
Computer program
A computer program is a sequence or set of instructions in a programming language for a computer to execute. Computer programs are one component of software, which also includes documentation and other intangible components.
A computer progra ...
s may manage their own resources by using features exposed by
programming language
A programming language is a system of notation for writing computer programs. Most programming languages are text-based formal languages, but they may also be graphical. They are a kind of computer language.
The description of a programming l ...
s ( is a survey article contrasting different approaches), or may elect to manage them by a host – an
operating system
An operating system (OS) is system software that manages computer hardware, software resources, and provides common daemon (computing), services for computer programs.
Time-sharing operating systems scheduler (computing), schedule tasks for ef ...
or
virtual machine
In computing, a virtual machine (VM) is the virtualization/ emulation of a computer system. Virtual machines are based on computer architectures and provide functionality of a physical computer. Their implementations may involve specialized har ...
– or another program.
Host-based management is known as ''resource tracking,'' and consists of cleaning up resource leaks: terminating access to resources that have been acquired but not released after use. This is known as ''reclaiming'' resources, and is analogous to
garbage collection for memory. On many systems, the operating system reclaims resources after the process makes the
exit system call
In computing, a system call (commonly abbreviated to syscall) is the programmatic way in which a computer program requests a service from the operating system on which it is executed. This may include hardware-related services (for example, acc ...
.
Controlling access
The omission of releasing a resource when a program has finished using it is known as a
resource leak
In computer science, a resource leak is a particular type of resource consumption by a computer program where the program does not release resources it has acquired. This condition is normally the result of a bug in a program. Typical resource lea ...
, and is an issue in sequential computing. Multiple processes wish to access a limited resource can be an issue in
concurrent computing
Concurrent computing is a form of computing in which several computations are executed '' concurrently''—during overlapping time periods—instead of ''sequentially—''with one completing before the next starts.
This is a property of a sys ...
, and is known as
resource contention.
Resource management seeks to control access in order to prevent both of these situations.
Resource leak
Formally, resource management (preventing resource leaks) consists of ensuring that a resource is released if and only if it is successfully acquired. This general problem can be abstracted as "''before,'' ''body,'' and ''after''" code, which normally are executed in this order, with the condition that the ''after'' code is called if and only if the ''before'' code successfully completes, regardless of whether the ''body'' code executes successfully or not. This is also known as ''execute around'' or a ''code sandwich,'' and occurs in various other contexts, such as a temporary change of program state, or
tracing entry and exit into a
subroutine
In computer programming, a function or subroutine is a sequence of program instructions that performs a specific task, packaged as a unit. This unit can then be used in programs wherever that particular task should be performed.
Functions ma ...
. However, resource management is the most commonly cited application. In
aspect-oriented programming
In computing, aspect-oriented programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. It does so by adding behavior to existing code (an advice) ''without'' modifying ...
, such execute around logic is a form of ''
advice''.
In the terminology of
control flow analysis
In computer science, control-flow analysis (CFA) is a static-code-analysis technique for determining the control flow of a program. The control flow is expressed as a control-flow graph (CFG). For both functional programming languages and ob ...
, resource release must
postdominate
In computer science, a node of a control-flow graph dominates a node if every path from the ''entry node'' to must go through . Notationally, this is written as (or sometimes ). By definition, every node dominates itself.
There are a n ...
successful resource acquisition; failure to ensure this is a bug, and a code path that violates this condition causes a resource leak. Resource leaks are often minor problems, generally not crashing the program, but instead causing some slowdown to the program or the overall system. However, they may cause crashes – either the program itself or other programs – due to ''resource exhaustion:'' if the system runs out of resources, acquisition requests fail. This can present a
security bug if an attack can cause resource exhaustion. Resource leaks may happen under regular program flow – such as simply forgetting to release a resource – or only in exceptional circumstances, such as when a resource is not released if there is an exception in another part of the program. Resource leaks are very frequently caused by
early exit from a subroutine, either by a
return
statement, or an exception raised either by the subroutine itself, or a deeper subroutine that it calls. While resource release due to return statements can be handled by carefully releasing within the subroutine before the return, exceptions cannot be handled without some additional language facility that guarantees that release code is executed.
More subtly, successful resource acquisition must
dominate
The Dominate, also known as the late Roman Empire, is the name sometimes given to the " despotic" later phase of imperial government in the ancient Roman Empire. It followed the earlier period known as the " Principate". Until the empire was reu ...
resource release, as otherwise the code will try to release a resource it has not acquired. The consequences of such an incorrect release range from being silently ignored to crashing the program or unpredictable behavior. These bugs generally manifest rarely, as they require resource allocation to first fail, which is generally an exceptional case. Further, the consequences may not be serious, as the program may already be crashing due to failure to acquire an essential resource. However, these can prevent recovery from the failure, or turn an orderly shutdown into a disorderly shutdown. This condition is generally ensured by first checking that the resource was successfully acquired before releasing it, either by having a boolean variable to record "successfully acquired" – which lacks atomicity if the resource is acquired but the flag variable fails to be updated, or conversely – or by the handle to the resource being a
nullable type
Nullable types are a feature of some programming languages which allow a value to be set to the special value NULL instead of the usual possible values of the data type. In statically typed languages, a nullable type is an option type, while in d ...
, where "null" indicates "not successfully acquired", which ensures atomicity.
Resource contention
Memory management
Memory can be treated as a resource, but
memory management
Memory management is a form of resource management applied to computer memory. The essential requirement of memory management is to provide ways to dynamically allocate portions of memory to programs at their request, and free it for reuse when ...
is usually considered separately, primarily because memory allocation and deallocation is significantly more frequent than acquisition and release of other resources, such as file handles. Memory managed by an ''external'' system has similarities to both (internal) memory management (since it is memory) and resource management (since it is managed by an external system). Examples include memory managed via native code and used from Java (via
Java Native Interface
In software design, the Java Native Interface (JNI) is a foreign function interface programming framework that enables Java code running in a Java virtual machine (JVM) to call and be called by
native applications (programs specific to a hardwa ...
); and objects in the
Document Object Model
The Document Object Model (DOM) is a cross-platform and language-independent interface that treats an XML or HTML document as a tree structure wherein each node is an object representing a part of the document. The DOM represents a docum ...
(DOM), used from
JavaScript
JavaScript (), often abbreviated as JS, is a programming language that is one of the core technologies of the World Wide Web, alongside HTML and CSS. As of 2022, 98% of Website, websites use JavaScript on the Client (computing), client side ...
. In both these cases, the
memory manager (
garbage collector) of the
runtime environment
In computer programming, a runtime system or runtime environment is a sub-system that exists both in the computer where a program is created, as well as in the computers where the program is intended to be run. The name comes from the compile ...
(virtual machine) is unable to manage the external memory (there is no shared memory management), and thus the external memory is treated as a resource, and managed analogously. However, cycles between systems (JavaScript referring to the DOM, referring back to JavaScript) can make management difficult or impossible.
Lexical management and explicit management
A key distinction in resource management within a program is between ''lexical management'' and ''explicit management'' – whether a resource can be handled as having a lexical scope, such as a stack variable (lifetime is restricted to a single lexical scope, being acquired on entry to or within a particular scope, and released when execution exits that scope), or whether a resource must be explicitly allocated and released, such as a resource acquired within a function and then returned from it, which must then be released outside of the acquiring function. Lexical management, when applicable, allows a better separation of concerns and is less error-prone.
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):
f = open(filename)
...
f.close()
This is correct if the intervening
...
code does not contain an early exit (
return
), the language does not have exceptions, and
open
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
open
can fail.
There are two more fundamental problems: the acquisition-release pair is not adjacent (the release code must be written far from the acquisition code), and resource management is not encapsulated – the programmer must manually ensure that they are always paired. In combination, these mean that acquisition and release must be explicitly paired, but cannot be placed together, thus making it easy for these to not be paired correctly.
The resource leak can be resolved in languages that support a
finally
construction (like Python) by placing the body in a
try
clause, and the release in a
finally
clause:
f = open(filename)
try:
...
finally:
f.close()
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
try
clause, ensuring that the
finally
clause is only executed if the
open
code succeeds (without throwing an exception), assuming that "no exception" means "success" (as is the case for
open
in Python). If resource acquisition can fail without throwing an exception, such as by returning a form of
null
, it must also be checked before release, such as:
f = open(filename)
try:
...
finally:
if f:
f.close()
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
with
statement in Python:
with open(filename) as f:
...
The above techniques – unwind protection (
finally
) and some form of encapsulation – are the most common approach to resource management, found in various forms in C#,
Common Lisp
Common Lisp (CL) is a dialect of the Lisp programming language, published in ANSI standard document ''ANSI INCITS 226-1994 (S20018)'' (formerly ''X3.226-1994 (R1999)''). The Common Lisp HyperSpec, a hyperlinked HTML version, has been derived fr ...
, Java, Python, Ruby,
Scheme, and
Smalltalk
Smalltalk is an object-oriented, dynamically typed reflective programming language. It was designed and created in part for educational use, specifically for constructionist learning, at the Learning Research Group (LRG) of Xerox PARC by ...
, among others; they date to the late 1970s in the
NIL dialect of Lisp; see . There are many variations in the implementation, and there are also significantly different
approaches.
Approaches
Unwind protection
The most common approach to resource management across languages is to use unwind protection, 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 thrown. 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 a
finally
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#
using
, Java
try
-with-resources, Python
with
); 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
Andrei Alexandrescu (born 1969) is a Romanian-American C++ and D language programmer and author. He is particularly known for his pioneering work on policy-based design implemented via template metaprogramming. These ideas are articulated ...
and Petru Marginean in 2000,
with improvements by Joshua Lehrer, and has direct language support in D via the
scope
keyword
ScopeGuardStatement, where it is one approach to
exception safety, in addition to RAII (see below). It has also been included in Go, as the
defer
/code> statement. 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
In object-oriented programming
Object-oriented programming (OOP) is a programming paradigm based on the concept of " objects", which can contain data and code. The data is in the form of fields (often known as attributes or ''properties''), and the code is in the form of ...
, resources are encapsulated within objects that use them, such as a file
object having a field whose value is a file descriptor
In Unix and Unix-like computer operating systems, a file descriptor (FD, less frequently fildes) is a process-unique identifier ( handle) for a file or other input/output resource, such as a pipe or network socket.
File descriptors typically ...
(or more general file handle). This allows the object to use and manage the resource without users of the object needing to do so. However, there is a wide variety of ways that objects and resources can be related.
Firstly, there is the question of ownership: does an object ''have'' a resource?
* Objects can ''own'' resources (via object composition, a strong "has a" relationship).
* Objects can ''view'' resources (via object aggregation
In computer science, object composition and object aggregation are closely related ways to combine objects or data types into more complex ones. In conversation the distinction between composition and aggregation is often ignored. Common kin ...
, a weak "has a" relationship).
* Objects can ''communicate'' with other objects that have resources (via Association).
Objects that have a resource can acquire and release it in different ways, at different points during the object lifetime
In object-oriented programming (OOP), the object lifetime (or life cycle) of an object is the time between an object's creation and its destruction. Rules for object lifetime vary significantly between languages, in some cases between implement ...
; these occur in pairs, but in practice they are often not used symmetrically (see below):
* Acquire/release while the object is valid, via (instance) methods such as open
or dispose
.
* Acquire/release during object creation/destruction (in the initializer and finalizer).
* Neither acquire nor release the resource, instead simply having a ''view'' or ''reference'' to a resource managed externally to the object, as in dependency injection; concretely, an object that has a resource (or can communicate with one that does) is passed in as an argument to a method or constructor.
Most common is to acquire a resource during object creation, and then explicitly release it via an instance method, commonly called dispose
. This is analogous to traditional file management (acquire during open
, release by explicit close
), and is known as the dispose pattern
In object-oriented programming, the dispose pattern is a design pattern for resource management. In this pattern, a resource is held by an object, and released by calling a conventional method – usually called close, dispose, free, release d ...
. This is the basic approach used in several major modern object-oriented languages, including Java
Java (; id, Jawa, ; jv, ꦗꦮ; su, ) is one of the Greater Sunda Islands in Indonesia. It is bordered by the Indian Ocean to the south and the Java Sea to the north. With a population of 151.6 million people, Java is the world's mo ...
, C# and Python, and these languages have additional constructs to automate resource management. However, even in these languages, more complex object relationships result in more complex resource management, as discussed below.
RAII
A natural approach is to make holding a resource be a class invariant
In computer programming, specifically object-oriented programming, a class invariant (or type invariant) is an invariant used for constraining objects of a class. Methods of the class should preserve the invariant. The class invariant constr ...
: resources are acquired during object creation (specifically initialization), and released during object destruction (specifically finalization). This is known as Resource Acquisition Is Initialization (RAII), and ties resource management to object lifetime
In object-oriented programming (OOP), the object lifetime (or life cycle) of an object is the time between an object's creation and its destruction. Rules for object lifetime vary significantly between languages, in some cases between implement ...
, ensuring that live objects have all necessary resources. Other approaches do not make holding the resource a class invariant, and thus objects may not have necessary resources (because they've not been acquired yet, have already been released, or are being managed externally), resulting in errors such as trying to read from a closed file. This approach ties resource management to memory management (specifically object management), so if there are no memory leaks (no object leaks), there are no resource leak
In computer science, a resource leak is a particular type of resource consumption by a computer program where the program does not release resources it has acquired. This condition is normally the result of a bug in a program. Typical resource lea ...
s. RAII works naturally for heap-managed resources, not only stack-managed resources, and is composable: resources held by objects in arbitrarily complicated relationships (a complicated object graph) are released transparently simply by object destruction (so long as this is done properly!).
RAII is the standard resource management approach in C++, but is little-used outside C++, despite its appeal, because it works poorly with modern automatic memory management, specifically tracing garbage collection: RAII ''ties'' resource management to memory management, but these have significant differences. Firstly, because resources are expensive, it is desirable to release them promptly, so objects holding resources should be destroyed as soon as they become garbage (are no longer in use). Object destruction is prompt in deterministic memory management, such as in C++ (stack-allocated objects are destroyed on stack unwind, heap-allocated objects are destroyed manually via calling delete
or automatically using unique_ptr
) or in deterministic reference-counting (where objects are destroyed immediately when their reference count falls to 0), and thus RAII works well in these situations. However, most modern automatic memory management is non-deterministic, making no guarantees that objects will be destroyed promptly or even at all! This is because it is cheaper to leave some garbage allocated than to precisely collect each object immediately on its becoming garbage. Secondly, releasing resources during object destruction means that an object must have a ''finalizer
In computer science, a finalizer or finalize method is a special method that performs finalization, generally some form of cleanup. A finalizer is executed during object destruction, prior to the object being deallocated, and is complementary t ...
'' (in deterministic memory management known as a ''destructor'') – the object cannot simply be deallocated – which significantly complicates and slows garbage collection.
Complex relationships
When multiple objects rely on a single resource, resource management can be complicated.
A fundamental question is whether a "has a" relationship is one of ''owning'' another object ( object composition), or ''viewing'' another object (object aggregation
In computer science, object composition and object aggregation are closely related ways to combine objects or data types into more complex ones. In conversation the distinction between composition and aggregation is often ignored. Common kin ...
). A common case is when one two objects are chained, as in pipe and filter pattern, the delegation pattern, the decorator pattern
In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is ofte ...
, or the adapter pattern
In software engineering, the adapter pattern is a software design pattern (also known as Wrapper function, wrapper, an alternative naming shared with the decorator pattern) that allows the interface (computer science), interface of an existing clas ...
. If the second object (which is not used directly) holds a resource, is the first object (which is used directly) responsible for managing the resource? This is generally answered identically to whether the first object ''owns'' the second object: if so, then the owning object is also responsible for resource management ("having a resource" is transitive), while if not, then it is not. Further, a single object may "have" several other objects, owning some and viewing others.
Both cases are commonly found, and conventions differ. Having objects that use resources indirectly be responsible for the resource (composition) provides encapsulation (one only needs the object that clients use, without separate objects for the resources), but results in considerable complexity, particularly when a resource is shared by multiple objects or objects have complex relationships. If only the object that directly uses the resource is responsible for the resource (aggregation), relationships between other objects that use the resources can be ignored, but there is no encapsulation (beyond the directly using object): the resource must be managed directly, and might not be available to the indirectly using object (if it has been released separately).
Implementation-wise, in object composition, if using the dispose pattern, the owning object thus will also have a dispose
method, which in turn calls the dispose
methods of owned objects that must be disposed; in RAII this is handled automatically (so long as owned objects are themselves automatically destroyed: in C++ if they are a value or a unique_ptr
, but not a raw pointer: see pointer ownership). In object aggregation, nothing needs to be done by the viewing object, as it is not responsible for the resource.
Both are commonly found. For example, in the Java Class Library
The Java Class Library (JCL) is a set of Library (computer science)#Dynamic linking, dynamically loadable libraries that List of JVM languages, Java Virtual Machine (JVM) languages can call at Run time (program lifecycle phase), run time. Because ...
, Reader#close()
/code> closes the underlying stream, and these can be chained. For example, a
/code> may contain a
/code>, which in turn contains a
/code>, and calling close
on the BufferedReader
in turn closes the InputStreamReader
, which in turn closes the FileInputStream
, 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))))
// reader is closed when the try-with-resources block is exited, which closes each of the contained objects in sequence.
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))))
// 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.
By contrast, in Python,
does not own the file
that it is reading, so there is no need (and it is not possible) to close the reader, and instead the file
itself must be closed.
with open(filename) as f:
r = csv.reader(f)
# Use r.
# 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.
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."
In case of a more complicated object graph, such as multiple objects sharing a resource, or cycles between objects that hold resources, proper resource management can be quite complicated, and exactly the same issues arise as in object finalization (via destructors or finalizers); for example, the lapsed listener problem can occur and cause resource leaks if using the
observer pattern
In software design and engineering, the observer pattern is a software design pattern in which an object, named the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by ...
(and observers hold resources). Various mechanisms exist to allow greater control of resource management. For example, in the Google Closure Library, the goog.Disposable
/code> class provides a registerDisposable
method to register other objects to be disposed with this object, together with various lower-level instance and class methods to manage disposal.
Structured programming
In structured programming
Structured programming is a programming paradigm aimed at improving the clarity, quality, and development time of a computer program by making extensive use of the structured control flow constructs of selection ( if/then/else) and repetition (w ...
, 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
An anti-pattern in software engineering, project management, and business processes is a common response to a recurring problem that is usually ineffective and risks being highly counterproductive. The term, coined in 1995 by computer programmer An ...
by some – the
Arrow Anti Pattern
''Flattening Arrow Code
Jeff Atwood, 10 Jan 2006 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
GoTo (goto, GOTO, GO TO or other case combinations, depending on the programming language) is a statement found in many computer programming languages. It performs a one-way transfer of control to another line of code; in contrast a function c ...
to jump to the cleanup before exit. This is infrequently seen in modern code, but occurs in some uses of C.
See also
* Memory management
Memory management is a form of resource management applied to computer memory. The essential requirement of memory management is to provide ways to dynamically allocate portions of memory to programs at their request, and free it for reuse when ...
* Pool (computer science)
In computer science, a pool is a collection of resources that are kept, in memory, ready to use, rather than the memory acquired on use and the memory released afterwards. In this context, ''resources'' can refer to system resources such as fi ...
References
*
*
{{refend
Further reading
DG Update: Dispose, Finalization, and Resource Management
Joe Duffy
Joseph Duffy (born 27 January 1956) is an Irish broadcaster employed by Raidió Teilifís Éireann (RTÉ). One of RTÉ's highest-earning stars, he is the current presenter of ''Liveline'', an interview and phone-in chat show broadcast on R ...
External links
Deterministic Resource Management
''WikiWikiWeb
The WikiWikiWeb is the first wiki, or user-editable website. It was launched on 25 March 1995 by programmer Ward Cunningham to accompany the Portland Pattern Repository website discussing software design patterns. The name ''WikiWikiWeb'' orig ...
''
Programming constructs