The open source OpenXR runtime
at prediction-2 117 lines 4.0 kB view raw
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