`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>
123 lines
3.9 KiB
C++
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
|