1 ///
2 module stdx.allocator.mmap_allocator;
3 
4 // MmapAllocator
5 /**
6 
7 Allocator (currently defined only for Posix and Windows) using
8 $(D $(LINK2 https://en.wikipedia.org/wiki/Mmap, mmap))
9 and $(D $(LUCKY munmap)) directly (or their Windows equivalents). There is no
10 additional structure: each call to $(D allocate(s)) issues a call to
11 $(D mmap(null, s, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)),
12 and each call to $(D deallocate(b)) issues $(D munmap(b.ptr, b.length)).
13 So $(D MmapAllocator) is usually intended for allocating large chunks to be
14 managed by fine-granular allocators.
15 
16 */
17 struct MmapAllocator
18 {
19     /// The one shared instance.
20     enum MmapAllocator instance = MmapAllocator();
21 
22     /**
23     Alignment is page-size and hardcoded to 4096 (even though on certain systems
24     it could be larger).
25     */
26     enum size_t alignment = 4096;
27 
28     version(Posix)
29     {
30         /// Allocator API.
31         static void[] allocate()(size_t bytes)
32         {
33             import core.sys.posix.sys.mman : mmap, MAP_ANON, PROT_READ,
34                 PROT_WRITE, MAP_PRIVATE, MAP_FAILED;
35             if (!bytes) return null;
36             auto p = mmap(null, bytes, PROT_READ | PROT_WRITE,
37                 MAP_PRIVATE | MAP_ANON, -1, 0);
38             if (p is MAP_FAILED) return null;
39             return p[0 .. bytes];
40         }
41 
42         /// Ditto
43         static bool deallocate()(void[] b)
44         {
45             import core.sys.posix.sys.mman : munmap;
46             if (b.ptr) munmap(b.ptr, b.length) == 0 || assert(0);
47             return true;
48         }
49     }
50     else version(Windows)
51     {
52         import core.sys.windows.windows : VirtualAlloc, VirtualFree, MEM_COMMIT,
53             PAGE_READWRITE, MEM_RELEASE;
54 
55         /// Allocator API.
56         static void[] allocate()(size_t bytes)
57         {
58             if (!bytes) return null;
59             auto p = VirtualAlloc(null, bytes, MEM_COMMIT, PAGE_READWRITE);
60             if (p == null)
61                 return null;
62             return p[0 .. bytes];
63         }
64 
65         /// Ditto
66         static bool deallocate()(void[] b)
67         {
68             return b.ptr is null || VirtualFree(b.ptr, 0, MEM_RELEASE) != 0;
69         }
70     }
71 }
72 
73 @system unittest
74 {
75     alias alloc = MmapAllocator.instance;
76     auto p = alloc.allocate(100);
77     assert(p.length == 100);
78     alloc.deallocate(p);
79 }