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