/* * 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 . */ #pragma once #include #include #include namespace ams::tipc { template concept IsServiceObjectAllocator = requires (T &t) { { t.Allocate() } -> std::convertible_to; }; template requires IsServiceObject class SingletonAllocator final { static_assert(N >= 1); private: T m_singleton; public: constexpr ALWAYS_INLINE SingletonAllocator() : m_singleton() { /* ... */ } ALWAYS_INLINE ServiceObjectBase *Allocate() { return std::addressof(m_singleton); } }; template requires IsServiceObject class SlabAllocator final : public ServiceObjectDeleter { private: struct Entry { bool used; util::TypedStorage storage; }; private: os::SdkMutex m_mutex; Entry m_entries[N]; public: constexpr ALWAYS_INLINE SlabAllocator() : m_entries() { /* ... */ } ServiceObjectBase *Allocate() { std::scoped_lock lk(m_mutex); for (size_t i = 0; i < N; ++i) { if (!m_entries[i].used) { m_entries[i].used = true; return util::ConstructAt(m_entries[i].storage); } } return nullptr; } void Deallocate(ServiceObjectBase *object) { std::scoped_lock lk(m_mutex); for (size_t i = 0; i < N; ++i) { if (m_entries[i].used && GetPointer(m_entries[i].storage) == object) { util::DestroyAt(m_entries[i].storage); m_entries[i].used = false; return; } } AMS_ABORT("Failed to deallocate entry in SlabAllocator"); } public: virtual void DeleteServiceObject(ServiceObjectBase *object) override { return this->Deallocate(object); } }; static_assert(IsServiceObjectAllocator>); static_assert(IsServiceObjectDeleter>); }