X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FExceptionWrapper.h;h=eb493fc68c10429428515a8f6459429e24d01162;hb=eab6da6adf08655248b054fd887005b61afdb5d6;hp=89ef616f1566b9122e36ca9ee5abe323abca5565;hpb=db0922d9d8979570ce47b68d834b5d945ae3f845;p=folly.git diff --git a/folly/ExceptionWrapper.h b/folly/ExceptionWrapper.h index 89ef616f..eb493fc6 100644 --- a/folly/ExceptionWrapper.h +++ b/folly/ExceptionWrapper.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2017-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,129 +13,686 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* + * Author: Eric Niebler + */ -#ifndef FOLLY_EXCEPTIONWRAPPER_H -#define FOLLY_EXCEPTIONWRAPPER_H +#pragma once #include +#include #include +#include #include -#include "folly/detail/ExceptionWrapper.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" +#pragma GCC diagnostic ignored "-Wpotentially-evaluated-expression" +// GCC gets confused about lambda scopes and issues shadow-local warnings for +// parameters in totally different functions. +FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS +#endif + +#define FOLLY_EXCEPTION_WRAPPER_H_INCLUDED namespace folly { -/* - * Throwing exceptions can be a convenient way to handle errors. Storing - * exceptions in an exception_ptr makes it easy to handle exceptions in a - * different thread or at a later time. exception_ptr can also be used in a very - * generic result/exception wrapper. - * - * However, there are some issues with throwing exceptions and - * std::exception_ptr. These issues revolve around throw being expensive, - * particularly in a multithreaded environment (see - * ExceptionWrapperBenchmark.cpp). - * - * Imagine we have a library that has an API which returns a result/exception - * wrapper. Let's consider some approaches for implementing this wrapper. - * First, we could store a std::exception. This approach loses the derived - * exception type, which can make exception handling more difficult for users - * that prefer rethrowing the exception. We could use a folly::dynamic for every - * possible type of exception. This is not very flexible - adding new types of - * exceptions requires a change to the result/exception wrapper. We could use an - * exception_ptr. However, constructing an exception_ptr as well as accessing - * the error requires a call to throw. That means that there will be two calls - * to throw in order to process the exception. For performance sensitive - * applications, this may be unacceptable. - * - * exception_wrapper is designed to handle exception management for both - * convenience and high performance use cases. make_exception_wrapper is - * templated on derived type, allowing us to rethrow the exception properly for - * users that prefer convenience. exception_wrapper is flexible enough to accept - * any std::exception. For performance sensitive applications, exception_wrapper - * exposes a get() function. These users can use dynamic_cast to retrieve - * desired derived types (hence the decision to limit usage to just - * std::exception instead of void*). - * - * Example usage: - * - * exception_wrapper globalExceptionWrapper; - * - * // Thread1 - * void doSomethingCrazy() { - * int rc = doSomethingCrazyWithLameReturnCodes(); - * if (rc == NAILED_IT) { - * globalExceptionWrapper = exception_wrapper(); - * } else if (rc == FACE_PLANT) { - * globalExceptionWrapper = make_exception_wrapper(); - * } else if (rc == FAIL_WHALE) { - * globalExceptionWrapper = make_exception_wrapper(); - * } - * } - * - * // Thread2: Exceptions are ok! - * void processResult() { - * try { - * globalExceptionWrapper.throwException(); - * } catch (const FacePlantException& e) { - * LOG(ERROR) << "FACEPLANT!"; - * } catch (const FailWhaleException& e) { - * LOG(ERROR) << "FAILWHALE!"; - * } - * } - * - * // Thread2: Exceptions are bad! - * void processResult() { - * auto ep = globalExceptionWrapper.get(); - * if (ep) { - * auto faceplant = dynamic_cast(ep); - * if (faceplant) { - * LOG(ERROR) << "FACEPLANT"; - * } else { - * auto failwhale = dynamic_cast(ep); - * if (failwhale) { - * LOG(ERROR) << "FAILWHALE!"; - * } - * } - * } - * } - * - */ -class exception_wrapper { - public: - exception_wrapper() : throwfn_(nullptr) { } +#define FOLLY_REQUIRES_DEF(...) \ + _t(__VA_ARGS__), long>> - void throwException() const { - if (throwfn_) { - throwfn_(item_.get()); - } - } +#define FOLLY_REQUIRES(...) FOLLY_REQUIRES_DEF(__VA_ARGS__) = __LINE__ + +namespace exception_wrapper_detail { + +template