mirror of
				https://github.com/Atmosphere-NX/Atmosphere.git
				synced 2025-11-03 20:41:17 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			164 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (c) Atmosphère-NX
 | 
						|
 *
 | 
						|
 * This program is free software; you can redistribute it and/or modify it
 | 
						|
 * under the terms and conditions of the GNU General Public License,
 | 
						|
 * version 2, as published by the Free Software Foundation.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
						|
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
						|
 * more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
 */
 | 
						|
#pragma once
 | 
						|
#include <mesosphere/kern_common.hpp>
 | 
						|
#include <mesosphere/kern_k_class_token.hpp>
 | 
						|
 | 
						|
namespace ams::kern {
 | 
						|
 | 
						|
    /* NOTE: This header is included after all other KAutoObjects. */
 | 
						|
    namespace impl {
 | 
						|
 | 
						|
        template<typename T> requires std::derived_from<T, KAutoObject>
 | 
						|
        consteval bool IsAutoObjectInheritanceValidImpl() {
 | 
						|
            #define CLASS_TOKEN_HANDLER(CLASSNAME)                                                                               \
 | 
						|
                if constexpr (std::same_as<T, CLASSNAME>) {                                                                      \
 | 
						|
                    if (T::GetStaticTypeObj().GetClassToken() != ::ams::kern::ClassToken<CLASSNAME>) {                           \
 | 
						|
                        return false;                                                                                            \
 | 
						|
                    }                                                                                                            \
 | 
						|
                } else {                                                                                                         \
 | 
						|
                    if (T::GetStaticTypeObj().IsDerivedFrom(CLASSNAME::GetStaticTypeObj()) != std::derived_from<T, CLASSNAME>) { \
 | 
						|
                        return false;                                                                                            \
 | 
						|
                    }                                                                                                            \
 | 
						|
                }
 | 
						|
 | 
						|
            FOR_EACH_K_CLASS_TOKEN_OBJECT_TYPE(CLASS_TOKEN_HANDLER)
 | 
						|
            #undef CLASS_TOKEN_HANDLER
 | 
						|
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
 | 
						|
        consteval bool IsEveryAutoObjectInheritanceValid() {
 | 
						|
            #define CLASS_TOKEN_HANDLER(CLASSNAME) if (!IsAutoObjectInheritanceValidImpl<CLASSNAME>()) { return false; }
 | 
						|
            FOR_EACH_K_CLASS_TOKEN_OBJECT_TYPE(CLASS_TOKEN_HANDLER)
 | 
						|
            #undef CLASS_TOKEN_HANDLER
 | 
						|
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
 | 
						|
        static_assert(IsEveryAutoObjectInheritanceValid());
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        concept IsAutoObjectWithSpecializedGetId = std::derived_from<T, KAutoObjectWithList> && requires (const T &t, const KAutoObjectWithList &l) {
 | 
						|
            { t.GetIdImpl() } -> std::same_as<decltype(l.GetId())>;
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        struct AutoObjectWithListComparatorImpl {
 | 
						|
            using RedBlackKeyType = u64;
 | 
						|
 | 
						|
            static ALWAYS_INLINE RedBlackKeyType GetRedBlackKey(const RedBlackKeyType &v) { return v; }
 | 
						|
 | 
						|
            static ALWAYS_INLINE RedBlackKeyType GetRedBlackKey(const KAutoObjectWithList &v) {
 | 
						|
                if constexpr (IsAutoObjectWithSpecializedGetId<T>) {
 | 
						|
                    return static_cast<const T &>(v).GetIdImpl();
 | 
						|
                } else {
 | 
						|
                    return reinterpret_cast<u64>(std::addressof(v));
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            template<typename U> requires (std::same_as<U, KAutoObjectWithList> || std::same_as<U, RedBlackKeyType>)
 | 
						|
            static ALWAYS_INLINE int Compare(const U &lhs, const KAutoObjectWithList &rhs) {
 | 
						|
                const u64 lid = GetRedBlackKey(lhs);
 | 
						|
                const u64 rid = GetRedBlackKey(rhs);
 | 
						|
 | 
						|
                if (lid < rid) {
 | 
						|
                    return -1;
 | 
						|
                } else if (lid > rid) {
 | 
						|
                    return 1;
 | 
						|
                } else {
 | 
						|
                    return 0;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        };
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        using AutoObjectWithListComparator = AutoObjectWithListComparatorImpl<typename std::conditional<IsAutoObjectWithSpecializedGetId<T>, T, KAutoObjectWithList>::type>;
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        using TrueObjectContainerListType = typename KAutoObjectWithListContainer<T>::ListType<AutoObjectWithListComparator<T>>;
 | 
						|
 | 
						|
        template<typename T>
 | 
						|
        ALWAYS_INLINE TrueObjectContainerListType<T> &GetTrueObjectContainerList(typename KAutoObjectWithListContainer<T>::DummyListType &l) {
 | 
						|
            static_assert(alignof(l) == alignof(impl::TrueObjectContainerListType<T>));
 | 
						|
            static_assert(sizeof(l)  == sizeof(impl::TrueObjectContainerListType<T>));
 | 
						|
            return *reinterpret_cast<TrueObjectContainerListType<T> *>(std::addressof(l));
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    inline NOINLINE void KAutoObject::ScheduleDestruction() {
 | 
						|
        MESOSPHERE_ASSERT_THIS();
 | 
						|
 | 
						|
        /* Set our object to destroy. */
 | 
						|
        m_next_closed_object = GetCurrentThread().GetClosedObject();
 | 
						|
 | 
						|
        /* Set ourselves as the thread's next object to destroy. */
 | 
						|
        GetCurrentThread().SetClosedObject(this);
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    class KAutoObjectWithListContainer<T>::ListAccessor : public impl::KAutoObjectWithListContainerBase::ListAccessorImpl<impl::TrueObjectContainerListType<T>> {
 | 
						|
        NON_COPYABLE(ListAccessor);
 | 
						|
        NON_MOVEABLE(ListAccessor);
 | 
						|
        private:
 | 
						|
            using BaseListAccessor = impl::KAutoObjectWithListContainerBase::ListAccessorImpl<impl::TrueObjectContainerListType<T>>;
 | 
						|
        public:
 | 
						|
            explicit ALWAYS_INLINE ListAccessor(KAutoObjectWithListContainer *container) : BaseListAccessor(container, impl::GetTrueObjectContainerList<T>(container->m_dummy_object_list)) { /* ... */ }
 | 
						|
            explicit ALWAYS_INLINE ListAccessor(KAutoObjectWithListContainer &container) : BaseListAccessor(container, impl::GetTrueObjectContainerList<T>(container.m_dummy_object_list)) { /* ... */ }
 | 
						|
 | 
						|
            ALWAYS_INLINE ~ListAccessor() { /* ... */ }
 | 
						|
    };
 | 
						|
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    ALWAYS_INLINE void KAutoObjectWithListContainer<T>::Register(T *obj) {
 | 
						|
        return this->RegisterImpl(obj, impl::GetTrueObjectContainerList<T>(m_dummy_object_list));
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    ALWAYS_INLINE void KAutoObjectWithListContainer<T>::Unregister(T *obj) {
 | 
						|
        return this->UnregisterImpl(obj, impl::GetTrueObjectContainerList<T>(m_dummy_object_list));
 | 
						|
    }
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    ALWAYS_INLINE size_t KAutoObjectWithListContainer<T>::GetOwnedCountChecked(const KProcess *owner) {
 | 
						|
        return this->GetOwnedCountImpl<T>(owner, impl::GetTrueObjectContainerList<T>(m_dummy_object_list));
 | 
						|
    }
 | 
						|
 | 
						|
    inline u64 KAutoObjectWithList::GetId() const {
 | 
						|
        #define CLASS_TOKEN_HANDLER(CLASSNAME)                                                                      \
 | 
						|
            if constexpr (impl::IsAutoObjectWithSpecializedGetId<CLASSNAME>) {                                      \
 | 
						|
                if (const CLASSNAME * const derived = this->DynamicCast<const CLASSNAME *>(); derived != nullptr) { \
 | 
						|
                    return []<typename T>(const T * const t_derived) ALWAYS_INLINE_LAMBDA -> u64 {                  \
 | 
						|
                        static_assert(std::same_as<T, CLASSNAME>);                                                  \
 | 
						|
                        if constexpr (impl::IsAutoObjectWithSpecializedGetId<CLASSNAME>) {                          \
 | 
						|
                            return impl::AutoObjectWithListComparator<CLASSNAME>::GetRedBlackKey(*t_derived);       \
 | 
						|
                        } else {                                                                                    \
 | 
						|
                            AMS_ASSUME(false);                                                                      \
 | 
						|
                        }                                                                                           \
 | 
						|
                    }(derived);                                                                                     \
 | 
						|
                }                                                                                                   \
 | 
						|
            }
 | 
						|
 | 
						|
        FOR_EACH_K_CLASS_TOKEN_OBJECT_TYPE(CLASS_TOKEN_HANDLER)
 | 
						|
        #undef CLASS_TOKEN_HANDLER
 | 
						|
 | 
						|
        return impl::AutoObjectWithListComparator<KAutoObjectWithList>::GetRedBlackKey(*this);
 | 
						|
    }
 | 
						|
 | 
						|
}
 |