folly/folly/ExceptionWrapper.h

/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <cassert>
#include <cstdint>
#include <exception>
#include <iosfwd>
#include <memory>
#include <new>
#include <type_traits>
#include <typeinfo>
#include <utility>

#include <folly/CPortability.h>
#include <folly/CppAttributes.h>
#include <folly/Demangle.h>
#include <folly/ExceptionString.h>
#include <folly/FBString.h>
#include <folly/Portability.h>
#include <folly/Traits.h>
#include <folly/Utility.h>
#include <folly/functional/traits.h>
#include <folly/lang/Assume.h>
#include <folly/lang/Exception.h>

namespace folly {

#define FOLLY_REQUIRES_DEF

#define FOLLY_REQUIRES

//! 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, inspecting exceptions through the `exception_ptr` interface, namely
//! through `rethrow_exception`, is expensive. This is a wrapper interface which
//! offers faster inspection.
//!
//! \par Example usage:
//! \code
//! 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<FacePlantException>();
//!   } else if (rc == FAIL_WHALE) {
//!     globalExceptionWrapper = make_exception_wrapper<FailWhaleException>();
//!   }
//! }
//!
//! // Thread2: Exceptions are ok!
//! void processResult() {
//!   try {
//!     globalExceptionWrapper.throw_exception();
//!   } catch (const FacePlantException& e) {
//!     LOG(ERROR) << "FACEPLANT!";
//!   } catch (const FailWhaleException& e) {
//!     LOG(ERROR) << "FAILWHALE!";
//!   }
//! }
//!
//! // Thread2: Exceptions are bad!
//! void processResult() {
//!   globalExceptionWrapper.handle(
//!       [&](FacePlantException& faceplant) {
//!         LOG(ERROR) << "FACEPLANT";
//!       },
//!       [&](FailWhaleException& failwhale) {
//!         LOG(ERROR) << "FAILWHALE!";
//!       },
//!       [](...) {
//!         LOG(FATAL) << "Unrecognized exception";
//!       });
//! }
//! \endcode
class exception_wrapper final {};

/**
 * \return An `exception_wrapper` that wraps an instance of type `Ex`
 *     that has been constructed with arguments `std::forward<As>(as)...`.
 */
template <class Ex, typename... As>
exception_wrapper make_exception_wrapper(As&&... as) {}

/**
 * Inserts `ew.what()` into the ostream `sout`.
 * \return `sout`
 */
template <class Ch>
std::basic_ostream<Ch>& operator<<(
    std::basic_ostream<Ch>& sout, exception_wrapper const& ew) {}

/**
 * Swaps the value of `a` with the value of `b`.
 */
inline void swap(exception_wrapper& a, exception_wrapper& b) noexcept {}

// For consistency with exceptionStr() functions in ExceptionString.h
fbstring exceptionStr(exception_wrapper const& ew);

//! `try_and_catch` is a convenience for `try {} catch(...) {}`` that returns an
//! `exception_wrapper` with the thrown exception, if any.
template <typename F>
exception_wrapper try_and_catch(F&& fn) noexcept {}
} // namespace folly

#include <folly/ExceptionWrapper-inl.h>

#undef FOLLY_REQUIRES
#undef FOLLY_REQUIRES_DEF