diff options
Diffstat (limited to 'src/core/hle/kernel/k_class_token.h')
-rw-r--r-- | src/core/hle/kernel/k_class_token.h | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/core/hle/kernel/k_class_token.h b/src/core/hle/kernel/k_class_token.h new file mode 100644 index 000000000..89b80a341 --- /dev/null +++ b/src/core/hle/kernel/k_class_token.h @@ -0,0 +1,131 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <atomic> + +#include "common/assert.h" +#include "common/bit_util.h" +#include "common/common_types.h" + +namespace Kernel { + +class KAutoObject; + +class KClassTokenGenerator { +public: + using TokenBaseType = u16; + +public: + static constexpr size_t BaseClassBits = 8; + static constexpr size_t FinalClassBits = (sizeof(TokenBaseType) * CHAR_BIT) - BaseClassBits; + // One bit per base class. + static constexpr size_t NumBaseClasses = BaseClassBits; + // Final classes are permutations of three bits. + static constexpr size_t NumFinalClasses = [] { + TokenBaseType index = 0; + for (size_t i = 0; i < FinalClassBits; i++) { + for (size_t j = i + 1; j < FinalClassBits; j++) { + for (size_t k = j + 1; k < FinalClassBits; k++) { + index++; + } + } + } + return index; + }(); + +private: + template <TokenBaseType Index> + static constexpr inline TokenBaseType BaseClassToken = BIT(Index); + + template <TokenBaseType Index> + static constexpr inline TokenBaseType FinalClassToken = [] { + TokenBaseType index = 0; + for (size_t i = 0; i < FinalClassBits; i++) { + for (size_t j = i + 1; j < FinalClassBits; j++) { + for (size_t k = j + 1; k < FinalClassBits; k++) { + if ((index++) == Index) { + return static_cast<TokenBaseType>(((1ULL << i) | (1ULL << j) | (1ULL << k)) + << BaseClassBits); + } + } + } + } + }(); + + template <typename T> + static constexpr inline TokenBaseType GetClassToken() { + static_assert(std::is_base_of<KAutoObject, T>::value); + if constexpr (std::is_same<T, KAutoObject>::value) { + static_assert(T::ObjectType == ObjectType::KAutoObject); + return 0; + } else if constexpr (!std::is_final<T>::value) { + static_assert(ObjectType::BaseClassesStart <= T::ObjectType && + T::ObjectType < ObjectType::BaseClassesEnd); + constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) - + static_cast<TokenBaseType>(ObjectType::BaseClassesStart); + return BaseClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>(); + } else if constexpr (ObjectType::FinalClassesStart <= T::ObjectType && + T::ObjectType < ObjectType::FinalClassesEnd) { + constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) - + static_cast<TokenBaseType>(ObjectType::FinalClassesStart); + return FinalClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>(); + } else { + static_assert(!std::is_same<T, T>::value, "GetClassToken: Invalid Type"); + } + }; + +public: + enum class ObjectType { + KAutoObject, + + BaseClassesStart, + + KSynchronizationObject = BaseClassesStart, + KReadableEvent, + + BaseClassesEnd, + + FinalClassesStart = BaseClassesEnd, + + KInterruptEvent = FinalClassesStart, + KDebug, + KThread, + KServerPort, + KServerSession, + KClientPort, + KClientSession, + Process, + KResourceLimit, + KLightSession, + KPort, + KSession, + KSharedMemory, + KEvent, + KWritableEvent, + KLightClientSession, + KLightServerSession, + KTransferMemory, + KDeviceAddressSpace, + KSessionRequest, + KCodeMemory, + + // NOTE: True order for these has not been determined yet. + KAlpha, + KBeta, + + FinalClassesEnd = FinalClassesStart + NumFinalClasses, + }; + + template <typename T> + static constexpr inline TokenBaseType ClassToken = GetClassToken<T>(); +}; + +using ClassTokenType = KClassTokenGenerator::TokenBaseType; + +template <typename T> +static constexpr inline ClassTokenType ClassToken = KClassTokenGenerator::ClassToken<T>; + +} // namespace Kernel |