/* * 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 /* Forward declare ams::fs allocate shared. */ namespace ams::fs::impl { template class AllocatorTemplateT, typename Impl, typename... Args> std::shared_ptr AllocateSharedImpl(Args &&... args); } namespace ams::fssystem { /* ACCURATE_TO_VERSION: Unknown */ using AllocateFunction = void *(*)(size_t size); using DeallocateFunction = void (*)(void *ptr, size_t size); void InitializeAllocator(AllocateFunction allocate_func, DeallocateFunction deallocate_func); void InitializeAllocatorForSystem(AllocateFunction allocate_func, DeallocateFunction deallocate_func); void *Allocate(size_t size); void Deallocate(void *ptr, size_t size); namespace impl { template class AllocatorFunctionSet { public: static void *Allocate(size_t size); static void *AllocateUnsafe(size_t size); static void Deallocate(void *ptr, size_t size); static void DeallocateUnsafe(void *ptr, size_t size); static void LockAllocatorMutex(); static void UnlockAllocatorMutex(); }; using AllocatorFunctionSetForNormal = AllocatorFunctionSet; using AllocatorFunctionSetForSystem = AllocatorFunctionSet; template class AllocatorTemplate : public std::allocator { public: template struct rebind { using other = AllocatorTemplate; }; private: static ALWAYS_INLINE T *AllocateImpl(::std::size_t n) { if constexpr (AllocateWhileLocked) { auto * const p = Impl::AllocateUnsafe(sizeof(T) * n); Impl::UnlockAllocatorMutex(); return static_cast(p); } else { return static_cast(Impl::Allocate(sizeof(T) * n)); } } public: AllocatorTemplate() { /* ... */ } template AllocatorTemplate(const AllocatorTemplate &) { /* ... */ } [[nodiscard]] T *allocate(::std::size_t n) { auto * const p = AllocateImpl(n); if constexpr (RequireNonNull) { AMS_ABORT_UNLESS(p != nullptr); } return p; } void deallocate(T *p, ::std::size_t n) { Impl::Deallocate(p, sizeof(T) * n); } }; template using AllocatorTemplateForAllocateShared = AllocatorTemplate; } template std::shared_ptr AllocateShared(Args &&... args) { return ::ams::fs::impl::AllocateSharedImpl(std::forward(args)...); } template Result AllocateSharedForSystem(std::shared_ptr *out, Args &&... args) { /* Allocate the object. */ auto p = ::ams::fs::impl::AllocateSharedImpl(std::forward(args)...); /* Check that allocation succeeded. */ R_UNLESS(p != nullptr, ErrorResult()); /* Return the allocated object. */ *out = std::move(p); return ResultSuccess(); } }