-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathmmap_allocator.d
79 lines (70 loc) · 2.28 KB
/
mmap_allocator.d
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
///
module stdx.allocator.mmap_allocator;
// MmapAllocator
/**
Allocator (currently defined only for Posix and Windows) using
$(D $(LINK2 https://en.wikipedia.org/wiki/Mmap, mmap))
and $(D $(LUCKY munmap)) directly (or their Windows equivalents). There is no
additional structure: each call to $(D allocate(s)) issues a call to
$(D mmap(null, s, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)),
and each call to $(D deallocate(b)) issues $(D munmap(b.ptr, b.length)).
So $(D MmapAllocator) is usually intended for allocating large chunks to be
managed by fine-granular allocators.
*/
struct MmapAllocator
{
/// The one shared instance.
enum MmapAllocator instance = MmapAllocator();
/**
Alignment is page-size and hardcoded to 4096 (even though on certain systems
it could be larger).
*/
enum size_t alignment = 4096;
version(Posix)
{
/// Allocator API.
static void[] allocate()(size_t bytes)
{
import core.sys.posix.sys.mman : mmap, MAP_ANON, PROT_READ,
PROT_WRITE, MAP_PRIVATE, MAP_FAILED;
if (!bytes) return null;
auto p = mmap(null, bytes, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (p is MAP_FAILED) return null;
return p[0 .. bytes];
}
/// Ditto
static bool deallocate()(void[] b)
{
import core.sys.posix.sys.mman : munmap;
if (b.ptr) munmap(b.ptr, b.length) == 0 || assert(0);
return true;
}
}
else version(Windows)
{
import core.sys.windows.windows : VirtualAlloc, VirtualFree, MEM_COMMIT,
PAGE_READWRITE, MEM_RELEASE;
/// Allocator API.
static void[] allocate()(size_t bytes)
{
if (!bytes) return null;
auto p = VirtualAlloc(null, bytes, MEM_COMMIT, PAGE_READWRITE);
if (p == null)
return null;
return p[0 .. bytes];
}
/// Ditto
static bool deallocate()(void[] b)
{
return b.ptr is null || VirtualFree(b.ptr, 0, MEM_RELEASE) != 0;
}
}
}
@system unittest
{
alias alloc = MmapAllocator.instance;
auto p = alloc.allocate(100);
assert(p.length == 100);
alloc.deallocate(p);
}