I have a use case where I think finally
should be a perfectly acceptable part of the C++11 language, as I think it is easier to read from a flow point of view. My use case is a consumer/producer chain of threads, where a sentinel nullptr
is sent at the end of the run to shut down all threads.
If C++ supported it, you would want your code to look like this:
extern Queue downstream, upstream; int Example() { try { while(!ExitRequested()) { X* x = upstream.pop(); if (!x) break; x->doSomething(); downstream.push(x); } } finally { downstream.push(nullptr); } }
I think this is more logical that putting your finally declaration at the start of the loop, since it occurs after the loop has exited... but that is wishful thinking because we can't do it in C++. Note that the queue downstream
is connected to another thread, so you can't put in the sentinel push(nullptr)
in the destructor of downstream
because it can't be destroyed at this point... it needs to stay alive until the other thread receives the nullptr
.
So here is how to use a RAII class with lambda to do the same:
class Finally { public: Finally(std::function<void(void)> callback) : callback_(callback) { } ~Finally() { callback_(); } std::function<void(void)> callback_; };
and here is how you use it:
extern Queue downstream, upstream; int Example() { Finally atEnd([](){ downstream.push(nullptr); }); while(!ExitRequested()) { X* x = upstream.pop(); if (!x) break; x->doSomething(); downstream.push(x); } }