/* * Copyright (c) 2018-2020 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 . */ #pragma once #include #include #include #include #include #include namespace ams::sf { namespace impl { template struct IsSmartPointer : public std::false_type{}; template struct IsSmartPointer> : public std::true_type{}; template struct IsSmartPointer> : public std::true_type{}; template struct IsSmartPointer> : public std::true_type{}; template struct UnmanagedEmplaceImplHolderBaseGetter { using Type = Impl; }; template requires (std::is_abstract::value ) struct UnmanagedEmplaceImplHolderBaseGetter { class Impl2 : public Impl { public: using Impl::Impl; private: constexpr virtual void AddReference() override { /* ... */ } constexpr virtual void Release() override { /* ... */ } }; using Type = Impl2; }; template class UnmanagedEmplacedImplHolder { template friend class impl::ImplTemplateBaseT; private: using Impl2 = typename UnmanagedEmplaceImplHolderBaseGetter::Type; static_assert(!std::is_abstract::value); private: Impl2 m_impl; private: template constexpr explicit UnmanagedEmplacedImplHolder(Args &&... args) : m_impl(std::forward(args)...) { /* ... */ } public: static constexpr Impl *GetImplPointer(UnmanagedEmplacedImplHolder *holder) { return std::addressof(holder->m_impl); } }; template class EmplacedImplHolder : private Impl { template friend class impl::ImplTemplateBaseT; private: template constexpr explicit EmplacedImplHolder(Args &&... args) : Impl(std::forward(args)...) { /* ... */ } public: static constexpr Impl *GetImplPointer(EmplacedImplHolder *holder) { return holder; } template static constexpr Impl *GetEmplacedImplPointerImpl(const SharedPointer &sp) { using Base = impl::ImplTemplateBase; return static_cast(sp.Get()); } }; template requires (IsSmartPointer::value) class EmplacedImplHolder : private Impl { template friend class impl::ImplTemplateBaseT; private: template constexpr explicit EmplacedImplHolder(Args &&... args) : Impl(std::forward(args)...) { /* ... */ } public: static constexpr auto *GetImplPointer(EmplacedImplHolder *holder) { return static_cast(holder)->operator ->(); } template static constexpr Impl *GetEmplacedImplPointerImpl(const SharedPointer &sp) { using Base = impl::ImplTemplateBase; return static_cast(sp.Get()); } }; template using SmartPointerHolder = EmplacedImplHolder; template class ManagedPointerHolder { template friend class impl::ImplTemplateBaseT; private: T *m_p; private: constexpr explicit ManagedPointerHolder(T *p) : m_p(p) { /* ... */ } constexpr ~ManagedPointerHolder() { m_p->Release(); } static constexpr T *GetImplPointer(ManagedPointerHolder *holder) { return holder->m_p; } }; template class UnmanagedPointerHolder { template friend class impl::ImplTemplateBaseT; private: T *m_p; private: constexpr explicit UnmanagedPointerHolder(T *p) : m_p(p) { /* ... */ } static constexpr T *GetImplPointer(UnmanagedPointerHolder *holder) { return holder->m_p; } }; } template class UnmanagedServiceObject final : public impl::ImplTemplateBase, impl::UnmanagedEmplacedImplHolder> { private: using ImplBase = impl::ImplTemplateBase, impl::UnmanagedEmplacedImplHolder>; public: using ImplBase::ImplBase; constexpr virtual void AddReference() override { /* ... */ } constexpr virtual void Release() override { /* ... */ } constexpr Impl &GetImpl() { return impl::UnmanagedEmplacedImplHolder::GetImplPointer(this); } constexpr SharedPointer GetShared() { return SharedPointer(this, false); } }; template class UnmanagedServiceObjectByPointer final : public impl::ImplTemplateBase, impl::UnmanagedPointerHolder> { private: using ImplBase = impl::ImplTemplateBase, impl::UnmanagedPointerHolder>; public: constexpr explicit UnmanagedServiceObjectByPointer(T *ptr) : ImplBase(ptr) { /* ... */ } constexpr virtual void AddReference() override { /* ... */ } constexpr virtual void Release() override { /* ... */ } constexpr SharedPointer GetShared() { return SharedPointer(this, false); } }; template class ObjectFactory; template class EmplacedRef : public SharedPointer { template friend class ObjectFactory; private: constexpr explicit EmplacedRef(Interface *ptr, bool incref) : SharedPointer(ptr, incref) { /* ... */ } public: constexpr EmplacedRef() { /* ... */ } constexpr Impl &GetImpl() const { return *impl::EmplacedImplHolder::template GetEmplacedImplPointerImpl(*this); } }; template requires (!IsStatefulPolicy) class ObjectFactory { private: template static constexpr SharedPointer CreateSharedForPointer(T t) { using Base = impl::ImplTemplateBase; return SharedPointer(ObjectImplFactory::Create(std::forward(t)), false); } public: template static constexpr EmplacedRef CreateSharedEmplaced(Args &&... args) { using Base = impl::ImplTemplateBase, impl::EmplacedImplHolder>; return EmplacedRef(ObjectImplFactory::Create(std::forward(args)...), false); } template static constexpr SharedPointer CreateUserSharedObject(Args &&... args) { return SharedPointer(ObjectImplFactory::Create(std::forward(args)...), false); } template static constexpr Impl *GetEmplacedImplPointer(const SharedPointer &sp) { return impl::EmplacedImplHolder::template GetEmplacedImplPointerImpl(sp); } template static constexpr SharedPointer CreateShared(Smart &&sp) { return CreateSharedForPointer::type>>(std::forward(sp)); } template static constexpr SharedPointer CreateShared(T *p) { return CreateSharedForPointer>(p); } template static constexpr SharedPointer CreateSharedWithoutManagement(T *p) { return CreateSharedForPointer>(p); } }; template requires (IsStatefulPolicy) class ObjectFactory { public: using Allocator = typename Policy::Allocator; private: template static constexpr SharedPointer CreateSharedForPointer(Allocator *a, T t) { using Base = impl::ImplTemplateBase; return SharedPointer(ObjectImplFactory::Create(a, std::forward(t)), false); } public: template static constexpr EmplacedRef CreateSharedEmplaced(Allocator *a, Args &&... args) { using Base = impl::ImplTemplateBase, impl::EmplacedImplHolder>; return EmplacedRef(ObjectImplFactory::Create(a, std::forward(args)...), false); } template static constexpr SharedPointer CreateUserSharedObject(Allocator *a, Args &&... args) { return SharedPointer(ObjectImplFactory::Create(a, std::forward(args)...), false); } template static constexpr Impl *GetEmplacedImplPointer(const SharedPointer &sp) { return impl::EmplacedImplHolder::template GetEmplacedImplPointerImpl(sp); } template static constexpr SharedPointer CreateShared(Allocator *a, Smart &&sp) { return CreateSharedForPointer::type>>(a, std::forward(sp)); } template static constexpr SharedPointer CreateShared(Allocator *a, T *p) { return CreateSharedForPointer>(a, p); } template static constexpr SharedPointer CreateSharedWithoutManagement(Allocator *a, T *p) { return CreateSharedForPointer>(a, p); } }; template class StatefulObjectFactory { public: using Allocator = typename Policy::Allocator; private: using StaticObjectFactory = ObjectFactory; private: Allocator *m_allocator; public: constexpr explicit StatefulObjectFactory(Allocator *a) : m_allocator(a) { /* ... */ } template constexpr EmplacedRef CreateSharedEmplaced(Args &&... args) { return StaticObjectFactory::template CreateSharedEmplaced(m_allocator, std::forward(args)...); } template static constexpr Impl *GetEmplacedImplPointer(const SharedPointer &sp) { return StaticObjectFactory::template GetEmplacedImplPointer(sp); } template constexpr SharedPointer CreateShared(Allocator *a, Smart &&sp) { return StaticObjectFactory::template CreateShared(m_allocator, std::forward(sp)); } template constexpr SharedPointer CreateShared(Allocator *a, T *p) { return StaticObjectFactory::template CreateShared(m_allocator, p); } template constexpr SharedPointer CreateSharedWithoutManagement(Allocator *a, T *p) { return StaticObjectFactory::template CreateSharedWithoutManagement(m_allocator, p); } }; using DefaultObjectFactory = ObjectFactory; using MemoryResourceObjectFactory = ObjectFactory; template inline EmplacedRef CreateSharedObjectEmplaced(Args &&... args) { return DefaultObjectFactory::CreateSharedEmplaced(std::forward(args)...); } template inline EmplacedRef CreateSharedObjectEmplaced(MemoryResource *mr, Args &&... args) { return MemoryResourceObjectFactory::CreateSharedEmplaced(mr, std::forward(args)...); } template inline SharedPointer CreateSharedObject(Smart &&sp) { return DefaultObjectFactory::CreateShared(std::forward(sp)); } template inline SharedPointer CreateSharedObject(MemoryResource *mr, Smart &&sp) { return MemoryResourceObjectFactory::CreateShared(mr, std::forward(sp)); } template inline SharedPointer CreateSharedObject(T *ptr) { return DefaultObjectFactory::CreateShared(std::move(ptr)); } template inline SharedPointer CreateSharedObjectWithoutManagement(T *ptr) { return DefaultObjectFactory::CreateSharedWithoutManagement(std::move(ptr)); } template inline SharedPointer CreateSharedObjectWithoutManagement(MemoryResource *mr, T *ptr) { return DefaultObjectFactory::CreateSharedWithoutManagement(mr, std::move(ptr)); } }