/* * 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 namespace ams::sf { namespace impl { struct StatelessDummyAllocator{}; template class ObjectImplFactoryWithStatelessAllocator { public: class Object; using Allocator = StatelessDummyAllocator; using StatelessAllocator = typename Policy::StatelessAllocator; class Object final : private ::ams::sf::impl::ServiceObjectImplBase2, public Base { NON_COPYABLE(Object); NON_MOVEABLE(Object); friend class ObjectImplFactoryWithStatelessAllocator; private: template explicit Object(Args &&... args) : Base(std::forward(args)...) { /* ... */ } static void *operator new(size_t size) { return Policy::template AllocateAligned(size, alignof(Object)); } static void operator delete(void *ptr, size_t size) { return Policy::template DeallocateAligned(ptr, size, alignof(Object)); } static void *operator new(size_t size, Allocator *); static void operator delete(void *ptr, Allocator *); void DisposeImpl() { delete this; } public: void AddReference() { ServiceObjectImplBase2::AddReferenceImpl(); } void Release() { if (ServiceObjectImplBase2::ReleaseImpl()) { this->DisposeImpl(); } } Allocator *GetAllocator() const { return nullptr; } }; template static Object *Create(Args &&... args) { return new Object(std::forward(args)...); } template static Object *Create(Allocator *, Args &&... args) { return new Object(std::forward(args)...); } }; template class ObjectImplFactoryWithStatefulAllocator { public: using Allocator = typename Policy::Allocator; class Object final : private ::ams::sf::impl::ServiceObjectImplBase2, public Base { NON_COPYABLE(Object); NON_MOVEABLE(Object); friend class ObjectImplFactoryWithStatefulAllocator; private: Allocator *m_allocator; private: template explicit Object(Args &&... args) : Base(std::forward(args)...) { /* ... */ } static void *operator new(size_t size); static void operator delete(void *ptr, size_t size) { /* ... */ } static void *operator new(size_t size, Allocator *a) { return Policy::AllocateAligned(a, size, alignof(Object)); } static void operator delete(void *ptr, Allocator *a) { return Policy::DeallocateAligned(a, ptr, sizeof(Object), alignof(Object)); } void DisposeImpl() { Allocator *a = this->GetAllocator(); this->~Object(); operator delete(this, a); } public: void AddReference() { ServiceObjectImplBase2::AddReferenceImpl(); } void Release() { if (ServiceObjectImplBase2::ReleaseImpl()) { this->DisposeImpl(); } } Allocator *GetAllocator() const { return m_allocator; } }; template static Object *Create(Allocator *a, Args &&... args) { auto *ptr = new (a) Object(std::forward(args)...); if (ptr != nullptr) { ptr->m_allocator = a; } return ptr; } }; } template class ObjectImplFactory; template requires (!IsStatefulPolicy) class ObjectImplFactory : public impl::ObjectImplFactoryWithStatelessAllocator{}; template requires (IsStatefulPolicy) class ObjectImplFactory : public impl::ObjectImplFactoryWithStatefulAllocator{}; }