#pragma once #ifdef __cpp_concepts # include "../ds/concept.h" # include "pal_consts.h" # include namespace snmalloc { /** * PALs must advertize the bit vector of their supported features and the * platform's page size. This concept enforces that these are indeed * constants that fit in the desired types. (This is subtly different from * saying that they are the required types; C++ may handle constants without * much regard for their claimed type.) */ template concept ConceptPAL_static_members = requires() { typename std::integral_constant; typename std::integral_constant; }; /** * PALs expose an error reporting function which takes a const C string. */ template concept ConceptPAL_error = requires(const char* const str) { { PAL::error(str) } -> ConceptSame; }; /** * PALs expose a basic library of memory operations. */ template concept ConceptPAL_memops = requires(void* vp, size_t sz) { { PAL::notify_not_using(vp, sz) } noexcept -> ConceptSame; { PAL::template notify_using(vp, sz) } noexcept -> ConceptSame; { PAL::template notify_using(vp, sz) } noexcept -> ConceptSame; { PAL::template zero(vp, sz) } noexcept -> ConceptSame; { PAL::template zero(vp, sz) } noexcept -> ConceptSame; }; /** * Absent any feature flags, the PAL must support a crude primitive allocator */ template concept ConceptPAL_reserve_at_least = requires(PAL p, void* vp, size_t sz) { { PAL::reserve_at_least(sz) } noexcept -> ConceptSame>; }; /** * Some PALs expose a richer allocator which understands aligned allocations */ template concept ConceptPAL_reserve_aligned = requires(size_t sz) { { PAL::template reserve_aligned(sz) } noexcept -> ConceptSame; { PAL::template reserve_aligned(sz) } noexcept -> ConceptSame; }; /** * Some PALs can provide memory pressure callbacks. */ template concept ConceptPAL_mem_low_notify = requires(PalNotificationObject* pno) { { PAL::expensive_low_memory_check() } -> ConceptSame; { PAL::register_for_low_memory_callback(pno) } -> ConceptSame; }; /** * PALs ascribe to the conjunction of several concepts. These are broken * out by the shape of the requires() quantifiers required and by any * requisite claimed pal_features. PALs not claiming particular features * are, naturally, not bound by the corresponding concept. */ template concept ConceptPAL = ConceptPAL_static_members && ConceptPAL_error && ConceptPAL_memops && (!(PAL::pal_features & LowMemoryNotification) || ConceptPAL_mem_low_notify) && (!(PAL::pal_features & NoAllocation) && ( (!!(PAL::pal_features & AlignedAllocation) || ConceptPAL_reserve_at_least) && (!(PAL::pal_features & AlignedAllocation) || ConceptPAL_reserve_aligned))); } // namespace snmalloc #endif