Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Finally.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Execution_Finally_h_
5#define _Stroika_Foundation_Execution_Finally_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include <concepts>
10#include <functional>
11
12#include "Stroika/Foundation/Common/Common.h"
13#include "Stroika/Foundation/Common/Concepts.h"
14
15/**
16 * \file
17 *
18 * Finally utility - to approximate C++ try/finally support.
19 *
20 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
21 *
22 * TODO:
23 * @todo Consider checking noexcept (f), and avoiding the IgnoreExceptionsForCall
24 *
25 * @todo Consider adding optional parameter to auto include context to suppress thread exceptions (since that's a common need)
26 */
27
29
30 namespace Private_ {
31 template <Common::INoThrowInvocable FUNCTION>
32 class FinallySentry {
33 public:
34 FinallySentry () = delete;
35 FinallySentry (FUNCTION&& f);
36 FinallySentry (FinallySentry&&) = default;
37 FinallySentry (const FinallySentry&) = delete;
38
39 public:
40 ~FinallySentry ();
41
42 public:
43 nonvirtual FinallySentry& operator= (const FinallySentry&) = delete;
44
45 private:
46 FUNCTION fCleanupCodeBlock_;
47 };
48 }
49
50 /**
51 * This helpful utility to plug a missing feature from C++11 - to have a block of code run at the end
52 * of a scope - regardless of whether you use normal exit or exception based exit.
53 *
54 * This has some defects:
55 * o The syntax is ugly - the cleanup having to be declared
56 * BEFORE the block instead of afterwards (languages like C# with try/finally the finally goes
57 * at the end)
58 *
59 * o Exceptions inside of cleanupCodeBlock must be suppressed
60 *
61 * Inspired by:
62 * http://nerds-central.blogspot.com/2012/03/c11-trycatchfinally-pattern-using-raii.html
63 *
64 * \note SEE https://en.cppreference.com/w/cpp/experimental/scope_exit
65 * https://en.cppreference.com/w/cpp/experimental/scope_fail
66 * https://en.cppreference.com/w/cpp/experimental/scope_success
67 * (these may replace Finally - success/fail variants maybe better, and scope_exit I think basically
68 * the same, except not sure always available)
69 *
70 * \note For cleanup which is important/critical to be completed, its sometimes wise to include
71 * Thread::SuppressInterruptionInContext suppressThreadInterrupts;
72 * in the function body
73 *
74 * \note This is (now) done in such a way that no locks are used or memory allocated, except if
75 * argument lambda uses them/does it.
76 *
77 * \note This automatically suppresses any expressions triggered in the argument function, but its usually best
78 * to pass in a noexcept lambda (future versions may be more efficient in that case).
79 *
80 * \note Important parts of why this works: use auto so 'type' (size of struct for params) is dynamically calculated,
81 * and on stack with no memory allocation/indirection; and NAMED rvalue-reference so that its lifetime
82 * extends to the end of the scope in which its contained.
83 *
84 * \par Example Usage
85 * \code
86 * [[maybe_unused]]auto&& cleanup = Finally ([] () noexcept { Require (not sKnownBadBeforeMainOrAfterMain_); });
87 * \endcode
88 */
89 template <Common::INoThrowInvocable FUNCTION>
90 auto Finally (FUNCTION&& f) -> Private_::FinallySentry<FUNCTION>;
91
92}
93
94/*
95 ********************************************************************************
96 ***************************** Implementation Details ***************************
97 ********************************************************************************
98 */
99#include "Finally.inl"
100
101#endif /*_Stroika_Foundation_Execution_Finally_h_*/
auto Finally(FUNCTION &&f) -> Private_::FinallySentry< FUNCTION >
Definition Finally.inl:31