X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FScopeGuard.h;h=9a65811d9001f146f6478d17fcce4d354da2d92a;hb=03e99d2e90996a2a424a20b1a99c90d245344a7e;hp=5647675fd1b370e55776b2e163737067ce7eddb2;hpb=8dd97c8c552242c5a69eeb6fd20c79ec1b748e88;p=folly.git diff --git a/folly/ScopeGuard.h b/folly/ScopeGuard.h index 5647675f..9a65811d 100644 --- a/folly/ScopeGuard.h +++ b/folly/ScopeGuard.h @@ -1,5 +1,5 @@ /* - * Copyright 2012 Facebook, Inc. + * Copyright 2014 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +20,9 @@ #include #include #include -#include -#include "folly/Preprocessor.h" +#include +#include namespace folly { @@ -85,7 +85,7 @@ class ScopeGuardImplBase { bool dismissed_; }; -template +template class ScopeGuardImpl : public ScopeGuardImplBase { public: explicit ScopeGuardImpl(const FunctionType& fn) @@ -95,8 +95,8 @@ class ScopeGuardImpl : public ScopeGuardImplBase { : function_(std::move(fn)) {} ScopeGuardImpl(ScopeGuardImpl&& other) - : ScopeGuardImplBase(std::move(other)), - function_(std::move(other.function_)) { + : ScopeGuardImplBase(std::move(other)) + , function_(std::move(other.function_)) { } ~ScopeGuardImpl() noexcept { @@ -105,24 +105,15 @@ class ScopeGuardImpl : public ScopeGuardImplBase { } } -private: + private: void* operator new(size_t) = delete; - void execute() noexcept { - try { - function_(); - } catch (const std::exception& ex) { - LOG(FATAL) << "ScopeGuard cleanup function threw a " << - typeid(ex).name() << "exception: " << ex.what(); - } catch (...) { - LOG(FATAL) << "ScopeGuard cleanup function threw a non-exception object"; - } - } + void execute() noexcept { function_(); } FunctionType function_; }; -template +template ScopeGuardImpl::type> makeGuard(FunctionType&& fn) { return ScopeGuardImpl::type>( @@ -135,6 +126,80 @@ makeGuard(FunctionType&& fn) { typedef ScopeGuardImplBase&& ScopeGuard; namespace detail { + +#if defined(FOLLY_EXCEPTION_COUNT_USE_CXA_GET_GLOBALS) || \ + defined(FOLLY_EXCEPTION_COUNT_USE_GETPTD) + +/** + * ScopeGuard used for executing a function when leaving the current scope + * depending on the presence of a new uncaught exception. + * + * If the executeOnException template parameter is true, the function is + * executed if a new uncaught exception is present at the end of the scope. + * If the parameter is false, then the function is executed if no new uncaught + * exceptions are present at the end of the scope. + * + * Used to implement SCOPE_FAIL and SCOPE_SUCCES below. + */ +template +class ScopeGuardForNewException { + public: + explicit ScopeGuardForNewException(const FunctionType& fn) + : function_(fn) { + } + + explicit ScopeGuardForNewException(FunctionType&& fn) + : function_(std::move(fn)) { + } + + ScopeGuardForNewException(ScopeGuardForNewException&& other) + : function_(std::move(other.function_)) + , exceptionCounter_(std::move(other.exceptionCounter_)) { + } + + ~ScopeGuardForNewException() noexcept(executeOnException) { + if (executeOnException == exceptionCounter_.isNewUncaughtException()) { + function_(); + } + } + + private: + ScopeGuardForNewException(const ScopeGuardForNewException& other) = delete; + + void* operator new(size_t) = delete; + + FunctionType function_; + UncaughtExceptionCounter exceptionCounter_; +}; + +/** + * Internal use for the macro SCOPE_FAIL below + */ +enum class ScopeGuardOnFail {}; + +template +ScopeGuardForNewException::type, true> +operator+(detail::ScopeGuardOnFail, FunctionType&& fn) { + return + ScopeGuardForNewException::type, true>( + std::forward(fn)); +} + +/** + * Internal use for the macro SCOPE_SUCCESS below + */ +enum class ScopeGuardOnSuccess {}; + +template +ScopeGuardForNewException::type, false> +operator+(ScopeGuardOnSuccess, FunctionType&& fn) { + return + ScopeGuardForNewException::type, false>( + std::forward(fn)); +} + +#endif // native uncaught_exception() supported + /** * Internal use for the macro SCOPE_EXIT below */ @@ -152,6 +217,17 @@ operator+(detail::ScopeGuardOnExit, FunctionType&& fn) { #define SCOPE_EXIT \ auto FB_ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \ - = ::folly::detail::ScopeGuardOnExit() + [&] + = ::folly::detail::ScopeGuardOnExit() + [&]() noexcept + +#if defined(FOLLY_EXCEPTION_COUNT_USE_CXA_GET_GLOBALS) || \ + defined(FOLLY_EXCEPTION_COUNT_USE_GETPTD) +#define SCOPE_FAIL \ + auto FB_ANONYMOUS_VARIABLE(SCOPE_FAIL_STATE) \ + = ::folly::detail::ScopeGuardOnFail() + [&]() noexcept + +#define SCOPE_SUCCESS \ + auto FB_ANONYMOUS_VARIABLE(SCOPE_SUCCESS_STATE) \ + = ::folly::detail::ScopeGuardOnSuccess() + [&]() +#endif // native uncaught_exception() supported #endif // FOLLY_SCOPEGUARD_H_