1///
2module std.experimental.allocator.mmap_allocator;
3
4// MmapAllocator
5/**
6
7Allocator (currently defined only for Posix and Windows) using
8$(D $(LINK2 https://en.wikipedia.org/wiki/Mmap, mmap))
9and $(D $(LUCKY munmap)) directly (or their Windows equivalents). There is no
10additional 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)),
12and each call to $(D deallocate(b)) issues $(D munmap(b.ptr, b.length)).
13So $(D MmapAllocator) is usually intended for allocating large chunks to be
14managed by fine-granular allocators.
15
16*/
17struct MmapAllocator
18{
19    /// The one shared instance.
20    static shared MmapAllocator instance;
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        void[] allocate(size_t bytes) shared
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        bool deallocate(void[] b) shared
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        void[] allocate(size_t bytes) shared
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        bool deallocate(void[] b) shared
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}
80