mmdeploy/csrc/core/status_code.h

193 lines
6.1 KiB
C++

// Copyright (c) OpenMMLab. All rights reserved.
#ifndef MMDEPLOY_SRC_CORE_STATUS_CODE_H_
#define MMDEPLOY_SRC_CORE_STATUS_CODE_H_
#include <system_error>
#include "outcome-experimental.hpp"
#if MMDEPLOY_STATUS_USE_SOURCE_LOCATION
#include "utils/source_location.h"
#elif MMDEPLOY_STATUS_USE_STACKTRACE
#include "utils/stacktrace.h"
#endif
namespace mmdeploy {
// clang-format off
enum class ErrorCode: int32_t {
eSuccess = 0,
eInvalidArgument = 1,
eNotSupported = 2,
eOutOfRange = 3,
eOutOfMemory = 4,
eFileNotExist = 5,
eFail = 6,
eShapeMismatch = 7,
eEntryNotFound = 8,
eNotReady = 9,
eUnknown = -1,
};
// clang-format on
#define USING_ERROR_CODE(code) constexpr inline const auto code = ErrorCode::code // NOLINT
// note that eSuccess is not brought to the outer namespace on purpose
USING_ERROR_CODE(eInvalidArgument);
USING_ERROR_CODE(eNotSupported);
USING_ERROR_CODE(eOutOfRange);
USING_ERROR_CODE(eOutOfMemory);
USING_ERROR_CODE(eFileNotExist);
USING_ERROR_CODE(eFail);
USING_ERROR_CODE(eShapeMismatch);
USING_ERROR_CODE(eEntryNotFound);
USING_ERROR_CODE(eNotReady);
USING_ERROR_CODE(eUnknown);
inline const char *to_string(ErrorCode code) {
switch (code) {
case ErrorCode::eSuccess:
return "success";
case ErrorCode::eInvalidArgument:
return "invalid argument";
case ErrorCode::eNotSupported:
return "not supported";
case ErrorCode::eOutOfRange:
return "out of range";
case ErrorCode::eOutOfMemory:
return "out of memory";
case ErrorCode::eFileNotExist:
return "file not exist";
case ErrorCode::eShapeMismatch:
return "shape mismatch";
case ErrorCode::eEntryNotFound:
return "entry not found";
case ErrorCode::eNotReady:
return "not ready";
default:
return "unknown";
}
}
struct Status {
ErrorCode ec{};
Status() = default;
SYSTEM_ERROR2_NAMESPACE::status_code_domain::string_ref message() const;
bool operator==(const ErrorCode &b) const noexcept { return ec == b; }
#if MMDEPLOY_STATUS_USE_SOURCE_LOCATION
const char *file{""};
int line{};
explicit Status(ErrorCode _ec, SourceLocation location = SourceLocation::current())
: ec(_ec), file(location.file_name()), line(static_cast<int>(location.line())) {}
#elif MMDEPLOY_STATUS_USE_STACKTRACE
Stacktrace st;
explicit Status(ErrorCode _ec, Stacktrace _st = Stacktrace(0)) : ec(_ec), st(std::move(_st)) {}
#else
explicit Status(ErrorCode _ec) : ec(_ec) {}
#endif
};
class StatusDomain;
using StatusCode = SYSTEM_ERROR2_NAMESPACE::status_code<StatusDomain>;
class StatusDomain : public SYSTEM_ERROR2_NAMESPACE::status_code_domain {
using _base = status_code_domain;
public:
using value_type = Status;
constexpr explicit StatusDomain(typename _base::unique_id_type id = 0x3584b6716049efb4) noexcept
: _base(id) {}
StatusDomain(const StatusDomain &) = default;
StatusDomain(StatusDomain &&) = default;
StatusDomain &operator=(const StatusDomain &) = default;
StatusDomain &operator=(StatusDomain &&) = default;
~StatusDomain() = default;
static inline constexpr const StatusDomain &get();
string_ref name() const noexcept override {
static string_ref v("mmdeploy");
return v;
}
// clang-format off
bool _do_failure(const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override {
assert(code.domain() == *this);
auto &c = static_cast<const StatusCode &>(code); // NOLINT
return c.value().ec != ErrorCode::eSuccess;
}
bool _do_equivalent(
const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code1,
const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code2) const noexcept override {
assert(code1.domain() == *this);
if (code1.domain() == *this && code2.domain() == *this) {
auto &c1 = static_cast<const StatusCode &>(code1); // NOLINT
auto &c2 = static_cast<const StatusCode &>(code2); // NOLINT
return c1.value().ec == c2.value().ec;
}
return false;
}
SYSTEM_ERROR2_NAMESPACE::generic_code _generic_code(
const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override {
assert(code.domain() == *this);
return SYSTEM_ERROR2_NAMESPACE::errc::unknown;
}
string_ref _do_message(
const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const noexcept override {
assert(code.domain() == *this);
auto &c = static_cast<const StatusCode &>(code); // NOLINT
return c.value().message();
}
// clang-format on
void _do_throw_exception(const SYSTEM_ERROR2_NAMESPACE::status_code<void> &code) const override;
};
constexpr inline StatusDomain status_domain;
inline constexpr const StatusDomain &StatusDomain::get() { return status_domain; }
inline StatusCode make_status_code(StatusCode::value_type v) {
return StatusCode(SYSTEM_ERROR2_NAMESPACE::in_place, static_cast<StatusCode::value_type &&>(v));
}
using OUTCOME_V2_NAMESPACE::failure;
using OUTCOME_V2_NAMESPACE::in_place_type;
using OUTCOME_V2_NAMESPACE::success;
inline bool operator==(const StatusCode &sc, ErrorCode ec) noexcept { return sc.value().ec == ec; }
inline bool operator==(ErrorCode ec, const StatusCode &sc) noexcept { return sc.value().ec == ec; }
using Error = SYSTEM_ERROR2_NAMESPACE::errored_status_code<StatusDomain>;
using Exception = SYSTEM_ERROR2_NAMESPACE::status_error<StatusDomain>;
template <typename T>
using Result = OUTCOME_V2_NAMESPACE::experimental::status_result<T, Error>;
#if MMDEPLOY_STATUS_USE_SOURCE_LOCATION
[[noreturn]] inline void throw_exception(ErrorCode ec,
SourceLocation location = SourceLocation::current()) {
Error(Status(ec, location)).throw_exception();
}
#elif MMDEPLOY_STATUS_USE_STACKTRACE
[[noreturn]] inline void throw_exception(ErrorCode ec, Stacktrace stacktrace = Stacktrace(0)) {
Error(Status(ec, std::move(stacktrace))).throw_exception();
}
#else
[[noreturn]] inline void throw_exception(const ErrorCode ec) {
Error(Status(ec)).throw_exception();
}
#endif
template <typename T>
inline constexpr bool is_result_v = OUTCOME_V2_NAMESPACE::is_basic_result_v<T>;
} // namespace mmdeploy
#endif // MMDEPLOY_SRC_CORE_STATUS_CODE_H_