Introduction
This article aims to help a programmer who has the need to use "finally
" like clause (like in Java) in C++.
Background
There are many cases where such need for finally
clause arises, mostly as I can see it, it always happen when a programmer uses a third party or legacy "C oriented" library that deals with resources in a procedural way like open/close file or connect/disconnect a service.
For example, MFC library solves the problem with the introduction of wrapper classes like CWaitCursor, where the cursor is a resource reclaimed back on destruction of the object. The destruction of the object is deterministic and happens on the event of getting out of scope (block end).
What I'm going to show is a solution for an already existing code that needs to be more deterministic and clean, but yet written in a procedural way.
Another reason to use this "finally
" like construct is for external resources that should be reclaimed no matter what happened after they were successfully claimed. For example, deterministic log-out of a remote service no matter what happens after a successful log-in to that service. That way prevents the remote dangling service from waiting for a log-out until some time-out routine will close the remote socket...
This solution is not a replacement for a superior design like using RAII (Resource Acquisition Is Initialization), see "Why doesn't C++ provide a "finally" construct?".
For beginners, I strongly suggest to read briefly the following items in the C++ reference:
- Lambda Functions in C++11 - the Definitive Guide
- Function objects
- std::function
- std::bind
It is possible to use the example ahead without deep knowledge of what is lambda or what is function object.
Using the Code
The code will run only on C++11 compiler and maybe some C++0x compilers!
For Beginners
It is very easy to use:
FILE *file = fopen("test","w");
finally close_the_file([&]{
cout << "Finally you close the file." << endl;
fclose(file);
});
The [&]
{
...}
is the code I suspect is not well understood for beginners, but it doesn't matter, as long as you accept the "unreadable" set of brackets, everything should be OK.
Let's explain:
- Opening a file the C way using
stdio
library, this is an old way of using files, but it is used here for the sake of the explanation. I consider the file opening as successful! - Next line, there is a declaration of object named
close_the_file
of a class finally
and then there is lambda expression that should run on the event of exiting the scope. basically you can copy and paste the class finally
(see ahead) and put somewhere in one of your libraries headers for later use.
The "finally" Class
The finally class
provides a means of running commands upon leaving the block by using the destructor of the class.
class finally
{
std::function<void(void)> functor;
public:
finally(const std::function<void(void)> &functor) : functor(functor) {}
~finally()
{
functor();
}
};
Example
Somehow the example file hasn't been uploaded so I decided to write a little example just to show how it works. Try this:
try {
cout << "Open a file" << endl;
FILE *file = fopen("test","w");
finally close_the_file([&]{
cout << "Finally you close the file." << endl;
fclose(file);
});
cout << "do something before exception" << endl;
throw("Some exception");
cout << "do something after exception!?" << endl;
}
catch(char *ex)
{
cout << ex << endl;
}
catch(...)
{
; }
History
- First revision
- Alternative example to the example file