1 // Written in the D programming language.
2 /**
3 Collection of typical and useful prebuilt allocators using the given
4 components. User code would typically import this module and use its
5 facilities, or import individual heap building blocks and assemble them.
6 
7 Source: $(PHOBOSSRC std/experimental/allocator/_showcase.d)
8 */
9 module std.experimental.allocator.showcase;
10 
11 import std.experimental.allocator.building_blocks.fallback_allocator,
12     std.experimental.allocator.gc_allocator,
13     std.experimental.allocator.building_blocks.region;
14 import std.traits : hasMember;
15 
16 /**
17 
18 Allocator that uses stack allocation for up to `stackSize` bytes and
19 then falls back to `Allocator`. Defined as:
20 
21 ----
22 alias StackFront(size_t stackSize, Allocator) =
23     FallbackAllocator!(
24         InSituRegion!(stackSize, Allocator.alignment,
25             hasMember!(Allocator, "deallocate")
26                 ? Yes.defineDeallocate
27                 : No.defineDeallocate),
28         Allocator);
29 ----
30 
31 Choosing `stackSize` is as always a compromise. Too small a size exhausts the
32 stack storage after a few allocations, after which there are no gains over the
33 backup allocator. Too large a size increases the stack consumed by the thread
34 and may end up worse off because it explores cold portions of the stack.
35 
36 */
37 alias StackFront(size_t stackSize, Allocator = GCAllocator) =
38     FallbackAllocator!(
39         InSituRegion!(stackSize, Allocator.alignment),
40         Allocator);
41 
42 ///
43 @system unittest
44 {
45     StackFront!4096 a;
46     auto b = a.allocate(4000);
47     assert(b.length == 4000);
48     auto c = a.allocate(4000);
49     assert(c.length == 4000);
50     a.deallocate(b);
51     a.deallocate(c);
52 }
53 
54 /**
55 Creates a scalable `AllocatorList` of `Regions`, each having at least
56 `bytesPerRegion` bytes. Allocation is very fast. This allocator does not offer
57 `deallocate` but does free all regions in its destructor. It is recommended for
58 short-lived batch applications that count on never running out of memory.
59 */
60 auto mmapRegionList(size_t bytesPerRegion)
61 {
62     static struct Factory
63     {
64         size_t bytesPerRegion;
65         import std.algorithm.comparison : max;
66         import std.experimental.allocator.building_blocks.region
67             : Region;
68         import std.experimental.allocator.mmap_allocator
69             : MmapAllocator;
70         this(size_t n)
71         {
72             bytesPerRegion = n;
73         }
74         auto opCall(size_t n)
75         {
76             return Region!MmapAllocator(max(n, bytesPerRegion));
77         }
78     }
79     import std.experimental.allocator.building_blocks.allocator_list
80         : AllocatorList;
81     import std.experimental.allocator.building_blocks.null_allocator
82         : NullAllocator;
83     auto shop = Factory(bytesPerRegion);
84     return AllocatorList!(Factory, NullAllocator)(shop);
85 }
86 
87 ///
88 @system unittest
89 {
90     auto alloc = mmapRegionList(1024 * 1024);
91     const b = alloc.allocate(100);
92     assert(b.length == 100);
93 }