#pragma once #ifdef __cpp_concepts # include # include "../ds/concept.h" # include "../pal/pal_concept.h" # include "../ds/address.h" namespace snmalloc { class MetaEntry; /** * The core of the static pagemap accessor interface: {get,set}_metadata. * * get_metadata takes a bool-ean template parameter indicating whether it may * be accessing memory that is not known to be committed. */ template concept ConceptBackendMeta = requires( address_t addr, size_t sz, const MetaEntry& t) { { Meta::set_metaentry(addr, sz, t) } -> ConceptSame; { Meta::template get_metaentry(addr) } -> ConceptSame; { Meta::template get_metaentry(addr) } -> ConceptSame; }; /** * The pagemap can also be told to commit backing storage for a range of * addresses. This is broken out to a separate concept so that we can * annotate which functions expect to do this vs. which merely use the core * interface above. In practice, use ConceptBackendMetaRange (without the * underscore) below, which combines this and the core concept, above. */ template concept ConceptBackendMeta_Range = requires(address_t addr, size_t sz) { { Meta::register_range(addr, sz) } -> ConceptSame; }; /** * The full pagemap accessor interface, with all of {get,set}_metadata and * register_range. Use this to annotate callers that need the full interface * and use ConceptBackendMeta for callers that merely need {get,set}_metadata, * but note that the difference is just for humans and not compilers (since * concept checking is lower bounding and does not constrain the templatized * code to use only those affordances given by the concept). */ template concept ConceptBackendMetaRange = ConceptBackendMeta && ConceptBackendMeta_Range; /** * The backend also defines domestication (that is, the difference between * Tame and Wild CapPtr bounds). It exports the intended affordance for * testing a Wild pointer and either returning nullptr or the original * pointer, now Tame. */ template concept ConceptBackendDomestication = requires( typename Globals::LocalState* ls, capptr::AllocWild ptr) { { Globals::capptr_domesticate(ls, ptr) } -> ConceptSame>; { Globals::capptr_domesticate(ls, ptr.template as_static()) } -> ConceptSame>; }; class CommonConfig; struct Flags; /** * Backend global objects of type T must obey a number of constraints. They * must... * * * inherit from CommonConfig (see commonconfig.h) * * specify which PAL is in use via T::Pal * * have static pagemap accessors via T::Pagemap * * define a T::LocalState type (and alias it as T::Pagemap::LocalState) * * define T::Options of type snmalloc::Flags * * expose the global allocator pool via T::pool() * */ template concept ConceptBackendGlobals = std::is_base_of::value && ConceptPAL && ConceptBackendMetaRange && requires() { typename Globals::LocalState; { Globals::Options } -> ConceptSameModRef; typename Globals::GlobalPoolState; { Globals::pool() } -> ConceptSame; }; /** * The lazy version of the above; please see ds/concept.h and use sparingly. */ template concept ConceptBackendGlobalsLazy = !is_type_complete_v || ConceptBackendGlobals; } // namespace snmalloc #endif