Nix 2.93.3
Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces
Loading...
Searching...
No Matches
finally.hh
Go to the documentation of this file.
1#pragma once
3
4#include <cassert>
5#include <exception>
6
10template<typename Fn>
11class Finally
12{
13private:
14 Fn fun;
15 bool movedFrom = false;
16
17public:
18 Finally(Fn fun) : fun(std::move(fun)) { }
19 // Copying Finallys is definitely not a good idea and will cause them to be
20 // called twice.
21 Finally(Finally &other) = delete;
22 Finally(Finally &&other) : fun(std::move(other.fun)) {
23 other.movedFrom = true;
24 }
25 // NOLINTNEXTLINE(bugprone-exception-escape): the noexcept is declared properly here, the analysis seems broken
26 ~Finally() noexcept(noexcept(fun()))
27 {
28 try {
29 if (!movedFrom)
30 fun();
31 } catch (...) {
32 // finally may only throw an exception if exception handling is not already
33 // in progress. if handling *is* in progress we have to return cleanly here
34 // but are still prohibited from doing so since eating the exception would,
35 // in almost all cases, mess up error handling even more. the only good way
36 // to handle this is to abort entirely and leave a message, so we'll assert
37 // (and rethrow anyway, just as a defense against possible NASSERT builds.)
38 if (std::uncaught_exceptions()) {
39 assert(false &&
40 "Finally function threw an exception during exception handling. "
41 "this is not what you want, please use some other methods (like "
42 "std::promise or async) instead.");
43 }
44 throw;
45 }
46 }
47};