The open source OpenXR runtime
1/** @file
2 @brief Header declaring a C++11 `finally` or "scope-guard" construct.
3
4 Inspirations are many - Alexandrescu's original and C++11 ScopeGuard, and
5 the Guideline Support Library's (GSL) `final_act`/`finally`
6 https://github.com/Microsoft/GSL/blob/0cf947db7760bf5756e4cb0d47c72a257ed527c5/include/gsl_util.h
7 come to mind, but this has been written and re-written numerous times
8 since its introduction into the C++ global consciousness, and this
9 implementation was written independently after I couldn't find a
10 previous independent implementation I had written a few weeks earlier in
11 an implementation file. -- Rylie Pavlik
12
13 See UniqueDestructionActionWrapper for a "generalized" (in some sense)
14 version of this.
15
16 Originally written for use in OSVR for Sensics <http://sensics.com/osvr>,
17 relicensed to BSL 1.0 with permission.
18
19 This header is maintained as a part of 'util-headers' - you can always
20 find the latest version online at https://github.com/rpavlik/util-headers
21
22 This GUID can help identify the project: d1dbc94e-e863-49cf-bc08-ab4d9f486613
23
24 This copy of the header is from the revision that Git calls
25 1a8444782d15cb9458052e3d8251c4f5b8e808d5
26
27 Commit date: "2022-03-11 12:11:32 -0600"
28
29 @date 2016
30
31 @author
32 Rylie Pavlik
33 <rylie@ryliepavlik.com>
34 <https://ryliepavlik.com>
35*/
36
37// Copyright 2016, Sensics, Inc.
38//
39// SPDX-License-Identifier: BSL-1.0
40//
41// Distributed under the Boost Software License, Version 1.0.
42// (See accompanying file LICENSE_1_0.txt or copy at
43// http://www.boost.org/LICENSE_1_0.txt)
44
45#ifndef INCLUDED_Finally_h_GUID_D925FE58_9C57_448B_C0BB_19A42B3243BA
46#define INCLUDED_Finally_h_GUID_D925FE58_9C57_448B_C0BB_19A42B3243BA
47
48// Internal Includes
49// - none
50
51// Library/third-party includes
52// - none
53
54// Standard includes
55#include <utility>
56
57namespace util {
58namespace detail {
59 /// Allows you to run a callable something at the end of a scope.
60 ///
61 /// The class that provides the scope-guard behavior. Often not referred to
62 /// by name because auto is useful here, and often not created by a direct
63 /// constructor call because of the finally() convenience functions combined
64 /// with lambdas.
65 template <typename F> class FinalTask {
66 public:
67 /// Explicit constructor from something callable.
68 explicit FinalTask(F f) : f_(std::move(f)) {}
69
70 /// Move constructor - cancels the moved-from task.
71 FinalTask(FinalTask &&other) : f_(std::move(other.f_)), do_(other.do_) {
72 other.cancel();
73 }
74
75 /// non-copyable
76 FinalTask(FinalTask const &) = delete;
77
78 /// non-assignable
79 FinalTask &operator=(FinalTask const &) = delete;
80
81 /// Destructor - if we haven't been cancelled, do our callable thing.
82 ~FinalTask() {
83 if (do_) {
84 f_();
85 }
86 }
87 /// Cancel causes us to not do our final task on destruction.
88 void cancel() { do_ = false; }
89
90 private:
91 /// Our callable task to do at destruction.
92 F f_;
93 /// Whether we should actually do it.
94 bool do_ = true;
95 };
96} // namespace detail
97
98/// Creation free function for final tasks to run on scope exit. Works great
99/// when paired with lambdas (particularly with `[&]` reference capture).
100/// Use like:
101/// `auto f = finally([&]{ dothis(); });` to have `dothis()` called when `f`
102/// goes out of scope, no matter how.
103template <typename F> inline detail::FinalTask<F> finally(F &&f) {
104 /// Perfect forwarding version.
105 return detail::FinalTask<F>(std::forward<F>(f));
106}
107
108/// @overload
109template <typename F> inline detail::FinalTask<F> finally(F const &f) {
110 // Added this overload because GSL had it and GSL is supposed to be best
111 // practices guidelines...
112 return detail::FinalTask<F>(f);
113}
114
115} // namespace util
116
117#endif // INCLUDED_Finally_h_GUID_D925FE58_9C57_448B_C0BB_19A42B3243BA