Files
snmalloc/src/backend/backend_concept.h
Nathaniel Wesley Filardo 1a608e6066 NFC: Introduce pointer domestication backend support
`capptr_domesticate<Backend>(Backend::LocalState*, CapPtr<T, B>)` is the
intended affordance for conversion to covert from a `CapPtr<T, B>` with
`B::wildness` `Wild` to a `CapPtr<>` with `B::with_wildness<Tame>` and thence
plumbed into the rest of the machinery.

David added the SFINAE wrapper so that `Backend`-s now don't need to implement a
domestication callback; instead, if the `Backend` does not provide a
`capptr_domesticate` function, a default, which just does an explicit type cast,
will be used instead.

This is not yet hooked into the rest of the tree.

Co-authored-by: David Chisnall <David.Chisnall@microsoft.com>
2021-10-13 16:30:41 +01:00

123 lines
3.9 KiB
C++

#pragma once
#ifdef __cpp_concepts
# include <cstddef>
# include "../ds/concept.h"
# include "../pal/pal_concept.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(
typename Meta::LocalState* ls,
address_t addr,
size_t sz,
MetaEntry t)
{
{ Meta::set_metaentry(ls, addr, sz, t) } -> ConceptSame<void>;
{ Meta::template get_metaentry<true>(ls, addr) }
-> ConceptSame<const MetaEntry&>;
{ Meta::template get_metaentry<false>(ls, 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(typename Meta::LocalState* ls, address_t addr, size_t sz)
{
{ Meta::register_range(ls, 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> &&
ConceptSame<
typename Globals::LocalState,
typename Globals::Pagemap::LocalState> &&
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