Files
snmalloc/src/backend/backend_concept.h
Nathaniel Wesley Filardo 7940fee00c Refactor MetaEntry remote_and_sizeclass
Introduce a class that we can use to more completely separate the frontend
encoding details from the backend.
2022-03-21 23:21:24 +00:00

120 lines
3.8 KiB
C++

#pragma once
#ifdef __cpp_concepts
# include <cstddef>
# 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<typename Meta>
concept ConceptBackendMeta =
requires(
address_t addr,
size_t sz,
const MetaEntry& t)
{
{ Meta::set_metaentry(addr, sz, t) } -> ConceptSame<void>;
{ Meta::template get_metaentry<MetaEntry, true>(addr) }
-> ConceptSame<const MetaEntry&>;
{ Meta::template get_metaentry<MetaEntry, false>(addr) }
-> ConceptSame<const MetaEntry&>;
};
/**
* 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<typename Meta>
concept ConceptBackendMeta_Range =
requires(address_t addr, size_t sz)
{
{ Meta::register_range(addr, sz) } -> ConceptSame<void>;
};
/**
* 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<typename Meta>
concept ConceptBackendMetaRange =
ConceptBackendMeta<Meta> && ConceptBackendMeta_Range<Meta>;
/**
* 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<typename Globals>
concept ConceptBackendDomestication =
requires(
typename Globals::LocalState* ls,
capptr::AllocWild<void> ptr)
{
{ Globals::capptr_domesticate(ls, ptr) }
-> ConceptSame<capptr::Alloc<void>>;
{ Globals::capptr_domesticate(ls, ptr.template as_static<char>()) }
-> ConceptSame<capptr::Alloc<char>>;
};
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<typename Globals>
concept ConceptBackendGlobals =
std::is_base_of<CommonConfig, Globals>::value &&
ConceptPAL<typename Globals::Pal> &&
ConceptBackendMetaRange<typename Globals::Pagemap> &&
requires()
{
typename Globals::LocalState;
{ Globals::Options } -> ConceptSameModRef<const Flags>;
typename Globals::GlobalPoolState;
{ Globals::pool() } -> ConceptSame<typename Globals::GlobalPoolState &>;
};
/**
* The lazy version of the above; please see ds/concept.h and use sparingly.
*/
template<typename Globals>
concept ConceptBackendGlobalsLazy =
!is_type_complete_v<Globals> || ConceptBackendGlobals<Globals>;
} // namespace snmalloc
#endif