/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include #include namespace tensorpipe { // Base class for actual errors. class BaseError { public: virtual ~BaseError() = default; // Returns an explanatory string. // Like `std::exception` but returns a `std::string`. virtual std::string what() const = 0; }; // Wrapper class for errors. // // Background: we wish to not use exceptions yet need an error // representation that can propagate across function and thread // boundaries. This representation must be copyable (so we can store // and return it at a later point in time) and retain downstream type // information. This implies a heap allocation because it's the // easiest way to deal with variable size objects (barring a union of // all downstream error classes and a lot of custom code). Instead of // passing a shared_ptr around directly, we use this wrapper class to // keep implementation details hidden from calling code. // class Error final { public: // Constant instance that indicates success. static const Error kSuccess; // Default constructor for error that is not an error. Error() {} Error(std::shared_ptr error, std::string file, int line) : error_(std::move(error)), file_(std::move(file)), line_(line) {} virtual ~Error() = default; // Converting to boolean means checking if there is an error. This // means we don't need to use an `std::optional` and allows for a // snippet like the following: // // if (error) { // // Deal with it. // } // operator bool() const { return static_cast(error_); } template std::shared_ptr castToType() const { return std::dynamic_pointer_cast(error_); } template bool isOfType() const { return castToType() != nullptr; } // Like `std::exception` but returns a `std::string`. std::string what() const; private: std::shared_ptr error_; std::string file_; int line_; }; class SystemError final : public BaseError { public: explicit SystemError(const char* syscall, int error) : syscall_(syscall), error_(error) {} std::string what() const override; int errorCode() const; private: const char* syscall_; const int error_; }; class ShortReadError final : public BaseError { public: ShortReadError(ssize_t expected, ssize_t actual) : expected_(expected), actual_(actual) {} std::string what() const override; private: const ssize_t expected_; const ssize_t actual_; }; class ShortWriteError final : public BaseError { public: ShortWriteError(ssize_t expected, ssize_t actual) : expected_(expected), actual_(actual) {} std::string what() const override; private: const ssize_t expected_; const ssize_t actual_; }; class EOFError final : public BaseError { public: EOFError() {} std::string what() const override; }; } // namespace tensorpipe