forked from microsoft/snmalloc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pal_concept.h
125 lines (110 loc) · 3.57 KB
/
pal_concept.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#pragma once
#ifdef __cpp_concepts
# include "../ds/concept.h"
# include "pal_consts.h"
# include "pal_ds.h"
# include <utility>
namespace snmalloc
{
/*
* These concepts enforce 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.)
*/
/**
* PALs must advertize the bit vector of their supported features.
*/
template<typename PAL>
concept ConceptPAL_static_features = requires()
{
typename std::integral_constant<uint64_t, PAL::pal_features>;
};
/**
* PALs must advertise the size of the address space and their page size
*/
template<typename PAL>
concept ConceptPAL_static_sizes = requires()
{
typename std::integral_constant<std::size_t, PAL::address_bits>;
typename std::integral_constant<std::size_t, PAL::page_size>;
};
/**
* PALs expose an error reporting function which takes a const C string.
*/
template<typename PAL>
concept ConceptPAL_error = requires(const char* const str)
{
{ PAL::error(str) } -> ConceptSame<void>;
};
/**
* PALs expose a basic library of memory operations.
*/
template<typename PAL>
concept ConceptPAL_memops = requires(void* vp, std::size_t sz)
{
{ PAL::notify_not_using(vp, sz) } noexcept -> ConceptSame<void>;
{ PAL::template notify_using<NoZero>(vp, sz) } noexcept
-> ConceptSame<void>;
{ PAL::template notify_using<YesZero>(vp, sz) } noexcept
-> ConceptSame<void>;
{ PAL::template zero<false>(vp, sz) } noexcept -> ConceptSame<void>;
{ PAL::template zero<true>(vp, sz) } noexcept -> ConceptSame<void>;
};
/**
* Absent any feature flags, the PAL must support a crude primitive allocator
*/
template<typename PAL>
concept ConceptPAL_reserve =
requires(PAL p, std::size_t sz)
{
{ PAL::reserve(sz) } noexcept -> ConceptSame<void*>;
};
/**
* Some PALs expose a richer allocator which understands aligned allocations
*/
template<typename PAL>
concept ConceptPAL_reserve_aligned = requires(std::size_t sz)
{
{ PAL::template reserve_aligned<true>(sz) } noexcept -> ConceptSame<void*>;
{ PAL::template reserve_aligned<false>(sz) } noexcept
-> ConceptSame<void*>;
};
/**
* Some PALs can provide memory pressure callbacks.
*/
template<typename PAL>
concept ConceptPAL_mem_low_notify = requires(PalNotificationObject* pno)
{
{ PAL::expensive_low_memory_check() } -> ConceptSame<bool>;
{ PAL::register_for_low_memory_callback(pno) } -> ConceptSame<void>;
};
template<typename PAL>
concept ConceptPAL_get_entropy64 = requires()
{
{ PAL::get_entropy64() } -> ConceptSame<uint64_t>;
};
/**
* 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<typename PAL>
concept ConceptPAL =
ConceptPAL_static_features<PAL> &&
ConceptPAL_static_sizes<PAL> &&
ConceptPAL_error<PAL> &&
ConceptPAL_memops<PAL> &&
(!pal_supports<Entropy, PAL> ||
ConceptPAL_get_entropy64<PAL>) &&
(!pal_supports<LowMemoryNotification, PAL> ||
ConceptPAL_mem_low_notify<PAL>) &&
(pal_supports<NoAllocation, PAL> ||
(
(!pal_supports<AlignedAllocation, PAL> ||
ConceptPAL_reserve_aligned<PAL>) &&
ConceptPAL_reserve<PAL>)
);
} // namespace snmalloc
#endif