// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. #pragma once // The Windows build doesn't fully support std::pmr, but we can // work around that limitation by providing our own default resource. // // This is a reimplementation of the default aligned allocator in // . // // Outside of Windows, til::pmr will use pmr directly. namespace til::pmr { #ifdef __INSIDE_WINDOWS // I really, really didn't want to have to stick this function in here. // However, the default constructor for optional (really, "optional construct base") // insists on being able to default-construct its type. We have an instance in til // of an optional> that forces _Aligned_get_default_resource // to get pulled in. This pragma mollifies the linker, and using this function in // get_default_resource below forces it to be included by the compiler. // I *believe* that if the VC++ Runtime is updated to include the PMR source, // this will safely no-op (since it's an ALTERNATENAME). #if defined(_M_AMD64) || defined(_M_ARM64) || defined(_M_ARM) #pragma comment(linker, "/ALTERNATENAME:_Aligned_get_default_resource=TIL_PMR_Aligned_get_default_resource") #else #pragma comment(linker, "/ALTERNATENAME:__Aligned_get_default_resource=_TIL_PMR_Aligned_get_default_resource") #endif extern "C" _TIL_INLINEPREFIX std::pmr::memory_resource* __cdecl TIL_PMR_Aligned_get_default_resource() noexcept { class aligned_new_delete_resource : public std::pmr::memory_resource { bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override { return this == &other; } void* do_allocate(const size_t bytes, const size_t align) override { if (align > __STDCPP_DEFAULT_NEW_ALIGNMENT__) { return ::operator new (bytes, std::align_val_t{ align }); } return ::operator new(bytes); } void do_deallocate(void* const ptr, const size_t bytes, const size_t align) noexcept override { if (align > __STDCPP_DEFAULT_NEW_ALIGNMENT__) { return ::operator delete (ptr, bytes, std::align_val_t{ align }); } ::operator delete(ptr, bytes); } }; static aligned_new_delete_resource resource; return &resource; } [[nodiscard]] inline std::pmr::memory_resource* get_default_resource() noexcept { return TIL_PMR_Aligned_get_default_resource(); } #else // !__INSIDE_WINDOWS [[nodiscard]] inline std::pmr::memory_resource* get_default_resource() noexcept { return std::pmr::get_default_resource(); } #endif }