Created
December 13, 2020 14:37
-
-
Save kingsamchen/187f00b4a9389370d6b608d7f3c26c60 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <exception> | |
#include <type_traits> | |
#include <utility> | |
namespace folly { | |
namespace detail { | |
class ScopeGuardImplBase { | |
public: | |
void dismiss() noexcept { dismissed_ = true; } | |
protected: | |
ScopeGuardImplBase() noexcept | |
: dismissed_(false) {} | |
static void warnAboutToCrash() noexcept; | |
static ScopeGuardImplBase makeEmptyScopeGuard() noexcept | |
{ | |
return ScopeGuardImplBase {}; | |
} | |
template<typename T> | |
static const T& asConst(const T& t) noexcept | |
{ | |
return t; | |
} | |
bool dismissed_; | |
}; | |
template<typename FunctionType, bool InvokeNoexcept> | |
class ScopeGuardImpl : public ScopeGuardImplBase { | |
public: | |
//explicit ScopeGuardImpl(FunctionType& fn) noexcept( | |
// std::is_nothrow_copy_constructible<FunctionType>::value) | |
// : ScopeGuardImpl( | |
// asConst(fn), | |
// makeFailsafe( | |
// std::is_nothrow_copy_constructible<FunctionType> {}, | |
// &fn)) {} | |
explicit ScopeGuardImpl(const FunctionType& fn) noexcept( | |
std::is_nothrow_copy_constructible<FunctionType>::value) | |
: ScopeGuardImpl( | |
fn, | |
makeFailsafe( | |
std::is_nothrow_copy_constructible<FunctionType> {}, | |
&fn)) {} | |
explicit ScopeGuardImpl(FunctionType&& fn) noexcept( | |
std::is_nothrow_move_constructible<FunctionType>::value) | |
: ScopeGuardImpl( | |
std::move_if_noexcept(fn), | |
makeFailsafe( | |
std::is_nothrow_move_constructible<FunctionType> {}, | |
&fn)) {} | |
ScopeGuardImpl(ScopeGuardImpl&& other) noexcept( | |
std::is_nothrow_move_constructible<FunctionType>::value) | |
: function_(std::move_if_noexcept(other.function_)) | |
{ | |
// If the above line attempts a copy and the copy throws, other is | |
// left owning the cleanup action and will execute it (or not) depending | |
// on the value of other.dismissed_. The following lines only execute | |
// if the move/copy succeeded, in which case *this assumes ownership of | |
// the cleanup action and dismisses other. | |
dismissed_ = std::exchange(other.dismissed_, true); | |
} | |
~ScopeGuardImpl() noexcept(InvokeNoexcept) | |
{ | |
if (!dismissed_) { | |
execute(); | |
} | |
} | |
private: | |
static ScopeGuardImplBase makeFailsafe(std::true_type, const void*) noexcept | |
{ | |
return makeEmptyScopeGuard(); | |
} | |
template<typename Fn> | |
static auto makeFailsafe(std::false_type, Fn* fn) noexcept | |
-> ScopeGuardImpl<decltype(std::ref(*fn)), InvokeNoexcept> | |
{ | |
return ScopeGuardImpl<decltype(std::ref(*fn)), InvokeNoexcept> { | |
std::ref(*fn) | |
}; | |
} | |
template<typename Fn> | |
explicit ScopeGuardImpl(Fn&& fn, ScopeGuardImplBase&& failsafe) | |
: ScopeGuardImplBase {}, function_(std::forward<Fn>(fn)) | |
{ | |
//failsafe.dismiss(); | |
} | |
void* operator new(std::size_t) = delete; | |
void execute() noexcept(InvokeNoexcept) | |
{ | |
if (InvokeNoexcept) { | |
using R = decltype(function_()); | |
auto catcher = []() -> R { warnAboutToCrash(), std::terminate(); }; | |
function_(); | |
//catch_exception(function_, catcher); | |
} else { | |
function_(); | |
} | |
} | |
FunctionType function_; | |
}; | |
template<typename F, bool INE> | |
using ScopeGuardImplDecay = ScopeGuardImpl<typename std::decay<F>::type, INE>; | |
} // namespace detail | |
} // namespace folly |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <string> | |
#include <functional> | |
#include "folly_scoped_guard.h" | |
int main() | |
{ | |
std::function<void()> cb([] { std::cout << "inside std::function<void()>\n"; }); | |
const std::function<void()> ccb([]{ std::cout << "inside std::function<void()>\n"; }); | |
std::string s = "test"; | |
auto mcb = [s]() mutable { | |
s += "fuck"; | |
std::cout << "inside mutable lambda -- " << s << "\n"; | |
}; | |
//folly::detail::ScopeGuardImpl<decltype(cb), true> guard(cb); | |
folly::detail::ScopeGuardImpl<decltype(mcb), true> guard2(mcb); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment