1///
2module std.experimental.allocator.building_blocks.null_allocator;
3
4/**
5$(D NullAllocator) is an emphatically empty implementation of the allocator
6interface. Although it has no direct use, it is useful as a "terminator" in
7composite allocators.
8*/
9struct NullAllocator
10{
11    import std.typecons : Ternary;
12    /**
13    $(D NullAllocator) advertises a relatively large _alignment equal to 64 KB.
14    This is because $(D NullAllocator) never actually needs to honor this
15    alignment and because composite allocators using $(D NullAllocator)
16    shouldn't be unnecessarily constrained.
17    */
18    enum uint alignment = 64 * 1024;
19    // /// Returns $(D n).
20    //size_t goodAllocSize(size_t n) shared const
21    //{ return .goodAllocSize(this, n); }
22    /// Always returns $(D null).
23    void[] allocate(size_t) shared { return null; }
24    /// Always returns $(D null).
25    void[] alignedAllocate(size_t, uint) shared { return null; }
26    /// Always returns $(D null).
27    void[] allocateAll() shared { return null; }
28    /**
29    These methods return $(D false).
30    Precondition: $(D b is null). This is because there is no other possible
31    legitimate input.
32    */
33    bool expand(ref void[] b, size_t s) shared
34    { assert(b is null); return s == 0; }
35    /// Ditto
36    bool reallocate(ref void[] b, size_t) shared
37    { assert(b is null); return false; }
38    /// Ditto
39    bool alignedReallocate(ref void[] b, size_t, uint) shared
40    { assert(b is null); return false; }
41    /// Returns $(D Ternary.no).
42    Ternary owns(void[]) shared const { return Ternary.no; }
43    /**
44    Returns $(D Ternary.no).
45    */
46    Ternary resolveInternalPointer(const void*, ref void[]) shared const
47    { return Ternary.no; }
48    /**
49    No-op.
50    Precondition: $(D b is null)
51    */
52    bool deallocate(void[] b) shared { assert(b is null); return true; }
53    /**
54    No-op.
55    */
56    bool deallocateAll() shared { return true; }
57    /**
58    Returns $(D Ternary.yes).
59    */
60    Ternary empty() shared const { return Ternary.yes; }
61    /**
62    Returns the $(D shared) global instance of the $(D NullAllocator).
63    */
64    static shared NullAllocator instance;
65}
66
67@system unittest
68{
69    assert(NullAllocator.instance.alignedAllocate(100, 0) is null);
70    assert(NullAllocator.instance.allocateAll() is null);
71    auto b = NullAllocator.instance.allocate(100);
72    assert(b is null);
73    assert(NullAllocator.instance.expand(b, 0));
74    assert(!NullAllocator.instance.expand(b, 42));
75    assert(!NullAllocator.instance.reallocate(b, 42));
76    assert(!NullAllocator.instance.alignedReallocate(b, 42, 0));
77    NullAllocator.instance.deallocate(b);
78    NullAllocator.instance.deallocateAll();
79
80    import std.typecons : Ternary;
81    assert(NullAllocator.instance.empty() == Ternary.yes);
82    assert(NullAllocator.instance.owns(null) == Ternary.no);
83    void[] p;
84    assert(NullAllocator.instance.resolveInternalPointer(null, p) == Ternary.no);
85}
86