deal.II version GIT relicensing-1936-ge55124254b 2024-10-04 21:10:00+00:00
|
#include <deal.II/base/scope_exit.h>
Public Member Functions | |
ScopeExit (const std::function< void()> &exit_function) | |
ScopeExit (const ScopeExit &)=delete | |
~ScopeExit () | |
ScopeExit & | operator= (const ScopeExit &)=delete |
Private Attributes | |
const std::function< void()> | exit_function |
A class that stores a function object (typically a lambda function) that is executed in the destructor of the current object. Such a class is useful to execute an action whenever the function in which the object is declared exits, whether that is by falling off the end of the function, an explicit return
statement, or because an exception is thrown. In all of these cases, the destructors of all local objects are run, and the destructor of the ScopeExit object then executes the stored action.
The typical use case is that we want to perform a clean-up action. For example, let's say that we want to print to the console that we're leaving a long-running and potentially complicated function. This could be achieved as follows:
The point here is that in order to have the message printed, we do not need to go through the 800 lines of complex code and find all places where either there is an explicit return
statement, or where a function that is called may throw an exception that we do not explicitly catch: Any way the current function is exited will lead to the message being printed.
A perhaps more instructive example is the following (from some past iteration of the implementation of SUNDIALS::KINSOL::solve()):
This code has a bug: At the bottom, it contains clean-up code that destroys a variety of objects created throughout the life of the function we are looking at. Because SUNDIALS is a library written in C, objects such as solution
, u_scale
, J
, LS
, etc., are really just regular pointers that need to be explicitly freed. But this does not happen in the places higher up where we throw
an exception and don't catch it again immediately. One might be tempted to just copy the clean-up code to right before the std::rethrow_exception
statement, but there is a path through the catch
clauses marked with "just eat the exception" that ends up returning control flow back to the regular path, and if we hit this path, we would call the clean-up functions twice – also not what we want. The upshot of this kind of example is that there are cases where it is quite difficult to say where exactly a function will exit and where the clean-up code needs to be placed; it is far easier to write it only once and let the compiler determine where it needs to be called, via a class such as the current one.
The function is conceptually very similar to the std::experimental::scope_exit class template that may find its way into a future C++ standard.
Definition at line 133 of file scope_exit.h.
|
inlineexplicit |
Constructor. Takes a function object that is to be executed at the place where the current object goes out of scope as argument.
Definition at line 169 of file scope_exit.h.
|
delete |
Copy constructor. These kinds of objects cannot be copied, so the constructor is deleted.
|
inline |
Destructor. Execute the stored action.
Definition at line 175 of file scope_exit.h.
Copy operator. These kinds of objects cannot be copied, so the operator is deleted.
|
private |
A copy of the function to be executed.
Definition at line 164 of file scope_exit.h.