Result: Refactor to have compiletime defs

This commit is contained in:
Michael Scire 2018-11-03 10:31:03 -07:00
parent be17f1f494
commit edcd4cbc26
2 changed files with 127 additions and 73 deletions

View file

@ -5,83 +5,137 @@
namespace mesosphere
{
class Result final {
public:
enum class Module : uint {
enum class ResultModule : uint {
None = 0,
Kernel = 1,
/* Other modules not included. */
};
enum class Description : uint {
None = 0,
class ResultHelper {
public:
using BaseType = uint;
static constexpr BaseType SuccessValue = BaseType();
static constexpr BaseType ModuleBits = 9;
static constexpr BaseType DescriptionBits = 13;
InvalidCapabilityDescriptor = 14,
NotImplemented = 33,
ThreadTerminated = 59,
OutOfDebugEvents = 70,
InvalidSize = 101,
InvalidAddress = 102,
AllocatorDepleted = 103,
OutOfMemory = 104,
OutOfHandles = 105,
InvalidMemoryState = 106,
InvalidMemoryPermissions = 108,
InvalidMemoryRange = 110,
InvalidPriority = 112,
InvalidCoreId = 113,
InvalidHandle = 114,
InvalidUserBuffer = 115,
InvalidCombination = 116,
TimedOut = 117,
Cancelled = 118,
OutOfRange = 119,
InvalidEnumValue = 120,
NotFound = 121,
AlreadyExists = 122,
ConnectionClosed = 123,
UnhandledUserInterrupt = 124,
InvalidState = 125,
ReservedValue = 126,
InvalidHwBreakpoint = 127,
FatalUserException = 128,
OwnedByAnotherProcess = 129,
ConnectionRefused = 131,
OutOfResource = 132,
IpcMapFailed = 259,
IpcCmdbufTooSmall = 260,
NotDebugged = 520,
template<ResultModule module, BaseType description>
struct MakeResult : public std::integral_constant<BaseType, ((static_cast<BaseType>(module)) | (description << ModuleBits))> {
static_assert(static_cast<BaseType>(module) < 1 << (ModuleBits + 1), "Invalid Module");
static_assert(description < 1 << (DescriptionBits + 1), "Invalid Description");
};
constexpr Result() : module{(uint)Module::None}, description{(uint)Description::None}, padding{0} {}
constexpr Result(Description description, Module module = Module::Kernel) :
module{(uint)module}, description{(uint)description}, padding{0} {}
constexpr bool IsSuccess() const
{
return module == (uint)Module::None && description == (uint)Description::None && padding == 0;
static constexpr ResultModule GetModule(BaseType value) {
return static_cast<ResultModule>(value & ~(~BaseType() << ModuleBits));
}
constexpr bool operator==(const Result &other) const
{
return module == other.module && description == other.description && padding == other.padding;
static constexpr BaseType GetDescription(BaseType value) {
return ((value >> ModuleBits) & ~(~BaseType() << DescriptionBits));
}
constexpr bool operator!=(const Result &other) const { return !(*this == other); }
};
constexpr Module GetModule() const { return (Module)module; }
constexpr Description GetDescription() const { return (Description)module; }
void SetModule(Module module) { this->module = (uint)module; }
void SetDescription(Description description) { this->description = (uint)description;}
/* Use CRTP for Results. */
template<typename Self>
class ResultBase {
public:
using BaseType = typename ResultHelper::BaseType;
static constexpr BaseType SuccessValue = ResultHelper::SuccessValue;
constexpr bool IsSuccess() const { return static_cast<const Self *>(this)->GetValue() == SuccessValue; }
constexpr bool IsFailure() const { return !IsSuccess(); }
constexpr operator bool() const { return IsSuccess(); }
constexpr bool operator !() const { return IsFailure(); }
constexpr ResultModule GetModule() const { return static_cast<const Self *>(this)->GetValue(); }
constexpr BaseType GetDescription() const { return static_cast<const Self *>(this)->GetValue(); }
};
/* Actual result type. */
class Result final : public ResultBase<Result> {
public:
using BaseType = typename ResultBase<Result>::BaseType;
static constexpr BaseType SuccessValue = ResultBase<Result>::SuccessValue;
constexpr Result() : value(SuccessValue) {}
constexpr BaseType GetValue() const { return this->value; }
constexpr bool operator==(const Result &other) const { return value == other.value; }
constexpr bool operator!=(const Result &other) const { return value != other.value; }
static constexpr Result MakeResult(BaseType v) { return Result(v); }
private:
uint module : 9;
uint description : 13;
uint padding : 10;
BaseType value;
constexpr explicit Result(BaseType v) : value(v) {}
};
static_assert(sizeof(Result) == sizeof(Result::BaseType), "Bad Result definition!");
/* Successful result class. */
class ResultSuccess final : public ResultBase<ResultSuccess> {
public:
using BaseType = typename ResultBase<ResultSuccess>::BaseType;
static constexpr BaseType SuccessValue = ResultBase<ResultSuccess>::SuccessValue;
constexpr operator Result() { return Result::MakeResult(SuccessValue); }
constexpr BaseType GetValue() const { return SuccessValue; }
};
/* Error result class. */
template<ResultModule module, ResultHelper::BaseType description>
class ResultError : public ResultBase<ResultError<module, description>> {
public:
using BaseType = typename ResultBase<ResultError<module, description>>::BaseType;
static constexpr BaseType SuccessValue = ResultBase<ResultError<module, description>>::SuccessValue;
static constexpr BaseType Value = ResultHelper::MakeResult<module, description>::value;
static_assert(Value != SuccessValue, "Invalid ResultError");
constexpr operator Result() { return Result::MakeResult(Value); }
constexpr BaseType GetValue() const { return Value; }
};
#define DEFINE_RESULT(module, name, description) class Result##module##name final : public ResultError<ResultModule::module, description> {}
DEFINE_RESULT(Kernel, InvalidCapabilityDescriptor, 14);
DEFINE_RESULT(Kernel, NotImplemented, 33);
DEFINE_RESULT(Kernel, ThreadTerminated, 59);
DEFINE_RESULT(Kernel, OutOfDebugEvents, 70);
DEFINE_RESULT(Kernel, InvalidSize, 101);
DEFINE_RESULT(Kernel, InvalidAddress, 102);
DEFINE_RESULT(Kernel, ResourceExhausted, 103);
DEFINE_RESULT(Kernel, OutOfMemory, 104);
DEFINE_RESULT(Kernel, OutOfHandles, 105);
DEFINE_RESULT(Kernel, InvalidMemoryState, 106);
DEFINE_RESULT(Kernel, InvalidMemoryPermissions, 108);
DEFINE_RESULT(Kernel, InvalidMemoryRange, 110);
DEFINE_RESULT(Kernel, InvalidPriority, 112);
DEFINE_RESULT(Kernel, InvalidCoreId, 113);
DEFINE_RESULT(Kernel, InvalidHandle, 114);
DEFINE_RESULT(Kernel, InvalidUserBuffer, 115);
DEFINE_RESULT(Kernel, InvalidCombination, 116);
DEFINE_RESULT(Kernel, TimedOut, 117);
DEFINE_RESULT(Kernel, Cancelled, 118);
DEFINE_RESULT(Kernel, OutOfRange, 119);
DEFINE_RESULT(Kernel, InvalidEnumValue, 120);
DEFINE_RESULT(Kernel, NotFound, 121);
DEFINE_RESULT(Kernel, AlreadyExists, 122);
DEFINE_RESULT(Kernel, ConnectionClosed, 123);
DEFINE_RESULT(Kernel, UnhandledUserInterrupt, 124);
DEFINE_RESULT(Kernel, NotPermitted, 125);
DEFINE_RESULT(Kernel, ReservedValue, 126);
DEFINE_RESULT(Kernel, InvalidHwBreakpoint, 127);
DEFINE_RESULT(Kernel, FatalUserException, 128);
DEFINE_RESULT(Kernel, OwnedByAnotherProcess, 129);
DEFINE_RESULT(Kernel, ConnectionRefused, 131);
DEFINE_RESULT(Kernel, OutOfResource, 132);
DEFINE_RESULT(Kernel, IpcMapFailed, 259);
DEFINE_RESULT(Kernel, IpcCmdbufTooSmall, 260);
DEFINE_RESULT(Kernel, NotDebugged, 520);
}

View file

@ -245,7 +245,7 @@ private:
size_t numKernelMutexWaiters = 0;
Handle syncResultHandle{};
Result syncResult{};
Result syncResult = ResultSuccess();
u64 lastScheduledTime = 0;
};