| // Written in the D programming language. | |
| /** | |
| Collection of typical and useful prebuilt allocators using the given | |
| components. User code would typically import this module and use its | |
| facilities, or import individual heap building blocks and assemble them. | |
| Source: $(PHOBOSSRC std/experimental/allocator/_showcase.d) | |
| */ | |
| module std.experimental.allocator.showcase; | |
| import std.experimental.allocator.building_blocks.fallback_allocator, | |
| std.experimental.allocator.gc_allocator, | |
| std.experimental.allocator.building_blocks.region; | |
| import std.traits : hasMember; | |
| /** | |
| Allocator that uses stack allocation for up to `stackSize` bytes and | |
| then falls back to `Allocator`. Defined as: | |
| ---- | |
| alias StackFront(size_t stackSize, Allocator) = | |
| FallbackAllocator!( | |
| InSituRegion!(stackSize, Allocator.alignment, | |
| hasMember!(Allocator, "deallocate") | |
| ? Yes.defineDeallocate | |
| : No.defineDeallocate), | |
| Allocator); | |
| ---- | |
| Choosing `stackSize` is as always a compromise. Too small a size exhausts the | |
| stack storage after a few allocations, after which there are no gains over the | |
| backup allocator. Too large a size increases the stack consumed by the thread | |
| and may end up worse off because it explores cold portions of the stack. | |
| */ | |
| alias StackFront(size_t stackSize, Allocator = GCAllocator) = | |
| FallbackAllocator!( | |
| InSituRegion!(stackSize, Allocator.alignment), | |
| Allocator); | |
| /// | |
| @system unittest | |
| { | |
| StackFront!4096 a; | |
| auto b = a.allocate(4000); | |
| assert(b.length == 4000); | |
| auto c = a.allocate(4000); | |
| assert(c.length == 4000); | |
| a.deallocate(b); | |
| a.deallocate(c); | |
| } | |
| /** | |
| Creates a scalable `AllocatorList` of `Regions`, each having at least | |
| `bytesPerRegion` bytes. Allocation is very fast. This allocator does not offer | |
| `deallocate` but does free all regions in its destructor. It is recommended for | |
| short-lived batch applications that count on never running out of memory. | |
| */ | |
| auto mmapRegionList(size_t bytesPerRegion) | |
| { | |
| static struct Factory | |
| { | |
| size_t bytesPerRegion; | |
| import std.algorithm.comparison : max; | |
| import std.experimental.allocator.building_blocks.region | |
| : Region; | |
| import std.experimental.allocator.mmap_allocator | |
| : MmapAllocator; | |
| this(size_t n) | |
| { | |
| bytesPerRegion = n; | |
| } | |
| auto opCall(size_t n) | |
| { | |
| return Region!MmapAllocator(max(n, bytesPerRegion)); | |
| } | |
| } | |
| import std.experimental.allocator.building_blocks.allocator_list | |
| : AllocatorList; | |
| import std.experimental.allocator.building_blocks.null_allocator | |
| : NullAllocator; | |
| auto shop = Factory(bytesPerRegion); | |
| return AllocatorList!(Factory, NullAllocator)(shop); | |
| } | |
| /// | |
| @system unittest | |
| { | |
| auto alloc = mmapRegionList(1024 * 1024); | |
| const b = alloc.allocate(100); | |
| assert(b.length == 100); | |
| } |