1// Written in the D programming language.
2/**
3
4High-level interface for allocators. Implements bundled allocation/creation
5and destruction/deallocation of data including `struct`s and `class`es,
6and also array primitives related to allocation. This module is the entry point
7for both making use of allocators and for their documentation.
8
9$(SCRIPT inhibitQuickIndex = 1;)
10$(BOOKTABLE,
11$(TR $(TH Category) $(TH Functions))
12$(TR $(TD Make) $(TD
13    $(LREF make)
14    $(LREF makeArray)
15    $(LREF makeMultidimensionalArray)
16))
17$(TR $(TD Dispose) $(TD
18    $(LREF dispose)
19    $(LREF disposeMultidimensionalArray)
20))
21$(TR $(TD Modify) $(TD
22    $(LREF expandArray)
23    $(LREF shrinkArray)
24))
25$(TR $(TD Global) $(TD
26    $(LREF processAllocator)
27    $(LREF theAllocator)
28))
29$(TR $(TD Class interface) $(TD
30    $(LREF allocatorObject)
31    $(LREF CAllocatorImpl)
32    $(LREF IAllocator)
33))
34)
35
36Synopsis:
37---
38// Allocate an int, initialize it with 42
39int* p = theAllocator.make!int(42);
40assert(*p == 42);
41// Destroy and deallocate it
42theAllocator.dispose(p);
43
44// Allocate using the global process allocator
45p = processAllocator.make!int(100);
46assert(*p == 100);
47// Destroy and deallocate
48processAllocator.dispose(p);
49
50// Create an array of 50 doubles initialized to -1.0
51double[] arr = theAllocator.makeArray!double(50, -1.0);
52// Append two zeros to it
53theAllocator.expandArray(arr, 2, 0.0);
54// On second thought, take that back
55theAllocator.shrinkArray(arr, 2);
56// Destroy and deallocate
57theAllocator.dispose(arr);
58---
59
60$(H2 Layered Structure)
61
62D's allocators have a layered structure in both implementation and documentation:
63
64$(OL
65$(LI A high-level, dynamically-typed layer (described further down in this
66module). It consists of an interface called $(LREF IAllocator), which concrete
67allocators need to implement. The interface primitives themselves are oblivious
68to the type of the objects being allocated; they only deal in `void[]`, by
69necessity of the interface being dynamic (as opposed to type-parameterized).
70Each thread has a current allocator it uses by default, which is a thread-local
71variable $(LREF theAllocator) of type $(LREF IAllocator). The process has a
72global allocator called $(LREF processAllocator), also of type $(LREF
73IAllocator). When a new thread is created, $(LREF processAllocator) is copied
74into $(LREF theAllocator). An application can change the objects to which these
75references point. By default, at application startup, $(LREF processAllocator)
76refers to an object that uses D's garbage collected heap. This layer also
77include high-level functions such as $(LREF make) and $(LREF dispose) that
78comfortably allocate/create and respectively destroy/deallocate objects. This
79layer is all needed for most casual uses of allocation primitives.)
80
81$(LI A mid-level, statically-typed layer for assembling several allocators into
82one. It uses properties of the type of the objects being created to route
83allocation requests to possibly specialized allocators. This layer is relatively
84thin and implemented and documented in the $(MREF
85std,experimental,allocator,typed) module. It allows an interested user to e.g.
86use different allocators for arrays versus fixed-sized objects, to the end of
87better overall performance.)
88
89$(LI A low-level collection of highly generic $(I heap building blocks)$(MDASH)
90Lego-like pieces that can be used to assemble application-specific allocators.
91The real allocation smarts are occurring at this level. This layer is of
92interest to advanced applications that want to configure their own allocators.
93A good illustration of typical uses of these building blocks is module $(MREF
94std,experimental,allocator,showcase) which defines a collection of frequently-
95used preassembled allocator objects. The implementation and documentation entry
96point is $(MREF std,experimental,allocator,building_blocks). By design, the
97primitives of the static interface have the same signatures as the $(LREF
98IAllocator) primitives but are for the most part optional and driven by static
99introspection. The parameterized class $(LREF CAllocatorImpl) offers an
100immediate and useful means to package a static low-level allocator into an
101implementation of $(LREF IAllocator).)
102
103$(LI Core allocator objects that interface with D's garbage collected heap
104($(MREF std,experimental,allocator,gc_allocator)), the C `malloc` family
105($(MREF std,experimental,allocator,mallocator)), and the OS ($(MREF
106std,experimental,allocator,mmap_allocator)). Most custom allocators would
107ultimately obtain memory from one of these core allocators.)
108)
109
110$(H2 Idiomatic Use of `std.experimental.allocator`)
111
112As of this time, `std.experimental.allocator` is not integrated with D's
113built-in operators that allocate memory, such as `new`, array literals, or
114array concatenation operators. That means `std.experimental.allocator` is
115opt-in$(MDASH)applications need to make explicit use of it.
116
117For casual creation and disposal of dynamically-allocated objects, use $(LREF
118make), $(LREF dispose), and the array-specific functions $(LREF makeArray),
119$(LREF expandArray), and $(LREF shrinkArray). These use by default D's garbage
120collected heap, but open the application to better configuration options. These
121primitives work either with `theAllocator` but also with any allocator obtained
122by combining heap building blocks. For example:
123
124----
125void fun(size_t n)
126{
127    // Use the current allocator
128    int[] a1 = theAllocator.makeArray!int(n);
129    scope(exit) theAllocator.dispose(a1);
130    ...
131}
132----
133
134To experiment with alternative allocators, set $(LREF theAllocator) for the
135current thread. For example, consider an application that allocates many 8-byte
136objects. These are not well supported by the default allocator, so a
137$(MREF_ALTTEXT free list allocator,
138std,experimental,allocator,building_blocks,free_list) would be recommended.
139To install one in `main`, the application would use:
140
141----
142void main()
143{
144    import std.experimental.allocator.building_blocks.free_list
145        : FreeList;
146    theAllocator = allocatorObject(FreeList!8());
147    ...
148}
149----
150
151$(H3 Saving the `IAllocator` Reference For Later Use)
152
153As with any global resource, setting `theAllocator` and `processAllocator`
154should not be done often and casually. In particular, allocating memory with
155one allocator and deallocating with another causes undefined behavior.
156Typically, these variables are set during application initialization phase and
157last through the application.
158
159To avoid this, long-lived objects that need to perform allocations,
160reallocations, and deallocations relatively often may want to store a reference
161to the allocator object they use throughout their lifetime. Then, instead of
162using `theAllocator` for internal allocation-related tasks, they'd use the
163internally held reference. For example, consider a user-defined hash table:
164
165----
166struct HashTable
167{
168    private IAllocator allocator;
169    this(size_t buckets, IAllocator allocator = theAllocator) {
170        this.allocator = allocator;
171        ...
172    }
173    // Getter and setter
174    IAllocator allocator() { return allocator; }
175    void allocator(IAllocator a) { assert(empty); allocator = a; }
176}
177----
178
179Following initialization, the `HashTable` object would consistently use its
180`allocator` object for acquiring memory. Furthermore, setting
181`HashTable.allocator` to point to a different allocator should be legal but
182only if the object is empty; otherwise, the object wouldn't be able to
183deallocate its existing state.
184
185$(H3 Using Allocators without `IAllocator`)
186
187Allocators assembled from the heap building blocks don't need to go through
188`IAllocator` to be usable. They have the same primitives as `IAllocator` and
189they work with $(LREF make), $(LREF makeArray), $(LREF dispose) etc. So it
190suffice to create allocator objects wherever fit and use them appropriately:
191
192----
193void fun(size_t n)
194{
195    // Use a stack-installed allocator for up to 64KB
196    StackFront!65536 myAllocator;
197    int[] a2 = myAllocator.makeArray!int(n);
198    scope(exit) myAllocator.dispose(a2);
199    ...
200}
201----
202
203In this case, `myAllocator` does not obey the `IAllocator` interface, but
204implements its primitives so it can work with `makeArray` by means of duck
205typing.
206
207One important thing to note about this setup is that statically-typed assembled
208allocators are almost always faster than allocators that go through
209`IAllocator`. An important rule of thumb is: "assemble allocator first, adapt
210to `IAllocator` after". A good allocator implements intricate logic by means of
211template assembly, and gets wrapped with `IAllocator` (usually by means of
212$(LREF allocatorObject)) only once, at client level.
213
214Copyright: Andrei Alexandrescu 2013-.
215
216License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
217
218Authors: $(HTTP erdani.com, Andrei Alexandrescu)
219
220Source: $(PHOBOSSRC std/experimental/allocator)
221
222*/
223
224module std.experimental.allocator;
225
226public import std.experimental.allocator.common,
227    std.experimental.allocator.typed;
228
229// Fix https://issues.dlang.org/show_bug.cgi?id=17806
230// this should always be the first unittest in this module in order to ensure
231// that we use the `processAllocator` setter before the getter
232@system unittest
233{
234    import std.experimental.allocator.mallocator : Mallocator;
235    import std.experimental.allocator.gc_allocator : GCAllocator;
236    auto newAlloc = sharedAllocatorObject(Mallocator.instance);
237    processAllocator = newAlloc;
238    assert(processAllocator is newAlloc);
239    processAllocator = sharedAllocatorObject(GCAllocator.instance);
240}
241
242// Example in the synopsis above
243@system unittest
244{
245    import std.algorithm.comparison : min, max;
246    import std.experimental.allocator.building_blocks.allocator_list
247        : AllocatorList;
248    import std.experimental.allocator.building_blocks.bitmapped_block
249        : BitmappedBlock;
250    import std.experimental.allocator.building_blocks.bucketizer : Bucketizer;
251    import std.experimental.allocator.building_blocks.free_list : FreeList;
252    import std.experimental.allocator.building_blocks.segregator : Segregator;
253    import std.experimental.allocator.gc_allocator : GCAllocator;
254
255    alias FList = FreeList!(GCAllocator, 0, unbounded);
256    alias A = Segregator!(
257        8, FreeList!(GCAllocator, 0, 8),
258        128, Bucketizer!(FList, 1, 128, 16),
259        256, Bucketizer!(FList, 129, 256, 32),
260        512, Bucketizer!(FList, 257, 512, 64),
261        1024, Bucketizer!(FList, 513, 1024, 128),
262        2048, Bucketizer!(FList, 1025, 2048, 256),
263        3584, Bucketizer!(FList, 2049, 3584, 512),
264        4072 * 1024, AllocatorList!(
265            (n) => BitmappedBlock!(4096)(
266                    cast(ubyte[])(GCAllocator.instance.allocate(
267                        max(n, 4072 * 1024))))),
268        GCAllocator
269    );
270    A tuMalloc;
271    auto b = tuMalloc.allocate(500);
272    assert(b.length == 500);
273    auto c = tuMalloc.allocate(113);
274    assert(c.length == 113);
275    assert(tuMalloc.expand(c, 14));
276    tuMalloc.deallocate(b);
277    tuMalloc.deallocate(c);
278}
279
280import std.range.primitives;
281import std.traits;
282import std.typecons;
283
284/**
285Dynamic allocator interface. Code that defines allocators ultimately implements
286this interface. This should be used wherever a uniform type is required for
287encapsulating various allocator implementations.
288
289Composition of allocators is not recommended at this level due to
290inflexibility of dynamic interfaces and inefficiencies caused by cascaded
291multiple calls. Instead, compose allocators using the static interface defined
292in $(MREF std,experimental,allocator,building_blocks),
293then adapt the composed
294allocator to `IAllocator` (possibly by using $(LREF CAllocatorImpl) below).
295
296Methods returning `Ternary` return `Ternary.yes` upon success,
297`Ternary.no` upon failure, and `Ternary.unknown` if the primitive is not
298implemented by the allocator instance.
299*/
300interface IAllocator
301{
302nothrow:
303    /**
304    Returns the alignment offered.
305    */
306    @property uint alignment();
307
308    /**
309    Returns the good allocation size that guarantees zero internal
310    fragmentation.
311    */
312    size_t goodAllocSize(size_t s);
313
314    /**
315    Allocates `n` bytes of memory.
316    */
317    void[] allocate(size_t, TypeInfo ti = null);
318
319    /**
320    Allocates `n` bytes of memory with specified alignment `a`. Implementations
321    that do not support this primitive should always return `null`.
322    */
323    void[] alignedAllocate(size_t n, uint a);
324
325    /**
326    Allocates and returns all memory available to this allocator.
327    Implementations that do not support this primitive should always return
328    `null`.
329    */
330    void[] allocateAll();
331
332    /**
333    Expands a memory block in place and returns `true` if successful.
334    Implementations that don't support this primitive should always return
335    `false`.
336    */
337    bool expand(ref void[], size_t);
338
339    /// Reallocates a memory block.
340    bool reallocate(ref void[], size_t);
341
342    /// Reallocates a memory block with specified alignment.
343    bool alignedReallocate(ref void[] b, size_t size, uint alignment);
344
345    /**
346    Returns `Ternary.yes` if the allocator owns `b`, `Ternary.no` if
347    the allocator doesn't own `b`, and `Ternary.unknown` if ownership
348    cannot be determined. Implementations that don't support this primitive
349    should always return `Ternary.unknown`.
350    */
351    Ternary owns(void[] b);
352
353    /**
354    Resolves an internal pointer to the full block allocated. Implementations
355    that don't support this primitive should always return `Ternary.unknown`.
356    */
357    Ternary resolveInternalPointer(const void* p, ref void[] result);
358
359    /**
360    Deallocates a memory block. Implementations that don't support this
361    primitive should always return `false`. A simple way to check that an
362    allocator supports deallocation is to call `deallocate(null)`.
363    */
364    bool deallocate(void[] b);
365
366    /**
367    Deallocates all memory. Implementations that don't support this primitive
368    should always return `false`.
369    */
370    bool deallocateAll();
371
372    /**
373    Returns `Ternary.yes` if no memory is currently allocated from this
374    allocator, `Ternary.no` if some allocations are currently active, or
375    `Ternary.unknown` if not supported.
376    */
377    Ternary empty();
378
379    /**
380    Increases the reference count of the concrete class that implements this
381    interface.
382
383    For stateless allocators, this does nothing.
384    */
385    @safe @nogc pure
386    void incRef();
387
388    /**
389    Decreases the reference count of the concrete class that implements this
390    interface.
391    When the reference count is `0`, the object self-destructs.
392
393    Returns: `true` if the reference count is greater than `0` and `false` when
394    it hits `0`. For stateless allocators, it always returns `true`.
395    */
396    @safe @nogc pure
397    bool decRef();
398}
399
400/**
401A reference counted struct that wraps the dynamic allocator interface.
402This should be used wherever a uniform type is required for encapsulating
403various allocator implementations.
404
405Code that defines allocators ultimately implements the $(LREF IAllocator)
406interface, possibly by using $(LREF CAllocatorImpl) below, and then build a
407`RCIAllocator` out of this.
408
409Composition of allocators is not recommended at this level due to
410inflexibility of dynamic interfaces and inefficiencies caused by cascaded
411multiple calls. Instead, compose allocators using the static interface defined
412in $(A std_experimental_allocator_building_blocks.html,
413`std.experimental.allocator.building_blocks`), then adapt the composed
414allocator to `RCIAllocator` (possibly by using $(LREF allocatorObject) below).
415*/
416struct RCIAllocator
417{
418    private IAllocator _alloc;
419
420nothrow:
421    private @nogc pure @safe
422    this(this _)(IAllocator alloc)
423    {
424        assert(alloc);
425        _alloc = alloc;
426    }
427
428    @nogc pure @safe
429    this(this)
430    {
431        if (_alloc !is null)
432        {
433            _alloc.incRef();
434        }
435    }
436
437    @nogc pure @safe
438    ~this()
439    {
440        if (_alloc !is null)
441        {
442            bool isLast = !_alloc.decRef();
443            if (isLast) _alloc = null;
444        }
445    }
446
447    @nogc pure @safe
448    auto ref opAssign()(typeof(this) rhs)
449    {
450        if (_alloc is rhs._alloc)
451        {
452            return this;
453        }
454        // incRef was allready called by rhs posblit, so we're just moving
455        // calling dtor is the equivalent of decRef
456        __dtor();
457        _alloc = rhs._alloc;
458        // move
459        rhs._alloc = null;
460        return this;
461    }
462
463    @nogc pure @safe
464    bool isNull(this _)()
465    {
466        return _alloc is null;
467    }
468
469    @property uint alignment()
470    {
471        assert(_alloc);
472        return _alloc.alignment();
473    }
474
475    size_t goodAllocSize(size_t s)
476    {
477        assert(_alloc);
478        return _alloc.goodAllocSize(s);
479    }
480
481    void[] allocate(size_t n, TypeInfo ti = null)
482    {
483        assert(_alloc);
484        return _alloc.allocate(n, ti);
485    }
486
487    void[] alignedAllocate(size_t n, uint a)
488    {
489        assert(_alloc);
490        return _alloc.alignedAllocate(n, a);
491    }
492
493    void[] allocateAll()
494    {
495        assert(_alloc);
496        return _alloc.allocateAll();
497    }
498
499    bool expand(ref void[] b, size_t size)
500    {
501        assert(_alloc);
502        return _alloc.expand(b, size);
503    }
504
505    bool reallocate(ref void[] b, size_t size)
506    {
507        assert(_alloc);
508        return _alloc.reallocate(b, size);
509    }
510
511    bool alignedReallocate(ref void[] b, size_t size, uint alignment)
512    {
513        assert(_alloc);
514        return _alloc.alignedReallocate(b, size, alignment);
515    }
516
517    Ternary owns(void[] b)
518    {
519        assert(_alloc);
520        return _alloc.owns(b);
521    }
522
523    Ternary resolveInternalPointer(const void* p, ref void[] result)
524    {
525        assert(_alloc);
526        return _alloc.resolveInternalPointer(p, result);
527    }
528
529    bool deallocate(void[] b)
530    {
531        assert(_alloc);
532        return _alloc.deallocate(b);
533    }
534
535    bool deallocateAll()
536    {
537        assert(_alloc);
538        return _alloc.deallocateAll();
539    }
540
541    Ternary empty()
542    {
543        assert(_alloc);
544        return _alloc.empty();
545    }
546}
547
548@system unittest
549{
550    import std.experimental.allocator.building_blocks.region : Region;
551    import std.conv : emplace;
552
553    auto reg = Region!()(new ubyte[1024]);
554    auto state = reg.allocate(stateSize!(CAllocatorImpl!(Region!(), Yes.indirect)));
555    auto regObj = emplace!(CAllocatorImpl!(Region!(), Yes.indirect))(state, &reg);
556
557    auto rcalloc = RCIAllocator(regObj);
558    auto b = rcalloc.allocate(10);
559    assert(b.length == 10);
560
561    // The reference counting is zero based
562    assert((cast(CAllocatorImpl!(Region!(), Yes.indirect))(rcalloc._alloc)).rc == 1);
563    {
564        auto rca2 = rcalloc;
565        assert((cast(CAllocatorImpl!(Region!(), Yes.indirect))(rcalloc._alloc)).rc == 2);
566    }
567    assert((cast(CAllocatorImpl!(Region!(), Yes.indirect))(rcalloc._alloc)).rc == 1);
568}
569
570@system unittest
571{
572    import std.conv;
573    import std.experimental.allocator.mallocator;
574    import std.experimental.allocator.building_blocks.stats_collector;
575
576    alias SCAlloc = StatsCollector!(Mallocator, Options.bytesUsed);
577    SCAlloc statsCollectorAlloc;
578
579    ulong bytesUsed = statsCollectorAlloc.bytesUsed;
580    assert(bytesUsed == 0);
581
582    {
583        auto _allocator = allocatorObject(&statsCollectorAlloc);
584        bytesUsed = statsCollectorAlloc.bytesUsed;
585        assert(bytesUsed == stateSize!(CAllocatorImpl!(SCAlloc, Yes.indirect)));
586    }
587
588    bytesUsed = statsCollectorAlloc.bytesUsed;
589    assert(bytesUsed == 0, "RCIAllocator leaks memory; leaked "
590            ~ to!string(bytesUsed) ~ " bytes");
591}
592
593@system unittest
594{
595    import std.conv;
596    import std.experimental.allocator.mallocator;
597    import std.experimental.allocator.building_blocks.stats_collector;
598
599    alias SCAlloc = StatsCollector!(Mallocator, Options.bytesUsed);
600    SCAlloc statsCollectorAlloc;
601
602    ulong bytesUsed = statsCollectorAlloc.bytesUsed;
603    assert(bytesUsed == 0);
604
605    {
606        auto _allocator = allocatorObject(statsCollectorAlloc);
607
608        // Ensure that the allocator was passed through in CAllocatorImpl
609        // This allocator was used to allocate the chunk that holds the
610        // CAllocatorImpl object; which is it's own wrapper
611        bytesUsed = (cast(CAllocatorImpl!(SCAlloc))(_allocator._alloc)).impl.bytesUsed;
612        assert(bytesUsed == stateSize!(CAllocatorImpl!(SCAlloc)),
613               "RCIAllocator leaks memory; leaked " ~ to!string(bytesUsed) ~ " bytes");
614        _allocator.allocate(1);
615        bytesUsed = (cast(CAllocatorImpl!(SCAlloc))(_allocator._alloc)).impl.bytesUsed;
616        assert(bytesUsed == stateSize!(CAllocatorImpl!(SCAlloc)) + 1,
617               "RCIAllocator leaks memory; leaked " ~ to!string(bytesUsed) ~ " bytes");
618    }
619
620    bytesUsed = statsCollectorAlloc.bytesUsed;
621    assert(bytesUsed == stateSize!(CAllocatorImpl!(SCAlloc)),
622            "RCIAllocator leaks memory; leaked "
623            ~ to!string(bytesUsed) ~ " bytes");
624}
625
626/**
627Dynamic shared allocator interface. Code that defines allocators shareable
628across threads ultimately implements this interface. This should be used
629wherever a uniform type is required for encapsulating various allocator
630implementations.
631
632Composition of allocators is not recommended at this level due to
633inflexibility of dynamic interfaces and inefficiencies caused by cascaded
634multiple calls. Instead, compose allocators using the static interface defined
635in $(MREF std,experimental,allocator,building_blocks),
636then adapt the composed
637allocator to `ISharedAllocator` (possibly by using $(LREF CSharedAllocatorImpl) below).
638
639Methods returning `Ternary` return `Ternary.yes` upon success,
640`Ternary.no` upon failure, and `Ternary.unknown` if the primitive is not
641implemented by the allocator instance.
642*/
643interface ISharedAllocator
644{
645nothrow:
646    /**
647    Returns the alignment offered.
648    */
649    @property uint alignment() shared;
650
651    /**
652    Returns the good allocation size that guarantees zero internal
653    fragmentation.
654    */
655    size_t goodAllocSize(size_t s) shared;
656
657    /**
658    Allocates `n` bytes of memory.
659    */
660    void[] allocate(size_t, TypeInfo ti = null) shared;
661
662    /**
663    Allocates `n` bytes of memory with specified alignment `a`. Implementations
664    that do not support this primitive should always return `null`.
665    */
666    void[] alignedAllocate(size_t n, uint a) shared;
667
668    /**
669    Allocates and returns all memory available to this allocator.
670    Implementations that do not support this primitive should always return
671    `null`.
672    */
673    void[] allocateAll() shared;
674
675    /**
676    Expands a memory block in place and returns `true` if successful.
677    Implementations that don't support this primitive should always return
678    `false`.
679    */
680    bool expand(ref void[], size_t) shared;
681
682    /// Reallocates a memory block.
683    bool reallocate(ref void[], size_t) shared;
684
685    /// Reallocates a memory block with specified alignment.
686    bool alignedReallocate(ref void[] b, size_t size, uint alignment) shared;
687
688    /**
689    Returns `Ternary.yes` if the allocator owns `b`, `Ternary.no` if
690    the allocator doesn't own `b`, and `Ternary.unknown` if ownership
691    cannot be determined. Implementations that don't support this primitive
692    should always return `Ternary.unknown`.
693    */
694    Ternary owns(void[] b) shared;
695
696    /**
697    Resolves an internal pointer to the full block allocated. Implementations
698    that don't support this primitive should always return `Ternary.unknown`.
699    */
700    Ternary resolveInternalPointer(const void* p, ref void[] result) shared;
701
702    /**
703    Deallocates a memory block. Implementations that don't support this
704    primitive should always return `false`. A simple way to check that an
705    allocator supports deallocation is to call `deallocate(null)`.
706    */
707    bool deallocate(void[] b) shared;
708
709    /**
710    Deallocates all memory. Implementations that don't support this primitive
711    should always return `false`.
712    */
713    bool deallocateAll() shared;
714
715    /**
716    Returns `Ternary.yes` if no memory is currently allocated from this
717    allocator, `Ternary.no` if some allocations are currently active, or
718    `Ternary.unknown` if not supported.
719    */
720    Ternary empty() shared;
721
722    /**
723    Increases the reference count of the concrete class that implements this
724    interface.
725
726    For stateless allocators, this does nothing.
727    */
728    @safe @nogc pure
729    void incRef() shared;
730
731    /**
732    Decreases the reference count of the concrete class that implements this
733    interface.
734    When the reference count is `0`, the object self-destructs.
735
736    For stateless allocators, this does nothing.
737
738    Returns: `true` if the reference count is greater than `0` and `false` when
739    it hits `0`. For stateless allocators, it always returns `true`.
740    */
741    @safe @nogc pure
742    bool decRef() shared;
743}
744
745/**
746A reference counted struct that wraps the dynamic shared allocator interface.
747This should be used wherever a uniform type is required for encapsulating
748various allocator implementations.
749
750Code that defines allocators shareable across threads ultimately implements the
751$(LREF ISharedAllocator) interface, possibly by using
752$(LREF CSharedAllocatorImpl) below, and then build a `RCISharedAllocator` out
753of this.
754
755Composition of allocators is not recommended at this level due to
756inflexibility of dynamic interfaces and inefficiencies caused by cascaded
757multiple calls. Instead, compose allocators using the static interface defined
758in $(A std_experimental_allocator_building_blocks.html,
759`std.experimental.allocator.building_blocks`), then adapt the composed allocator
760to `RCISharedAllocator` (possibly by using $(LREF sharedAllocatorObject) below).
761*/
762shared struct RCISharedAllocator
763{
764    private ISharedAllocator _alloc;
765
766nothrow:
767    private @nogc pure @safe
768    this(shared ISharedAllocator alloc)
769    {
770        assert(alloc);
771        _alloc = alloc;
772    }
773
774    @nogc pure @safe
775    this(this)
776    {
777        if (_alloc !is null)
778        {
779            _alloc.incRef();
780        }
781    }
782
783    @nogc pure @safe
784    ~this()
785    {
786        if (_alloc !is null)
787        {
788            bool isLast = !_alloc.decRef();
789            if (isLast) _alloc = null;
790        }
791    }
792
793    @nogc pure @safe
794    auto ref opAssign()(RCISharedAllocator rhs)
795    {
796        if (_alloc is rhs._alloc)
797        {
798            return this;
799        }
800        // incRef was allready called by rhs posblit, so we're just moving
801        if (_alloc !is null)
802        {
803            _alloc.decRef();
804        }
805        _alloc = rhs._alloc;
806        // move
807        rhs._alloc = null;
808        return this;
809    }
810
811    @nogc pure @safe
812    bool isNull(this _)()
813    {
814        return _alloc is null;
815    }
816
817    @property uint alignment()
818    {
819        assert(_alloc);
820        return _alloc.alignment();
821    }
822
823    size_t goodAllocSize(size_t s)
824    {
825        assert(_alloc);
826        return _alloc.goodAllocSize(s);
827    }
828
829    void[] allocate(size_t n, TypeInfo ti = null)
830    {
831        assert(_alloc);
832        return _alloc.allocate(n, ti);
833    }
834
835    void[] alignedAllocate(size_t n, uint a)
836    {
837        assert(_alloc);
838        return _alloc.alignedAllocate(n, a);
839    }
840
841    void[] allocateAll()
842    {
843        assert(_alloc);
844        return _alloc.allocateAll();
845    }
846
847    bool expand(ref void[] b, size_t size)
848    {
849        assert(_alloc);
850        return _alloc.expand(b, size);
851    }
852
853    bool reallocate(ref void[] b, size_t size)
854    {
855        assert(_alloc);
856        return _alloc.reallocate(b, size);
857    }
858
859    bool alignedReallocate(ref void[] b, size_t size, uint alignment)
860    {
861        assert(_alloc);
862        return _alloc.alignedReallocate(b, size, alignment);
863    }
864
865    Ternary owns(void[] b)
866    {
867        assert(_alloc);
868        return _alloc.owns(b);
869    }
870
871    Ternary resolveInternalPointer(const void* p, ref void[] result)
872    {
873        assert(_alloc);
874        return _alloc.resolveInternalPointer(p, result);
875    }
876
877    bool deallocate(void[] b)
878    {
879        assert(_alloc);
880        return _alloc.deallocate(b);
881    }
882
883    bool deallocateAll()
884    {
885        assert(_alloc);
886        return _alloc.deallocateAll();
887    }
888
889    Ternary empty()
890    {
891        assert(_alloc);
892        return _alloc.empty();
893    }
894}
895
896private RCISharedAllocator _processAllocator;
897private RCIAllocator _threadAllocator;
898
899@nogc nothrow @safe
900private ref RCIAllocator setupThreadAllocator()
901{
902    /*
903    Forwards the `_threadAllocator` calls to the `processAllocator`
904    */
905    static class ThreadAllocator : IAllocator
906    {
907    nothrow:
908        private RCISharedAllocator _allocator;
909
910        @nogc @safe
911        this(ref RCISharedAllocator procAlloc)
912        {
913            _allocator = procAlloc;
914        }
915
916        override @property uint alignment()
917        {
918            return _allocator.alignment();
919        }
920
921        override size_t goodAllocSize(size_t s)
922        {
923            return _allocator.goodAllocSize(s);
924        }
925
926        override void[] allocate(size_t n, TypeInfo ti = null)
927        {
928            return _allocator.allocate(n, ti);
929        }
930
931        override void[] alignedAllocate(size_t n, uint a)
932        {
933            return _allocator.alignedAllocate(n, a);
934        }
935
936        override void[] allocateAll()
937        {
938            return _allocator.allocateAll();
939        }
940
941        override bool expand(ref void[] b, size_t size)
942        {
943            return _allocator.expand(b, size);
944        }
945
946        override bool reallocate(ref void[] b, size_t size)
947        {
948            return _allocator.reallocate(b, size);
949        }
950
951        override bool alignedReallocate(ref void[] b, size_t size, uint alignment)
952        {
953            return _allocator.alignedReallocate(b, size, alignment);
954        }
955
956        override Ternary owns(void[] b)
957        {
958            return _allocator.owns(b);
959        }
960
961        override Ternary resolveInternalPointer(const void* p, ref void[] result)
962        {
963            return _allocator.resolveInternalPointer(p, result);
964        }
965
966        override bool deallocate(void[] b)
967        {
968            return _allocator.deallocate(b);
969        }
970
971        override bool deallocateAll()
972        {
973            return _allocator.deallocateAll();
974        }
975
976        override Ternary empty()
977        {
978            return _allocator.empty();
979        }
980
981        @nogc pure @safe
982        override void incRef()
983        {
984            _allocator._alloc.incRef();
985        }
986
987        @nogc pure @safe
988        override bool decRef()
989        {
990            return _allocator._alloc.decRef();
991        }
992    }
993
994    assert(_threadAllocator.isNull);
995    import core.lifetime : emplace;
996    static ulong[stateSize!(ThreadAllocator).divideRoundUp(ulong.sizeof)] _threadAllocatorState;
997    () @trusted {
998        _threadAllocator = RCIAllocator(emplace!(ThreadAllocator)(_threadAllocatorState[], processAllocator()));
999    }();
1000    return _threadAllocator;
1001}
1002
1003// Fix threadAllocator bug: the threadAllocator should hold an internal reference
1004// to the processAllocator that it's using
1005@system unittest
1006{
1007    import std.experimental.allocator.mallocator : Mallocator;
1008
1009    auto a = sharedAllocatorObject(Mallocator.instance);
1010    auto buf = theAllocator.allocate(42);
1011    processAllocator = a;
1012    theAllocator.deallocate(buf);
1013}
1014
1015/**
1016Gets/sets the allocator for the current thread. This is the default allocator
1017that should be used for allocating thread-local memory. For allocating memory
1018to be shared across threads, use `processAllocator` (below). By default,
1019`theAllocator` ultimately fetches memory from `processAllocator`, which
1020in turn uses the garbage collected heap.
1021*/
1022@nogc nothrow @safe
1023@property ref RCIAllocator theAllocator()
1024{
1025    alias p = _threadAllocator;
1026    return !p.isNull() ? p : setupThreadAllocator();
1027}
1028
1029/// Ditto
1030nothrow @system @nogc
1031@property void theAllocator(RCIAllocator a)
1032{
1033    assert(!a.isNull);
1034    _threadAllocator = a;
1035}
1036
1037///
1038@system unittest
1039{
1040    // Install a new allocator that is faster for 128-byte allocations.
1041    import std.experimental.allocator.building_blocks.free_list : FreeList;
1042    import std.experimental.allocator.gc_allocator : GCAllocator;
1043    auto oldAllocator = theAllocator;
1044    scope(exit) theAllocator = oldAllocator;
1045    theAllocator = allocatorObject(FreeList!(GCAllocator, 128)());
1046    // Use the now changed allocator to allocate an array
1047    const ubyte[] arr = theAllocator.makeArray!ubyte(128);
1048    assert(arr.ptr);
1049    //...
1050}
1051
1052/**
1053Gets/sets the allocator for the current process. This allocator must be used
1054for allocating memory shared across threads. Objects created using this
1055allocator can be cast to `shared`.
1056*/
1057@nogc nothrow @trusted
1058@property ref RCISharedAllocator processAllocator()
1059{
1060    import std.experimental.allocator.gc_allocator : GCAllocator;
1061    import std.concurrency : initOnce;
1062
1063    static RCISharedAllocator* forceAttributes()
1064    {
1065        return &initOnce!_processAllocator(
1066                sharedAllocatorObject(GCAllocator.instance));
1067    }
1068
1069    return *(cast(RCISharedAllocator* function() @nogc nothrow)(&forceAttributes))();
1070}
1071
1072/// Ditto
1073@nogc nothrow @system
1074@property void processAllocator(ref RCISharedAllocator a)
1075{
1076    assert(!a.isNull);
1077    processAllocator() = a;
1078}
1079
1080@system unittest
1081{
1082    import core.exception : AssertError;
1083    import std.exception : assertThrown;
1084    import std.experimental.allocator.building_blocks.free_list : SharedFreeList;
1085    import std.experimental.allocator.mallocator : Mallocator;
1086
1087    assert(!processAllocator.isNull);
1088    assert(!theAllocator.isNull);
1089
1090    testAllocatorObject(processAllocator);
1091    testAllocatorObject(theAllocator);
1092
1093    shared SharedFreeList!(Mallocator, chooseAtRuntime, chooseAtRuntime) sharedFL;
1094    RCISharedAllocator sharedFLObj = sharedAllocatorObject(sharedFL);
1095    alias SharedAllocT = CSharedAllocatorImpl!(
1096            shared SharedFreeList!(
1097                Mallocator, chooseAtRuntime, chooseAtRuntime));
1098
1099    assert((cast(SharedAllocT)(sharedFLObj._alloc)).rc == 1);
1100    assert(!sharedFLObj.isNull);
1101    testAllocatorObject(sharedFLObj);
1102
1103    // Test processAllocator setter
1104    RCISharedAllocator oldProcessAllocator = processAllocator;
1105    processAllocator = sharedFLObj;
1106    assert((cast(SharedAllocT)(sharedFLObj._alloc)).rc == 2);
1107    assert(processAllocator._alloc is sharedFLObj._alloc);
1108
1109    testAllocatorObject(processAllocator);
1110    testAllocatorObject(theAllocator);
1111    assertThrown!AssertError(processAllocator = RCISharedAllocator(null));
1112
1113    // Restore initial processAllocator state
1114    processAllocator = oldProcessAllocator;
1115    assert((cast(SharedAllocT)(sharedFLObj._alloc)).rc == 1);
1116    assert(processAllocator is oldProcessAllocator);
1117
1118    RCISharedAllocator indirectShFLObj = sharedAllocatorObject(&sharedFL);
1119    testAllocatorObject(indirectShFLObj);
1120    alias IndirectSharedAllocT = CSharedAllocatorImpl!(
1121            shared SharedFreeList!(
1122                Mallocator, chooseAtRuntime, chooseAtRuntime)
1123            , Yes.indirect);
1124
1125    assert((cast(IndirectSharedAllocT)(indirectShFLObj._alloc)).rc == 1);
1126
1127    RCIAllocator indirectMallocator = allocatorObject(&Mallocator.instance);
1128    testAllocatorObject(indirectMallocator);
1129}
1130
1131/**
1132Dynamically allocates (using `alloc`) and then creates in the memory
1133allocated an object of type `T`, using `args` (if any) for its
1134initialization. Initialization occurs in the memory allocated and is otherwise
1135semantically the same as `T(args)`.
1136(Note that using `alloc.make!(T[])` creates a pointer to an (empty) array
1137of `T`s, not an array. To use an allocator to allocate and initialize an
1138array, use `alloc.makeArray!T` described below.)
1139
1140Params:
1141T = Type of the object being created.
1142alloc = The allocator used for getting the needed memory. It may be an object
1143implementing the static interface for allocators, or an `IAllocator`
1144reference.
1145args = Optional arguments used for initializing the created object. If not
1146present, the object is default constructed.
1147
1148Returns: If `T` is a class type, returns a reference to the created `T`
1149object. Otherwise, returns a `T*` pointing to the created object. In all
1150cases, returns `null` if allocation failed.
1151
1152Throws: If `T`'s constructor throws, deallocates the allocated memory and
1153propagates the exception.
1154*/
1155auto make(T, Allocator, A...)(auto ref Allocator alloc, auto ref A args)
1156{
1157    import std.algorithm.comparison : max;
1158    static if (!is(T == class) && !is(T == interface) && A.length == 0
1159        && __traits(compiles, {T t;}) && __traits(isZeroInit, T)
1160        && is(typeof(alloc.allocateZeroed(size_t.max))))
1161    {
1162        auto m = alloc.allocateZeroed(max(T.sizeof, 1));
1163        return (() @trusted => cast(T*) m.ptr)();
1164    }
1165    else
1166    {
1167        import core.internal.lifetime : emplaceRef;
1168        import core.lifetime : emplace;
1169
1170        auto m = alloc.allocate(max(stateSize!T, 1));
1171        if (!m.ptr) return null;
1172
1173        // make can only be @safe if emplace or emplaceRef is `pure`
1174        auto construct()
1175        {
1176            static if (is(T == class)) return emplace!T(m, args);
1177            else
1178            {
1179                // Assume cast is safe as allocation succeeded for `stateSize!T`
1180                auto p = () @trusted { return cast(T*) m.ptr; }();
1181                emplaceRef!T(*p, args);
1182                return p;
1183            }
1184        }
1185
1186        scope(failure)
1187        {
1188            static if (is(typeof(() pure { return construct(); })))
1189            {
1190                // Assume deallocation is safe because:
1191                // 1) in case of failure, `m` is the only reference to this memory
1192                // 2) `m` is known to originate from `alloc`
1193                () @trusted { alloc.deallocate(m); }();
1194            }
1195            else
1196            {
1197                alloc.deallocate(m);
1198            }
1199        }
1200
1201        return construct();
1202    }
1203}
1204
1205///
1206@system unittest
1207{
1208    // Dynamically allocate one integer
1209    const int* p1 = theAllocator.make!int;
1210    // It's implicitly initialized with its .init value
1211    assert(*p1 == 0);
1212    // Dynamically allocate one double, initialize to 42.5
1213    const double* p2 = theAllocator.make!double(42.5);
1214    assert(*p2 == 42.5);
1215
1216    // Dynamically allocate a struct
1217    static struct Point
1218    {
1219        int x, y, z;
1220    }
1221    // Use the generated constructor taking field values in order
1222    const Point* p = theAllocator.make!Point(1, 2);
1223    assert(p.x == 1 && p.y == 2 && p.z == 0);
1224
1225    // Dynamically allocate a class object
1226    static class Customer
1227    {
1228        uint id = uint.max;
1229        this() {}
1230        this(uint id) { this.id = id; }
1231        // ...
1232    }
1233    Customer cust = theAllocator.make!Customer;
1234    assert(cust.id == uint.max); // default initialized
1235    cust = theAllocator.make!Customer(42);
1236    assert(cust.id == 42);
1237
1238    // explicit passing of outer pointer
1239    static class Outer
1240    {
1241        int x = 3;
1242        class Inner
1243        {
1244            auto getX() { return x; }
1245        }
1246    }
1247    auto outer = theAllocator.make!Outer();
1248    auto inner = theAllocator.make!(Outer.Inner)(outer);
1249    assert(outer.x == inner.getX);
1250}
1251
1252// https://issues.dlang.org/show_bug.cgi?id=15639
1253// https://issues.dlang.org/show_bug.cgi?id=15772
1254@system unittest
1255{
1256    abstract class Foo {}
1257    class Bar: Foo {}
1258    static assert(!is(typeof(theAllocator.make!Foo)));
1259    static assert( is(typeof(theAllocator.make!Bar)));
1260}
1261
1262@system unittest
1263{
1264    void test(Allocator)(auto ref Allocator alloc)
1265    {
1266        const int* a = alloc.make!int(10);
1267        assert(*a == 10);
1268
1269        struct A
1270        {
1271            int x;
1272            string y;
1273            double z;
1274        }
1275
1276        A* b = alloc.make!A(42);
1277        assert(b.x == 42);
1278        assert(b.y is null);
1279        import std.math.traits : isNaN;
1280        assert(b.z.isNaN);
1281
1282        b = alloc.make!A(43, "44", 45);
1283        assert(b.x == 43);
1284        assert(b.y == "44");
1285        assert(b.z == 45);
1286
1287        static class B
1288        {
1289            int x;
1290            string y;
1291            double z;
1292            this(int _x, string _y = null, double _z = double.init)
1293            {
1294                x = _x;
1295                y = _y;
1296                z = _z;
1297            }
1298        }
1299
1300        B c = alloc.make!B(42);
1301        assert(c.x == 42);
1302        assert(c.y is null);
1303        assert(c.z.isNaN);
1304
1305        c = alloc.make!B(43, "44", 45);
1306        assert(c.x == 43);
1307        assert(c.y == "44");
1308        assert(c.z == 45);
1309
1310        const parray = alloc.make!(int[]);
1311        assert((*parray).empty);
1312    }
1313
1314    import std.experimental.allocator.gc_allocator : GCAllocator;
1315    test(GCAllocator.instance);
1316    test(theAllocator);
1317}
1318
1319// Attribute propagation
1320nothrow @safe @nogc unittest
1321{
1322    import std.experimental.allocator.mallocator : Mallocator;
1323    alias alloc = Mallocator.instance;
1324
1325    void test(T, Args...)(auto ref Args args)
1326    {
1327        auto k = alloc.make!T(args);
1328        () @trusted { alloc.dispose(k); }();
1329    }
1330
1331    test!int;
1332    test!(int*);
1333    test!int(0);
1334    test!(int*)(null);
1335}
1336
1337// should be pure with the GCAllocator
1338/*pure nothrow*/ @safe unittest
1339{
1340    import std.experimental.allocator.gc_allocator : GCAllocator;
1341
1342    alias alloc = GCAllocator.instance;
1343
1344    void test(T, Args...)(auto ref Args args)
1345    {
1346        auto k = alloc.make!T(args);
1347        (a) @trusted { a.dispose(k); }(alloc);
1348    }
1349
1350    test!int();
1351    test!(int*);
1352    test!int(0);
1353    test!(int*)(null);
1354}
1355
1356// Verify that making an object by calling an impure constructor is not @safe
1357nothrow @safe @nogc unittest
1358{
1359    import std.experimental.allocator.mallocator : Mallocator;
1360    static struct Pure { this(int) pure nothrow @nogc @safe {} }
1361
1362    cast(void) Mallocator.instance.make!Pure(0);
1363
1364    static int g = 0;
1365    static struct Impure { this(int) nothrow @nogc @safe {
1366        g++;
1367    } }
1368    static assert(!__traits(compiles, cast(void) Mallocator.instance.make!Impure(0)));
1369}
1370
1371// test failure with a pure, failing struct
1372@safe unittest
1373{
1374    import std.exception : assertThrown, enforce;
1375
1376    // this struct can't be initialized
1377    struct InvalidStruct
1378    {
1379        this(int b)
1380        {
1381            enforce(1 == 2);
1382        }
1383    }
1384    import std.experimental.allocator.mallocator : Mallocator;
1385    assertThrown(make!InvalidStruct(Mallocator.instance, 42));
1386}
1387
1388// test failure with an impure, failing struct
1389@system unittest
1390{
1391    import std.exception : assertThrown, enforce;
1392    static int g;
1393    struct InvalidImpureStruct
1394    {
1395        this(int b)
1396        {
1397            g++;
1398            enforce(1 == 2);
1399        }
1400    }
1401    import std.experimental.allocator.mallocator : Mallocator;
1402    assertThrown(make!InvalidImpureStruct(Mallocator.instance, 42));
1403}
1404
1405// Don't allow zero-ctor-args `make` for structs with `@disable this();`
1406@system unittest
1407{
1408    struct NoDefaultCtor
1409    {
1410        int i;
1411        @disable this();
1412    }
1413    import std.experimental.allocator.mallocator : Mallocator;
1414    static assert(!__traits(compiles, make!NoDefaultCtor(Mallocator.instance)),
1415        "Don't allow zero-ctor-args `make` for structs with `@disable this();`");
1416}
1417
1418// https://issues.dlang.org/show_bug.cgi?id=18937
1419@safe unittest
1420{
1421    static struct S
1422    {
1423        ubyte[16 * 1024] data;
1424    }
1425
1426    static struct SomeAllocator
1427    {
1428        ubyte[] allocate(size_t) { return []; }
1429        void deallocate(void[]) {}
1430    }
1431
1432    auto x = SomeAllocator().make!S();
1433}
1434
1435private void fillWithMemcpy(T)(scope void[] array, auto ref T filler) nothrow
1436if (T.sizeof == 1)
1437{
1438    import core.stdc.string : memset;
1439    import std.traits : CopyConstness;
1440    if (!array.length) return;
1441    memset(array.ptr, *cast(CopyConstness!(T*, ubyte*)) &filler, array.length);
1442}
1443
1444private void fillWithMemcpy(T)(scope void[] array, auto ref T filler) nothrow
1445if (T.sizeof != 1)
1446{
1447    import core.stdc.string : memcpy;
1448    import std.algorithm.comparison : min;
1449    if (!array.length) return;
1450    memcpy(array.ptr, &filler, T.sizeof);
1451    // Fill the array from the initialized portion of itself exponentially.
1452    for (size_t offset = T.sizeof; offset < array.length; )
1453    {
1454        size_t extent = min(offset, array.length - offset);
1455        memcpy(array.ptr + offset, array.ptr, extent);
1456        offset += extent;
1457    }
1458}
1459
1460@system unittest
1461{
1462    // Test T.sizeof == 1 path of fillWithMemcpy.
1463    ubyte[] a;
1464    fillWithMemcpy(a, ubyte(42));
1465    assert(a.length == 0);
1466    a = [ 1, 2, 3, 4, 5 ];
1467    fillWithMemcpy(a, ubyte(42));
1468    assert(a == [ 42, 42, 42, 42, 42]);
1469}
1470
1471@system unittest
1472{
1473    int[] a;
1474    fillWithMemcpy(a, 42);
1475    assert(a.length == 0);
1476    a = [ 1, 2, 3, 4, 5 ];
1477    fillWithMemcpy(a, 42);
1478    assert(a == [ 42, 42, 42, 42, 42]);
1479}
1480
1481//Make shared object
1482@system unittest
1483{
1484    import core.atomic : atomicLoad;
1485    auto psi = theAllocator.make!(shared(int))(10);
1486    assert(10 == (*psi).atomicLoad());
1487}
1488
1489private T[] uninitializedFillDefault(T)(T[] array) nothrow
1490{
1491    static if (__traits(isZeroInit, T))
1492    {
1493        import core.stdc.string : memset;
1494        if (array !is null)
1495            memset(array.ptr, 0, T.sizeof * array.length);
1496        return array;
1497    }
1498    else static if (is(immutable T == immutable char) || is(immutable T == immutable wchar))
1499    {
1500        import core.stdc.string : memset;
1501        if (array !is null)
1502            memset(array.ptr, 0xff, T.sizeof * array.length);
1503        return array;
1504    }
1505    else
1506    {
1507        T t = T.init;
1508        fillWithMemcpy(array, t);
1509        return array;
1510    }
1511}
1512
1513pure nothrow @nogc
1514@system unittest
1515{
1516    static struct S { int x = 42; @disable this(this); }
1517
1518    int[5] expected = [42, 42, 42, 42, 42];
1519    S[5] arr = void;
1520    uninitializedFillDefault(arr);
1521    assert((cast(int*) arr.ptr)[0 .. arr.length] == expected);
1522}
1523
1524@system unittest
1525{
1526    int[] a = [1, 2, 4];
1527    uninitializedFillDefault(a);
1528    assert(a == [0, 0, 0]);
1529
1530    char[] b = [1, 2, 4];
1531    uninitializedFillDefault(b);
1532    assert(b == [0xff, 0xff, 0xff]);
1533
1534    wchar[] c = [1, 2, 4];
1535    uninitializedFillDefault(c);
1536    assert(c == [0xffff, 0xffff, 0xffff]);
1537}
1538
1539@system unittest
1540{
1541    static struct P { float x = 0; float y = 0; }
1542
1543    static assert(__traits(isZeroInit, P));
1544    P[] a = [P(10, 11), P(20, 21), P(40, 41)];
1545    uninitializedFillDefault(a);
1546    assert(a == [P.init, P.init, P.init]);
1547}
1548
1549/**
1550Create an array of `T` with `length` elements using `alloc`. The array is either default-initialized, filled with copies of `init`, or initialized with values fetched from `range`.
1551
1552Params:
1553T = element type of the array being created
1554alloc = the allocator used for getting memory
1555length = length of the newly created array
1556init = element used for filling the array
1557range = range used for initializing the array elements
1558
1559Returns:
1560The newly-created array, or `null` if either `length` was `0` or
1561allocation failed.
1562
1563Throws:
1564The first two overloads throw only if `alloc`'s primitives do. The
1565overloads that involve copy initialization deallocate memory and propagate the
1566exception if the copy operation throws.
1567*/
1568T[] makeArray(T, Allocator)(auto ref Allocator alloc, size_t length)
1569{
1570    if (!length) return null;
1571    static if (T.sizeof <= 1)
1572    {
1573        const nAlloc = length * T.sizeof;
1574    }
1575    else
1576    {
1577        import core.checkedint : mulu;
1578        bool overflow;
1579        const nAlloc = mulu(length, T.sizeof, overflow);
1580        if (overflow) return null;
1581    }
1582
1583    static if (__traits(isZeroInit, T) && hasMember!(Allocator, "allocateZeroed"))
1584    {
1585        auto m = alloc.allocateZeroed(nAlloc);
1586        return (() @trusted => cast(T[]) m)();
1587    }
1588    else
1589    {
1590        auto m = alloc.allocate(nAlloc);
1591        if (!m.ptr) return null;
1592        alias U = Unqual!T;
1593        return () @trusted { return cast(T[]) uninitializedFillDefault(cast(U[]) m); }();
1594    }
1595}
1596
1597@system unittest
1598{
1599    void test1(A)(auto ref A alloc)
1600    {
1601        int[] a = alloc.makeArray!int(0);
1602        assert(a.length == 0 && a.ptr is null);
1603        a = alloc.makeArray!int(5);
1604        assert(a.length == 5);
1605        static immutable cheatsheet = [0, 0, 0, 0, 0];
1606        assert(a == cheatsheet);
1607    }
1608
1609    void test2(A)(auto ref A alloc)
1610    {
1611        static struct S { int x = 42; @disable this(this); }
1612        S[] arr = alloc.makeArray!S(5);
1613        assert(arr.length == 5);
1614        int[] arrInt = () @trusted { return (cast(int*) arr.ptr)[0 .. 5]; }();
1615        static immutable res = [42, 42, 42, 42, 42];
1616        assert(arrInt == res);
1617    }
1618
1619    import std.experimental.allocator.gc_allocator : GCAllocator;
1620    import std.experimental.allocator.mallocator : Mallocator;
1621    (alloc) /*pure nothrow*/ @safe { test1(alloc); test2(alloc);} (GCAllocator.instance);
1622    (alloc) nothrow @safe @nogc { test1(alloc); test2(alloc);} (Mallocator.instance);
1623    test2(theAllocator);
1624}
1625
1626@system unittest
1627{
1628    import std.algorithm.comparison : equal;
1629    auto a = theAllocator.makeArray!(shared int)(5);
1630    static assert(is(typeof(a) == shared(int)[]));
1631    assert(a.length == 5);
1632    assert(a.equal([0, 0, 0, 0, 0]));
1633
1634    auto b = theAllocator.makeArray!(const int)(5);
1635    static assert(is(typeof(b) == const(int)[]));
1636    assert(b.length == 5);
1637    assert(b.equal([0, 0, 0, 0, 0]));
1638
1639    auto c = theAllocator.makeArray!(immutable int)(5);
1640    static assert(is(typeof(c) == immutable(int)[]));
1641    assert(c.length == 5);
1642    assert(c.equal([0, 0, 0, 0, 0]));
1643}
1644
1645// https://issues.dlang.org/show_bug.cgi?id=19085 - makeArray with void
1646@system unittest
1647{
1648    auto b = theAllocator.makeArray!void(5);
1649    scope(exit) theAllocator.dispose(b);
1650    auto c = cast(ubyte[]) b;
1651    assert(c.length == 5);
1652    assert(c == [0, 0, 0, 0, 0]); // default initialization
1653}
1654
1655private enum hasPurePostblit(T) = !hasElaborateCopyConstructor!T ||
1656    is(typeof(() pure { T.init.__xpostblit(); }));
1657
1658private enum hasPureDtor(T) = !hasElaborateDestructor!T ||
1659    is(typeof(() pure { T.init.__xdtor(); }));
1660
1661// `true` when postblit and destructor of T cannot escape references to itself
1662private enum canSafelyDeallocPostRewind(T) = hasPurePostblit!T && hasPureDtor!T;
1663
1664/// Ditto
1665T[] makeArray(T, Allocator)(auto ref Allocator alloc, size_t length, T init)
1666{
1667    if (!length) return null;
1668    auto m = alloc.allocate(T.sizeof * length);
1669    if (!m.ptr) return null;
1670    auto result = () @trusted { return cast(T[]) m; } ();
1671    import std.traits : hasElaborateCopyConstructor;
1672    static if (hasElaborateCopyConstructor!T)
1673    {
1674        scope(failure)
1675        {
1676            static if (canSafelyDeallocPostRewind!T)
1677                () @trusted { alloc.deallocate(m); } ();
1678            else
1679                alloc.deallocate(m);
1680        }
1681
1682        size_t i = 0;
1683        static if (hasElaborateDestructor!T)
1684        {
1685            scope (failure)
1686            {
1687                foreach (j; 0 .. i)
1688                {
1689                    destroy(result[j]);
1690                }
1691            }
1692        }
1693        import core.lifetime : emplace;
1694        for (; i < length; ++i)
1695        {
1696            emplace!T(&result[i], init);
1697        }
1698    }
1699    else
1700    {
1701        alias U = Unqual!T;
1702        () @trusted { fillWithMemcpy(cast(U[]) result, *(cast(U*) &init)); }();
1703    }
1704    return result;
1705}
1706
1707///
1708@system unittest
1709{
1710    import std.algorithm.comparison : equal;
1711    static void test(T)()
1712    {
1713        T[] a = theAllocator.makeArray!T(2);
1714        assert(a.equal([0, 0]));
1715        a = theAllocator.makeArray!T(3, 42);
1716        assert(a.equal([42, 42, 42]));
1717        import std.range : only;
1718        a = theAllocator.makeArray!T(only(42, 43, 44));
1719        assert(a.equal([42, 43, 44]));
1720    }
1721    test!int();
1722    test!(shared int)();
1723    test!(const int)();
1724    test!(immutable int)();
1725}
1726
1727@system unittest
1728{
1729    void test(T)(in T initialValue)
1730    {
1731        auto t = theAllocator.makeArray!T(100, initialValue);
1732        //auto t = theAllocator.makeArray(100, initialValue); // works well with the old code
1733    }
1734
1735    const int init = 3;
1736    test(init);
1737}
1738
1739@system unittest
1740{
1741    void test(A)(auto ref A alloc)
1742    {
1743        long[] a = alloc.makeArray!long(0, 42);
1744        assert(a.length == 0 && a.ptr is null);
1745        a = alloc.makeArray!long(5, 42);
1746        assert(a.length == 5);
1747        assert(a == [ 42, 42, 42, 42, 42 ]);
1748    }
1749    import std.experimental.allocator.gc_allocator : GCAllocator;
1750    (alloc) /*pure nothrow*/ @safe { test(alloc); } (GCAllocator.instance);
1751    test(theAllocator);
1752}
1753
1754// test failure with a pure, failing struct
1755@safe unittest
1756{
1757    import std.exception : assertThrown, enforce;
1758
1759    struct NoCopy
1760    {
1761        @disable this();
1762
1763        this(int b){}
1764
1765        // can't be copied
1766        this(this)
1767        {
1768            enforce(1 == 2);
1769        }
1770    }
1771    import std.experimental.allocator.mallocator : Mallocator;
1772    assertThrown(makeArray!NoCopy(Mallocator.instance, 10, NoCopy(42)));
1773}
1774
1775// test failure with an impure, failing struct
1776@system unittest
1777{
1778    import std.exception : assertThrown, enforce;
1779
1780    static int i = 0;
1781    struct Singleton
1782    {
1783        @disable this();
1784
1785        this(int b){}
1786
1787        // can't be copied
1788        this(this)
1789        {
1790            enforce(i++ == 0);
1791        }
1792
1793        ~this()
1794        {
1795            i--;
1796        }
1797    }
1798    import std.experimental.allocator.mallocator : Mallocator;
1799    assertThrown(makeArray!Singleton(Mallocator.instance, 10, Singleton(42)));
1800}
1801
1802/// Ditto
1803Unqual!(ElementEncodingType!R)[] makeArray(Allocator, R)(auto ref Allocator alloc, R range)
1804if (isInputRange!R && !isInfinite!R)
1805{
1806    alias T = Unqual!(ElementEncodingType!R);
1807    return makeArray!(T, Allocator, R)(alloc, range);
1808}
1809
1810/// Ditto
1811T[] makeArray(T, Allocator, R)(auto ref Allocator alloc, R range)
1812if (isInputRange!R && !isInfinite!R)
1813{
1814    static if (isForwardRange!R || hasLength!R)
1815    {
1816        static if (hasLength!R || isNarrowString!R)
1817            immutable length = range.length;
1818        else
1819            immutable length = range.save.walkLength;
1820
1821        if (!length) return null;
1822        auto m = alloc.allocate(T.sizeof * length);
1823        if (!m.ptr) return null;
1824        auto result = () @trusted { return cast(T[]) m; } ();
1825
1826        size_t i = 0;
1827        scope (failure)
1828        {
1829            foreach (j; 0 .. i)
1830            {
1831                auto p = () @trusted { return cast(Unqual!T*) &result[j]; }();
1832                destroy(p);
1833            }
1834
1835            static if (canSafelyDeallocPostRewind!T)
1836                () @trusted { alloc.deallocate(m); } ();
1837            else
1838                alloc.deallocate(m);
1839        }
1840
1841        import core.internal.lifetime : emplaceRef;
1842        static if (isNarrowString!R || isRandomAccessRange!R)
1843        {
1844            foreach (j; 0 .. range.length)
1845            {
1846                emplaceRef!T(result[i++], range[j]);
1847            }
1848        }
1849        else
1850        {
1851            for (; !range.empty; range.popFront, ++i)
1852            {
1853                emplaceRef!T(result[i], range.front);
1854            }
1855        }
1856
1857        return result;
1858    }
1859    else
1860    {
1861        // Estimated size
1862        size_t estimated = 8;
1863        auto m = alloc.allocate(T.sizeof * estimated);
1864        if (!m.ptr) return null;
1865        auto result = () @trusted { return cast(T[]) m; } ();
1866
1867        size_t initialized = 0;
1868        void bailout()
1869        {
1870            foreach (i; 0 .. initialized + 1)
1871            {
1872                destroy(result[i]);
1873            }
1874
1875            static if (canSafelyDeallocPostRewind!T)
1876                () @trusted { alloc.deallocate(m); } ();
1877            else
1878                alloc.deallocate(m);
1879        }
1880        scope (failure) bailout;
1881
1882        for (; !range.empty; range.popFront, ++initialized)
1883        {
1884            if (initialized == estimated)
1885            {
1886                // Need to reallocate
1887                static if (hasPurePostblit!T)
1888                    auto success = () @trusted { return alloc.reallocate(m, T.sizeof * (estimated *= 2)); } ();
1889                else
1890                    auto success = alloc.reallocate(m, T.sizeof * (estimated *= 2));
1891                if (!success)
1892                {
1893                    bailout;
1894                    return null;
1895                }
1896                result = () @trusted { return cast(T[]) m; } ();
1897            }
1898            import core.internal.lifetime : emplaceRef;
1899            emplaceRef(result[initialized], range.front);
1900        }
1901
1902        if (initialized < estimated)
1903        {
1904            // Try to shrink memory, no harm if not possible
1905            static if (hasPurePostblit!T)
1906                auto success = () @trusted { return alloc.reallocate(m, T.sizeof * initialized); } ();
1907            else
1908                auto success = alloc.reallocate(m, T.sizeof * initialized);
1909            if (success)
1910                result = () @trusted { return cast(T[]) m; } ();
1911        }
1912
1913        return result[0 .. initialized];
1914    }
1915}
1916
1917@system unittest
1918{
1919    void test(A)(auto ref A alloc)
1920    {
1921        long[] a = alloc.makeArray!long((int[]).init);
1922        assert(a.length == 0 && a.ptr is null);
1923        a = alloc.makeArray!long([5, 42]);
1924        assert(a.length == 2);
1925        assert(a == [ 5, 42]);
1926
1927        // we can also infer the type
1928        auto b = alloc.makeArray([4.0, 2.0]);
1929        static assert(is(typeof(b) == double[]));
1930        assert(b == [4.0, 2.0]);
1931    }
1932    import std.experimental.allocator.gc_allocator : GCAllocator;
1933    (alloc) pure nothrow @safe { test(alloc); } (GCAllocator.instance);
1934    test(theAllocator);
1935}
1936
1937// infer types for strings
1938@system unittest
1939{
1940    void test(A)(auto ref A alloc)
1941    {
1942        auto c = alloc.makeArray("foo������");
1943        static assert(is(typeof(c) == char[]));
1944        assert(c == "foo������");
1945
1946        auto d = alloc.makeArray("foo������"d);
1947        static assert(is(typeof(d) == dchar[]));
1948        assert(d == "foo������");
1949
1950        auto w = alloc.makeArray("foo������"w);
1951        static assert(is(typeof(w) == wchar[]));
1952        assert(w == "foo������");
1953    }
1954
1955    import std.experimental.allocator.gc_allocator : GCAllocator;
1956    (alloc) pure nothrow @safe { test(alloc); } (GCAllocator.instance);
1957    test(theAllocator);
1958}
1959
1960/*pure*/ nothrow @safe unittest
1961{
1962    import std.algorithm.comparison : equal;
1963    import std.experimental.allocator.gc_allocator : GCAllocator;
1964    import std.internal.test.dummyrange;
1965    import std.range : iota;
1966    foreach (DummyType; AllDummyRanges)
1967    {
1968        (alloc) pure nothrow @safe
1969        {
1970            DummyType d;
1971            auto arr = alloc.makeArray(d);
1972            assert(arr.length == 10);
1973            assert(arr.equal(iota(1, 11)));
1974        } (GCAllocator.instance);
1975    }
1976}
1977
1978// test failure with a pure, failing struct
1979@safe unittest
1980{
1981    import std.exception : assertThrown, enforce;
1982
1983    struct NoCopy
1984    {
1985        int b;
1986
1987        @disable this();
1988
1989        this(int b)
1990        {
1991            this.b = b;
1992        }
1993
1994        // can't be copied
1995        this(this)
1996        {
1997            enforce(b < 3, "there can only be three elements");
1998        }
1999    }
2000    import std.experimental.allocator.mallocator : Mallocator;
2001    auto arr = [NoCopy(1), NoCopy(2), NoCopy(3)];
2002    assertThrown(makeArray!NoCopy(Mallocator.instance, arr));
2003
2004    struct NoCopyRange
2005    {
2006        static j = 0;
2007        bool empty()
2008        {
2009            return j > 5;
2010        }
2011
2012        auto front()
2013        {
2014            return NoCopy(j);
2015        }
2016
2017        void popFront()
2018        {
2019            j++;
2020        }
2021    }
2022    makeArray!NoCopy(Mallocator.instance, NoCopyRange()); // rvalue elements are forwarded/moved
2023}
2024
2025// test failure with an impure, failing struct
2026@system unittest
2027{
2028    import std.exception : assertThrown, enforce;
2029
2030    static i = 0;
2031    static maxElements = 2;
2032    struct NoCopy
2033    {
2034        int val;
2035        @disable this();
2036
2037        this(int b){
2038            this.val = i++;
2039        }
2040
2041        // can't be copied
2042        this(this)
2043        {
2044            enforce(i++ < maxElements, "there can only be four elements");
2045        }
2046    }
2047
2048    import std.experimental.allocator.mallocator : Mallocator;
2049    auto arr = [NoCopy(1), NoCopy(2)];
2050    assertThrown(makeArray!NoCopy(Mallocator.instance, arr));
2051
2052    i = 0;
2053    maxElements = 0; // disallow any postblit
2054    static j = 0;
2055
2056    struct NoCopyRange
2057    {
2058        bool empty()
2059        {
2060            return j > 100;
2061        }
2062
2063        auto front()
2064        {
2065            return NoCopy(1);
2066        }
2067
2068        void popFront()
2069        {
2070            j++;
2071        }
2072    }
2073
2074    auto arr2 = makeArray!NoCopy(Mallocator.instance, NoCopyRange());
2075    assert(i == j && i == 101); // all 101 rvalue elements forwarded/moved
2076}
2077
2078version (StdUnittest)
2079{
2080    private struct ForcedInputRange(T)
2081    {
2082        T[]* array;
2083        pure nothrow @safe @nogc:
2084        bool empty() { return !array || (*array).empty; }
2085        ref T front() { return (*array)[0]; }
2086        void popFront() { *array = (*array)[1 .. $]; }
2087    }
2088}
2089
2090@system unittest
2091{
2092    import std.array : array;
2093    import std.range : iota;
2094    int[] arr = iota(10).array;
2095
2096    void test(A)(auto ref A alloc)
2097    {
2098        ForcedInputRange!int r;
2099        long[] a = alloc.makeArray!long(r);
2100        assert(a.length == 0 && a.ptr is null);
2101        auto arr2 = arr;
2102        r.array = () @trusted { return &arr2; } ();
2103        a = alloc.makeArray!long(r);
2104        assert(a.length == 10);
2105        assert(a == iota(10).array);
2106    }
2107    import std.experimental.allocator.gc_allocator : GCAllocator;
2108    (alloc) pure nothrow @safe { test(alloc); } (GCAllocator.instance);
2109    test(theAllocator);
2110}
2111
2112/**
2113Grows `array` by appending `delta` more elements. The needed memory is
2114allocated using `alloc`. The extra elements added are either default-
2115initialized, filled with copies of `init`, or initialized with values
2116fetched from `range`.
2117
2118Params:
2119T = element type of the array being created
2120alloc = the allocator used for getting memory
2121array = a reference to the array being grown
2122delta = number of elements to add (upon success the new length of `array` is
2123$(D array.length + delta))
2124init = element used for filling the array
2125range = range used for initializing the array elements
2126
2127Returns:
2128`true` upon success, `false` if memory could not be allocated. In the
2129latter case `array` is left unaffected.
2130
2131Throws:
2132The first two overloads throw only if `alloc`'s primitives do. The
2133overloads that involve copy initialization deallocate memory and propagate the
2134exception if the copy operation throws.
2135*/
2136bool expandArray(T, Allocator)(auto ref Allocator alloc, ref T[] array,
2137        size_t delta)
2138{
2139    if (!delta) return true;
2140    if (array is null) return false;
2141    immutable oldLength = array.length;
2142    void[] buf = array;
2143    if (!alloc.reallocate(buf, buf.length + T.sizeof * delta)) return false;
2144    array = cast(T[]) buf;
2145    array[oldLength .. $].uninitializedFillDefault;
2146    return true;
2147}
2148
2149@system unittest
2150{
2151    void test(A)(auto ref A alloc)
2152    {
2153        auto arr = alloc.makeArray!int([1, 2, 3]);
2154        assert(alloc.expandArray(arr, 3));
2155        assert(arr == [1, 2, 3, 0, 0, 0]);
2156    }
2157    import std.experimental.allocator.gc_allocator : GCAllocator;
2158    test(GCAllocator.instance);
2159    test(theAllocator);
2160}
2161
2162/// Ditto
2163bool expandArray(T, Allocator)(auto ref Allocator alloc, ref T[] array,
2164    size_t delta, auto ref T init)
2165{
2166    if (!delta) return true;
2167    if (array is null) return false;
2168    void[] buf = array;
2169    if (!alloc.reallocate(buf, buf.length + T.sizeof * delta)) return false;
2170    immutable oldLength = array.length;
2171    array = cast(T[]) buf;
2172    scope(failure) array[oldLength .. $].uninitializedFillDefault;
2173    import std.algorithm.mutation : uninitializedFill;
2174    array[oldLength .. $].uninitializedFill(init);
2175    return true;
2176}
2177
2178@system unittest
2179{
2180    void test(A)(auto ref A alloc)
2181    {
2182        auto arr = alloc.makeArray!int([1, 2, 3]);
2183        assert(alloc.expandArray(arr, 3, 1));
2184        assert(arr == [1, 2, 3, 1, 1, 1]);
2185    }
2186    import std.experimental.allocator.gc_allocator : GCAllocator;
2187    test(GCAllocator.instance);
2188    test(theAllocator);
2189}
2190
2191/// Ditto
2192bool expandArray(T, Allocator, R)(auto ref Allocator alloc, ref T[] array,
2193        R range)
2194if (isInputRange!R)
2195{
2196    if (array is null) return false;
2197    static if (isForwardRange!R)
2198    {
2199        immutable delta = walkLength(range.save);
2200        if (!delta) return true;
2201        immutable oldLength = array.length;
2202
2203        // Reallocate support memory
2204        void[] buf = array;
2205        if (!alloc.reallocate(buf, buf.length + T.sizeof * delta))
2206        {
2207            return false;
2208        }
2209        array = cast(T[]) buf;
2210        // At this point we're committed to the new length.
2211
2212        auto toFill = array[oldLength .. $];
2213        scope (failure)
2214        {
2215            // Fill the remainder with default-constructed data
2216            toFill.uninitializedFillDefault;
2217        }
2218
2219        for (; !range.empty; range.popFront, toFill = toFill[1 .. $])
2220        {
2221            assert(toFill.length > 0);
2222            import core.lifetime : emplace;
2223            emplace!T(&toFill[0], range.front);
2224        }
2225        assert(toFill.length == 0);
2226    }
2227    else
2228    {
2229        scope(failure)
2230        {
2231            // The last element didn't make it, fill with default
2232            array[$ - 1 .. $].uninitializedFillDefault;
2233        }
2234        void[] buf = array;
2235        for (; !range.empty; range.popFront)
2236        {
2237            if (!alloc.reallocate(buf, buf.length + T.sizeof))
2238            {
2239                array = cast(T[]) buf;
2240                return false;
2241            }
2242            import core.lifetime : emplace;
2243            emplace!T(buf[$ - T.sizeof .. $], range.front);
2244        }
2245
2246        array = cast(T[]) buf;
2247    }
2248    return true;
2249}
2250
2251///
2252@system unittest
2253{
2254    auto arr = theAllocator.makeArray!int([1, 2, 3]);
2255    assert(theAllocator.expandArray(arr, 2));
2256    assert(arr == [1, 2, 3, 0, 0]);
2257    import std.range : only;
2258    assert(theAllocator.expandArray(arr, only(4, 5)));
2259    assert(arr == [1, 2, 3, 0, 0, 4, 5]);
2260}
2261
2262@system unittest
2263{
2264    auto arr = theAllocator.makeArray!int([1, 2, 3]);
2265    ForcedInputRange!int r;
2266    int[] b = [ 1, 2, 3, 4 ];
2267    auto temp = b;
2268    r.array = &temp;
2269    assert(theAllocator.expandArray(arr, r));
2270    assert(arr == [1, 2, 3, 1, 2, 3, 4]);
2271}
2272
2273// Regression test for https://issues.dlang.org/show_bug.cgi?id=20929
2274@system unittest
2275{
2276    static void test(Char, Allocator)(auto ref Allocator alloc)
2277    {
2278        auto arr = alloc.makeArray!Char(1, Char('f'));
2279
2280        import std.utf : byUTF;
2281        auto forwardRange = "oo".byUTF!Char();
2282        static assert(isForwardRange!(typeof(forwardRange)));
2283        // Test the forward-range code-path.
2284        assert(alloc.expandArray(arr, forwardRange));
2285
2286        assert(arr == "foo");
2287
2288        immutable(Char)[] temp = "bar";
2289        auto inputRange = ForcedInputRange!(immutable(Char))(&temp);
2290        // Test the input-range code-path.
2291        assert(alloc.expandArray(arr, inputRange));
2292
2293        assert(arr == "foobar");
2294    }
2295
2296    import std.experimental.allocator.gc_allocator : GCAllocator;
2297    test!char(GCAllocator.instance);
2298    test!wchar(GCAllocator.instance);
2299    test!char(theAllocator);
2300    test!wchar(theAllocator);
2301}
2302
2303/**
2304Shrinks an array by `delta` elements.
2305
2306If $(D array.length < delta), does nothing and returns `false`. Otherwise,
2307destroys the last $(D array.length - delta) elements in the array and then
2308reallocates the array's buffer. If reallocation fails, fills the array with
2309default-initialized data.
2310
2311Params:
2312T = element type of the array being created
2313alloc = the allocator used for getting memory
2314array = a reference to the array being shrunk
2315delta = number of elements to remove (upon success the new length of `array` is $(D array.length - delta))
2316
2317Returns:
2318`true` upon success, `false` if memory could not be reallocated. In the latter
2319case, the slice $(D array[$ - delta .. $]) is left with default-initialized
2320elements.
2321
2322Throws:
2323The first two overloads throw only if `alloc`'s primitives do. The
2324overloads that involve copy initialization deallocate memory and propagate the
2325exception if the copy operation throws.
2326*/
2327bool shrinkArray(T, Allocator)(auto ref Allocator alloc,
2328        ref T[] array, size_t delta)
2329{
2330    if (delta > array.length) return false;
2331
2332    // Destroy elements. If a destructor throws, fill the already destroyed
2333    // stuff with the default initializer.
2334    {
2335        size_t destroyed;
2336        scope(failure)
2337        {
2338            array[$ - delta .. $][0 .. destroyed].uninitializedFillDefault;
2339        }
2340        foreach (ref e; array[$ - delta .. $])
2341        {
2342            e.destroy;
2343            ++destroyed;
2344        }
2345    }
2346
2347    if (delta == array.length)
2348    {
2349        alloc.deallocate(array);
2350        array = null;
2351        return true;
2352    }
2353
2354    void[] buf = array;
2355    if (!alloc.reallocate(buf, buf.length - T.sizeof * delta))
2356    {
2357        // urgh, at least fill back with default
2358        array[$ - delta .. $].uninitializedFillDefault;
2359        return false;
2360    }
2361    array = cast(T[]) buf;
2362    return true;
2363}
2364
2365///
2366@system unittest
2367{
2368    int[] a = theAllocator.makeArray!int(100, 42);
2369    assert(a.length == 100);
2370    assert(theAllocator.shrinkArray(a, 98));
2371    assert(a.length == 2);
2372    assert(a == [42, 42]);
2373}
2374
2375@system unittest
2376{
2377    void test(A)(auto ref A alloc)
2378    {
2379        long[] a = alloc.makeArray!long((int[]).init);
2380        assert(a.length == 0 && a.ptr is null);
2381        a = alloc.makeArray!long(100, 42);
2382        assert(alloc.shrinkArray(a, 98));
2383        assert(a.length == 2);
2384        assert(a == [ 42, 42]);
2385    }
2386    import std.experimental.allocator.gc_allocator : GCAllocator;
2387    test(GCAllocator.instance);
2388    test(theAllocator);
2389}
2390
2391/**
2392
2393Destroys and then deallocates (using `alloc`) the object pointed to by a
2394pointer, the class object referred to by a `class` or `interface`
2395reference, or an entire array. It is assumed the respective entities had been
2396allocated with the same allocator.
2397
2398*/
2399void dispose(A, T)(auto ref A alloc, auto ref T* p)
2400{
2401    static if (hasElaborateDestructor!T)
2402    {
2403        destroy(*p);
2404    }
2405    alloc.deallocate((cast(void*) p)[0 .. T.sizeof]);
2406    static if (__traits(isRef, p))
2407        p = null;
2408}
2409
2410/// Ditto
2411void dispose(A, T)(auto ref A alloc, auto ref T p)
2412if (is(T == class) || is(T == interface))
2413{
2414    if (!p) return;
2415    static if (is(T == interface))
2416    {
2417        version (Windows)
2418        {
2419            import core.sys.windows.unknwn : IUnknown;
2420            static assert(!is(T: IUnknown), "COM interfaces can't be destroyed in "
2421                ~ __PRETTY_FUNCTION__);
2422        }
2423        auto ob = cast(Object) p;
2424    }
2425    else
2426        alias ob = p;
2427    auto support = (cast(void*) ob)[0 .. typeid(ob).initializer.length];
2428    destroy(p);
2429    alloc.deallocate(support);
2430    static if (__traits(isRef, p))
2431        p = null;
2432}
2433
2434/// Ditto
2435void dispose(A, T)(auto ref A alloc, auto ref T[] array)
2436{
2437    static if (hasElaborateDestructor!(typeof(array[0])))
2438    {
2439        foreach (ref e; array)
2440        {
2441            destroy(e);
2442        }
2443    }
2444    alloc.deallocate(array);
2445    static if (__traits(isRef, array))
2446        array = null;
2447}
2448
2449@system unittest
2450{
2451    static int x;
2452    static interface I
2453    {
2454        void method();
2455    }
2456    static class A : I
2457    {
2458        int y;
2459        override void method() { x = 21; }
2460        ~this() { x = 42; }
2461    }
2462    static class B : A
2463    {
2464    }
2465    auto a = theAllocator.make!A;
2466    a.method();
2467    assert(x == 21);
2468    theAllocator.dispose(a);
2469    assert(x == 42);
2470
2471    B b = theAllocator.make!B;
2472    b.method();
2473    assert(x == 21);
2474    theAllocator.dispose(b);
2475    assert(x == 42);
2476
2477    I i = theAllocator.make!B;
2478    i.method();
2479    assert(x == 21);
2480    theAllocator.dispose(i);
2481    assert(x == 42);
2482
2483    int[] arr = theAllocator.makeArray!int(43);
2484    theAllocator.dispose(arr);
2485}
2486
2487// https://issues.dlang.org/show_bug.cgi?id=16512
2488@system unittest
2489{
2490    import std.experimental.allocator.mallocator : Mallocator;
2491
2492    int* i = Mallocator.instance.make!int(0);
2493    Mallocator.instance.dispose(i);
2494    assert(i is null);
2495
2496    Object o = Mallocator.instance.make!Object();
2497    Mallocator.instance.dispose(o);
2498    assert(o is null);
2499
2500    uint* u = Mallocator.instance.make!uint(0);
2501    Mallocator.instance.dispose((){return u;}());
2502    assert(u !is null);
2503
2504    uint[] ua = Mallocator.instance.makeArray!uint([0,1,2]);
2505    Mallocator.instance.dispose(ua);
2506    assert(ua is null);
2507}
2508
2509// https://issues.dlang.org/show_bug.cgi?id=15721
2510@system unittest
2511{
2512    import std.experimental.allocator.mallocator : Mallocator;
2513
2514    interface Foo {}
2515    class Bar: Foo {}
2516
2517    Bar bar;
2518    Foo foo;
2519    bar = Mallocator.instance.make!Bar;
2520    foo = cast(Foo) bar;
2521    Mallocator.instance.dispose(foo);
2522}
2523
2524/**
2525Allocates a multidimensional array of elements of type T.
2526
2527Params:
2528N = number of dimensions
2529T = element type of an element of the multidimensional arrat
2530alloc = the allocator used for getting memory
2531lengths = static array containing the size of each dimension
2532
2533Returns:
2534An N-dimensional array with individual elements of type T.
2535*/
2536auto makeMultidimensionalArray(T, Allocator, size_t N)(auto ref Allocator alloc, size_t[N] lengths...)
2537{
2538    static if (N == 1)
2539    {
2540        return makeArray!T(alloc, lengths[0]);
2541    }
2542    else
2543    {
2544        alias E = typeof(makeMultidimensionalArray!(T, Allocator, N - 1)(alloc, lengths[1 .. $]));
2545        auto ret = makeArray!E(alloc, lengths[0]);
2546        foreach (ref e; ret)
2547            e = makeMultidimensionalArray!(T, Allocator, N - 1)(alloc, lengths[1 .. $]);
2548        return ret;
2549    }
2550}
2551
2552///
2553@system unittest
2554{
2555    import std.experimental.allocator.mallocator : Mallocator;
2556
2557    auto mArray = Mallocator.instance.makeMultidimensionalArray!int(2, 3, 6);
2558
2559    // deallocate when exiting scope
2560    scope(exit)
2561    {
2562        Mallocator.instance.disposeMultidimensionalArray(mArray);
2563    }
2564
2565    assert(mArray.length == 2);
2566    foreach (lvl2Array; mArray)
2567    {
2568        assert(lvl2Array.length == 3);
2569        foreach (lvl3Array; lvl2Array)
2570            assert(lvl3Array.length == 6);
2571    }
2572}
2573
2574/**
2575Destroys and then deallocates a multidimensional array, assuming it was
2576created with makeMultidimensionalArray and the same allocator was used.
2577
2578Params:
2579T = element type of an element of the multidimensional array
2580alloc = the allocator used for getting memory
2581array = the multidimensional array that is to be deallocated
2582*/
2583void disposeMultidimensionalArray(T, Allocator)(auto ref Allocator alloc, auto ref T[] array)
2584{
2585    static if (isArray!T)
2586    {
2587        foreach (ref e; array)
2588            disposeMultidimensionalArray(alloc, e);
2589    }
2590
2591    dispose(alloc, array);
2592    static if (__traits(isRef, array))
2593        array = null;
2594}
2595
2596///
2597@system unittest
2598{
2599    struct TestAllocator
2600    {
2601        import std.experimental.allocator.common : platformAlignment;
2602        import std.experimental.allocator.mallocator : Mallocator;
2603
2604        alias allocator = Mallocator.instance;
2605
2606        private static struct ByteRange
2607        {
2608            void* ptr;
2609            size_t length;
2610        }
2611
2612        private ByteRange[] _allocations;
2613
2614        enum uint alignment = platformAlignment;
2615
2616        void[] allocate(size_t numBytes)
2617        {
2618             auto ret = allocator.allocate(numBytes);
2619             _allocations ~= ByteRange(ret.ptr, ret.length);
2620             return ret;
2621        }
2622
2623        bool deallocate(void[] bytes)
2624        {
2625            import std.algorithm.mutation : remove;
2626            import std.algorithm.searching : canFind;
2627
2628            bool pred(ByteRange other)
2629            { return other.ptr == bytes.ptr && other.length == bytes.length; }
2630
2631            assert(_allocations.canFind!pred);
2632
2633             _allocations = _allocations.remove!pred;
2634             return allocator.deallocate(bytes);
2635        }
2636
2637        ~this()
2638        {
2639            assert(!_allocations.length);
2640        }
2641    }
2642
2643    TestAllocator allocator;
2644
2645    auto mArray = allocator.makeMultidimensionalArray!int(2, 3, 5, 6, 7, 2);
2646
2647    allocator.disposeMultidimensionalArray(mArray);
2648}
2649
2650/**
2651
2652Returns a dynamically-typed `CAllocator` built around a given statically-
2653typed allocator `a` of type `A`. Passing a pointer to the allocator
2654creates a dynamic allocator around the allocator pointed to by the pointer,
2655without attempting to copy or move it. Passing the allocator by value or
2656reference behaves as follows.
2657
2658$(UL
2659$(LI If `A` has no state, the resulting object is allocated in static
2660shared storage.)
2661$(LI If `A` has state, the result will $(REF move, std,algorithm,mutation)
2662the supplied allocator $(D A a) within. The result itself is allocated in its
2663own statically-typed allocator.)
2664)
2665
2666*/
2667RCIAllocator allocatorObject(A)(auto ref A a)
2668if (!isPointer!A)
2669{
2670    import core.lifetime : emplace;
2671    static if (stateSize!A == 0)
2672    {
2673        enum s = stateSize!(CAllocatorImpl!A).divideRoundUp(ulong.sizeof);
2674        __gshared ulong[s] state;
2675        __gshared RCIAllocator result;
2676        if (result.isNull)
2677        {
2678            // Don't care about a few races
2679            result = RCIAllocator(emplace!(CAllocatorImpl!A)(state[]));
2680        }
2681        assert(!result.isNull);
2682        return result;
2683    }
2684    else
2685    {
2686        auto state = a.allocate(stateSize!(CAllocatorImpl!A));
2687        import std.algorithm.mutation : move;
2688        import std.traits : hasMember;
2689        static if (hasMember!(A, "deallocate"))
2690        {
2691            scope(failure) a.deallocate(state);
2692        }
2693        auto tmp = cast(CAllocatorImpl!A) emplace!(CAllocatorImpl!A)(state);
2694        move(a, tmp.impl);
2695        return RCIAllocator(tmp);
2696    }
2697}
2698
2699/// Ditto
2700RCIAllocator allocatorObject(A)(A* pa)
2701{
2702    assert(pa);
2703    import core.lifetime : emplace;
2704    auto state = pa.allocate(stateSize!(CAllocatorImpl!(A, Yes.indirect)));
2705    import std.traits : hasMember;
2706    static if (hasMember!(A, "deallocate"))
2707    {
2708        scope(failure) pa.deallocate(state);
2709    }
2710    return RCIAllocator(emplace!(CAllocatorImpl!(A, Yes.indirect))
2711                            (state, pa));
2712}
2713
2714///
2715@system unittest
2716{
2717    import std.experimental.allocator.mallocator : Mallocator;
2718
2719    RCIAllocator a = allocatorObject(Mallocator.instance);
2720    auto b = a.allocate(100);
2721    assert(b.length == 100);
2722    assert(a.deallocate(b));
2723
2724    // The in-situ region must be used by pointer
2725    import std.experimental.allocator.building_blocks.region : InSituRegion;
2726    auto r = InSituRegion!1024();
2727    a = allocatorObject(&r);
2728    b = a.allocate(200);
2729    assert(b.length == 200);
2730    // In-situ regions can deallocate the last allocation
2731    assert(a.deallocate(b));
2732}
2733
2734@system unittest
2735{
2736    import std.conv;
2737    import std.experimental.allocator.mallocator;
2738    import std.experimental.allocator.building_blocks.stats_collector;
2739
2740    alias SCAlloc = StatsCollector!(Mallocator, Options.bytesUsed);
2741    SCAlloc statsCollectorAlloc;
2742    assert(statsCollectorAlloc.bytesUsed == 0);
2743
2744    auto _allocator = allocatorObject(statsCollectorAlloc);
2745    // Ensure that the allocator was passed through in CAllocatorImpl
2746    // This allocator was used to allocate the chunk that holds the
2747    // CAllocatorImpl object; which is it's own wrapper
2748    assert((cast(CAllocatorImpl!(SCAlloc))(_allocator._alloc)).impl.bytesUsed
2749            == stateSize!(CAllocatorImpl!(SCAlloc)));
2750    _allocator.allocate(1);
2751    assert((cast(CAllocatorImpl!(SCAlloc))(_allocator._alloc)).impl.bytesUsed
2752            == stateSize!(CAllocatorImpl!(SCAlloc)) + 1);
2753}
2754
2755/**
2756
2757Returns a dynamically-typed `CSharedAllocator` built around a given statically-
2758typed allocator `a` of type `A`. Passing a pointer to the allocator
2759creates a dynamic allocator around the allocator pointed to by the pointer,
2760without attempting to copy or move it. Passing the allocator by value or
2761reference behaves as follows.
2762
2763$(UL
2764$(LI If `A` has no state, the resulting object is allocated in static
2765shared storage.)
2766$(LI If `A` has state and is copyable, the result will
2767$(REF move, std,algorithm,mutation) the supplied allocator $(D A a) within.
2768The result itself is allocated in its own statically-typed allocator.)
2769$(LI If `A` has state and is not copyable, the result will move the
2770passed-in argument into the result. The result itself is allocated in its own
2771statically-typed allocator.)
2772)
2773
2774*/
2775//nothrow @safe
2776//nothrow @nogc @safe
2777nothrow
2778RCISharedAllocator sharedAllocatorObject(A)(auto ref A a)
2779if (!isPointer!A)
2780{
2781    import core.lifetime : emplace;
2782    static if (stateSize!A == 0)
2783    {
2784        enum s = stateSize!(CSharedAllocatorImpl!A).divideRoundUp(ulong.sizeof);
2785        static shared ulong[s] state;
2786        static RCISharedAllocator result;
2787        if (result.isNull)
2788        {
2789            // Don't care about a few races
2790            result = RCISharedAllocator(
2791                    (cast(shared CSharedAllocatorImpl!A)(
2792                        emplace!(CSharedAllocatorImpl!A)(
2793                            (() @trusted => cast(ulong[]) state[])()))));
2794        }
2795        assert(!result.isNull);
2796        return result;
2797    }
2798    else static if (is(typeof({ shared A b = a; shared A c = b; }))) // copyable
2799    {
2800        auto state = a.allocate(stateSize!(CSharedAllocatorImpl!A));
2801        import std.algorithm.mutation : move;
2802        import std.traits : hasMember;
2803        static if (hasMember!(A, "deallocate"))
2804        {
2805            scope(failure) a.deallocate(state);
2806        }
2807        auto tmp = emplace!(shared CSharedAllocatorImpl!A)(state);
2808        move(a, tmp.impl);
2809        return RCISharedAllocator(tmp);
2810    }
2811    else // the allocator object is not copyable
2812    {
2813        assert(0, "Not yet implemented");
2814    }
2815}
2816
2817/// Ditto
2818RCISharedAllocator sharedAllocatorObject(A)(A* pa)
2819{
2820    assert(pa);
2821    import core.lifetime : emplace;
2822    auto state = pa.allocate(stateSize!(CSharedAllocatorImpl!(A, Yes.indirect)));
2823    import std.traits : hasMember;
2824    static if (hasMember!(A, "deallocate"))
2825    {
2826        scope(failure) pa.deallocate(state);
2827    }
2828    return RCISharedAllocator(emplace!(shared CSharedAllocatorImpl!(A, Yes.indirect))(state, pa));
2829}
2830
2831
2832/**
2833
2834Implementation of `IAllocator` using `Allocator`. This adapts a
2835statically-built allocator type to `IAllocator` that is directly usable by
2836non-templated code.
2837
2838Usually `CAllocatorImpl` is used indirectly by calling $(LREF theAllocator).
2839*/
2840class CAllocatorImpl(Allocator, Flag!"indirect" indirect = No.indirect)
2841    : IAllocator
2842{
2843    import std.traits : hasMember;
2844
2845    static if (stateSize!Allocator) private size_t rc = 1;
2846
2847    /**
2848    The implementation is available as a public member.
2849    */
2850    static if (indirect)
2851    {
2852    nothrow:
2853        private Allocator* pimpl;
2854
2855        @nogc pure @safe
2856        ref Allocator impl()
2857        {
2858            return *pimpl;
2859        }
2860
2861        @nogc pure @safe
2862        this(Allocator* pa)
2863        {
2864            pimpl = pa;
2865        }
2866    }
2867    else
2868    {
2869        static if (stateSize!Allocator) Allocator impl;
2870        else alias impl = Allocator.instance;
2871    }
2872
2873nothrow:
2874    /// Returns `impl.alignment`.
2875    override @property uint alignment()
2876    {
2877        return impl.alignment;
2878    }
2879
2880    /**
2881    Returns `impl.goodAllocSize(s)`.
2882    */
2883    override size_t goodAllocSize(size_t s)
2884    {
2885        return impl.goodAllocSize(s);
2886    }
2887
2888    /**
2889    Returns `impl.allocate(s)`.
2890    */
2891    override void[] allocate(size_t s, TypeInfo ti = null)
2892    {
2893        return impl.allocate(s);
2894    }
2895
2896    /**
2897    If `impl.alignedAllocate` exists, calls it and returns the result.
2898    Otherwise, always returns `null`.
2899    */
2900    override void[] alignedAllocate(size_t s, uint a)
2901    {
2902        static if (hasMember!(Allocator, "alignedAllocate"))
2903            return impl.alignedAllocate(s, a);
2904        else
2905            return null;
2906    }
2907
2908    /**
2909    If `Allocator` implements `owns`, forwards to it. Otherwise, returns
2910    `Ternary.unknown`.
2911    */
2912    override Ternary owns(void[] b)
2913    {
2914        static if (hasMember!(Allocator, "owns")) return impl.owns(b);
2915        else return Ternary.unknown;
2916    }
2917
2918    /// Returns $(D impl.expand(b, s)) if defined, `false` otherwise.
2919    override bool expand(ref void[] b, size_t s)
2920    {
2921        static if (hasMember!(Allocator, "expand"))
2922            return impl.expand(b, s);
2923        else
2924            return s == 0;
2925    }
2926
2927    /// Returns $(D impl.reallocate(b, s)).
2928    override bool reallocate(ref void[] b, size_t s)
2929    {
2930        return impl.reallocate(b, s);
2931    }
2932
2933    /// Forwards to `impl.alignedReallocate` if defined, `false` otherwise.
2934    bool alignedReallocate(ref void[] b, size_t s, uint a)
2935    {
2936        static if (!hasMember!(Allocator, "alignedAllocate"))
2937        {
2938            return false;
2939        }
2940        else
2941        {
2942            return impl.alignedReallocate(b, s, a);
2943        }
2944    }
2945
2946    // Undocumented for now
2947    Ternary resolveInternalPointer(const void* p, ref void[] result)
2948    {
2949        static if (hasMember!(Allocator, "resolveInternalPointer"))
2950        {
2951            return impl.resolveInternalPointer(p, result);
2952        }
2953        else
2954        {
2955            return Ternary.unknown;
2956        }
2957    }
2958
2959    /**
2960    If `impl.deallocate` is not defined, returns `false`. Otherwise it forwards
2961    the call.
2962    */
2963    override bool deallocate(void[] b)
2964    {
2965        static if (hasMember!(Allocator, "deallocate"))
2966        {
2967            return impl.deallocate(b);
2968        }
2969        else
2970        {
2971            return false;
2972        }
2973    }
2974
2975    /**
2976    Calls `impl.deallocateAll()` and returns the result if defined,
2977    otherwise returns `false`.
2978    */
2979    override bool deallocateAll()
2980    {
2981        static if (hasMember!(Allocator, "deallocateAll"))
2982        {
2983            return impl.deallocateAll();
2984        }
2985        else
2986        {
2987            return false;
2988        }
2989    }
2990
2991    /**
2992    Forwards to `impl.empty()` if defined, otherwise returns `Ternary.unknown`.
2993    */
2994    override Ternary empty()
2995    {
2996        static if (hasMember!(Allocator, "empty"))
2997        {
2998            return Ternary(impl.empty);
2999        }
3000        else
3001        {
3002            return Ternary.unknown;
3003        }
3004    }
3005
3006    /**
3007    Returns `impl.allocateAll()` if present, `null` otherwise.
3008    */
3009    override void[] allocateAll()
3010    {
3011        static if (hasMember!(Allocator, "allocateAll"))
3012        {
3013            return impl.allocateAll();
3014        }
3015        else
3016        {
3017            return null;
3018        }
3019    }
3020
3021    @nogc nothrow pure @safe
3022    override void incRef()
3023    {
3024        static if (stateSize!Allocator) ++rc;
3025    }
3026
3027    @nogc nothrow pure @trusted
3028    override bool decRef()
3029    {
3030        static if (stateSize!Allocator)
3031        {
3032            import core.stdc.string : memcpy;
3033
3034            if (rc == 1)
3035            {
3036                static if (indirect)
3037                {
3038                    Allocator* tmp = pimpl;
3039                }
3040                else
3041                {
3042                    Allocator tmp;
3043                    memcpy(&tmp, &this.impl, Allocator.sizeof);
3044                }
3045                void[] support = (cast(void*) this)[0 .. stateSize!(typeof(this))];
3046                tmp.deallocate(support);
3047                return false;
3048            }
3049
3050            --rc;
3051            return true;
3052        }
3053        else
3054        {
3055            return true;
3056        }
3057    }
3058}
3059
3060/**
3061
3062Implementation of `ISharedAllocator` using `Allocator`. This adapts a
3063statically-built, shareable across threads, allocator type to `ISharedAllocator`
3064that is directly usable by non-templated code.
3065
3066Usually `CSharedAllocatorImpl` is used indirectly by calling
3067$(LREF processAllocator).
3068*/
3069class CSharedAllocatorImpl(Allocator, Flag!"indirect" indirect = No.indirect)
3070    : ISharedAllocator
3071{
3072    import std.traits : hasMember;
3073    import core.atomic : atomicOp, atomicLoad;
3074
3075    static if (stateSize!Allocator) shared size_t rc = 1;
3076
3077    /**
3078    The implementation is available as a public member.
3079    */
3080    static if (indirect)
3081    {
3082    nothrow:
3083        private shared Allocator* pimpl;
3084
3085        @nogc pure @safe
3086        ref Allocator impl() shared
3087        {
3088            return *pimpl;
3089        }
3090
3091        @nogc pure @safe
3092        this(Allocator* pa) shared
3093        {
3094            pimpl = pa;
3095        }
3096    }
3097    else
3098    {
3099        static if (stateSize!Allocator) shared Allocator impl;
3100        else alias impl = Allocator.instance;
3101    }
3102
3103nothrow:
3104    /// Returns `impl.alignment`.
3105    override @property uint alignment() shared
3106    {
3107        return impl.alignment;
3108    }
3109
3110    /**
3111    Returns `impl.goodAllocSize(s)`.
3112    */
3113    override size_t goodAllocSize(size_t s) shared
3114    {
3115        return impl.goodAllocSize(s);
3116    }
3117
3118    /**
3119    Returns `impl.allocate(s)`.
3120    */
3121    override void[] allocate(size_t s, TypeInfo ti = null) shared
3122    {
3123        return impl.allocate(s);
3124    }
3125
3126    /**
3127    If `impl.alignedAllocate` exists, calls it and returns the result.
3128    Otherwise, always returns `null`.
3129    */
3130    override void[] alignedAllocate(size_t s, uint a) shared
3131    {
3132        static if (hasMember!(Allocator, "alignedAllocate"))
3133            return impl.alignedAllocate(s, a);
3134        else
3135            return null;
3136    }
3137
3138    /**
3139    If `Allocator` implements `owns`, forwards to it. Otherwise, returns
3140    `Ternary.unknown`.
3141    */
3142    override Ternary owns(void[] b) shared
3143    {
3144        static if (hasMember!(Allocator, "owns")) return impl.owns(b);
3145        else return Ternary.unknown;
3146    }
3147
3148    /// Returns $(D impl.expand(b, s)) if defined, `false` otherwise.
3149    override bool expand(ref void[] b, size_t s) shared
3150    {
3151        static if (hasMember!(Allocator, "expand"))
3152            return impl.expand(b, s);
3153        else
3154            return s == 0;
3155    }
3156
3157    /// Returns $(D impl.reallocate(b, s)).
3158    override bool reallocate(ref void[] b, size_t s) shared
3159    {
3160        return impl.reallocate(b, s);
3161    }
3162
3163    /// Forwards to `impl.alignedReallocate` if defined, `false` otherwise.
3164    bool alignedReallocate(ref void[] b, size_t s, uint a) shared
3165    {
3166        static if (!hasMember!(Allocator, "alignedAllocate"))
3167        {
3168            return false;
3169        }
3170        else
3171        {
3172            return impl.alignedReallocate(b, s, a);
3173        }
3174    }
3175
3176    // Undocumented for now
3177    Ternary resolveInternalPointer(const void* p, ref void[] result) shared
3178    {
3179        static if (hasMember!(Allocator, "resolveInternalPointer"))
3180        {
3181            return impl.resolveInternalPointer(p, result);
3182        }
3183        else
3184        {
3185            return Ternary.unknown;
3186        }
3187    }
3188
3189    /**
3190    If `impl.deallocate` is not defined, returns `false`. Otherwise it forwards
3191    the call.
3192    */
3193    override bool deallocate(void[] b) shared
3194    {
3195        static if (hasMember!(Allocator, "deallocate"))
3196        {
3197            return impl.deallocate(b);
3198        }
3199        else
3200        {
3201            return false;
3202        }
3203    }
3204
3205    /**
3206    Calls `impl.deallocateAll()` and returns the result if defined,
3207    otherwise returns `false`.
3208    */
3209    override bool deallocateAll() shared
3210    {
3211        static if (hasMember!(Allocator, "deallocateAll"))
3212        {
3213            return impl.deallocateAll();
3214        }
3215        else
3216        {
3217            return false;
3218        }
3219    }
3220
3221    /**
3222    Forwards to `impl.empty()` if defined, otherwise returns `Ternary.unknown`.
3223    */
3224    override Ternary empty() shared
3225    {
3226        static if (hasMember!(Allocator, "empty"))
3227        {
3228            return Ternary(impl.empty);
3229        }
3230        else
3231        {
3232            return Ternary.unknown;
3233        }
3234    }
3235
3236    /**
3237    Returns `impl.allocateAll()` if present, `null` otherwise.
3238    */
3239    override void[] allocateAll() shared
3240    {
3241        static if (hasMember!(Allocator, "allocateAll"))
3242        {
3243            return impl.allocateAll();
3244        }
3245        else
3246        {
3247            return null;
3248        }
3249    }
3250
3251    @nogc nothrow pure @safe
3252    override void incRef() shared
3253    {
3254        static if (stateSize!Allocator) atomicOp!"+="(rc, 1);
3255    }
3256
3257    @nogc nothrow pure @trusted
3258    override bool decRef() shared
3259    {
3260        static if (stateSize!Allocator)
3261        {
3262            import core.stdc.string : memcpy;
3263
3264            // rc starts as 1 to avoid comparing with size_t(0) - 1
3265            if (atomicOp!"-="(rc, 1) == 0)
3266            {
3267                static if (indirect)
3268                {
3269                    Allocator* tmp = pimpl;
3270                }
3271                else
3272                {
3273                    Allocator tmp;
3274                    memcpy(cast(void*) &tmp, cast(void*) &this.impl, Allocator.sizeof);
3275                    Allocator empty;
3276                    memcpy(cast(void*) &this.impl, cast(void*) &empty, Allocator.sizeof);
3277                }
3278                void[] support = (cast(void*) this)[0 .. stateSize!(typeof(this))];
3279                (cast(bool delegate(void[]) @nogc nothrow pure)(&tmp.deallocate))(support);
3280                return false;
3281            }
3282            return true;
3283        }
3284        else
3285        {
3286            return true;
3287        }
3288    }
3289}
3290
3291
3292// Example in intro above
3293@system unittest
3294{
3295    // Allocate an int, initialize it with 42
3296    int* p = theAllocator.make!int(42);
3297    assert(*p == 42);
3298
3299    // Destroy and deallocate it
3300    theAllocator.dispose(p);
3301
3302    // Allocate using the global process allocator
3303    p = processAllocator.make!int(100);
3304    assert(*p == 100);
3305
3306    // Destroy and deallocate
3307    processAllocator.dispose(p);
3308
3309    // Create an array of 50 doubles initialized to -1.0
3310    double[] arr = theAllocator.makeArray!double(50, -1.0);
3311
3312    // Check internal pointer
3313    void[] result;
3314    assert(theAllocator.resolveInternalPointer(null, result) == Ternary.no);
3315    Ternary r = theAllocator.resolveInternalPointer(arr.ptr, result);
3316    assert(result.ptr is arr.ptr && result.length >= arr.length);
3317
3318    // Append two zeros to it
3319    theAllocator.expandArray(arr, 2, 0.0);
3320    // On second thought, take that back
3321    theAllocator.shrinkArray(arr, 2);
3322    // Destroy and deallocate
3323    theAllocator.dispose(arr);
3324}
3325
3326/**
3327
3328Stores an allocator object in thread-local storage (i.e. non-`shared` D
3329global). `ThreadLocal!A` is a subtype of `A` so it appears to implement
3330`A`'s allocator primitives.
3331
3332`A` must hold state, otherwise `ThreadLocal!A` refuses instantiation. This
3333means e.g. `ThreadLocal!Mallocator` does not work because `Mallocator`'s
3334state is not stored as members of `Mallocator`, but instead is hidden in the
3335C library implementation.
3336
3337*/
3338struct ThreadLocal(A)
3339{
3340    static assert(stateSize!A,
3341        typeof(A).stringof
3342        ~ " does not have state so it cannot be used with ThreadLocal");
3343
3344    /**
3345    The allocator instance.
3346    */
3347    static A instance;
3348
3349    /**
3350    `ThreadLocal!A` is a subtype of `A` so it appears to implement `A`'s
3351    allocator primitives.
3352    */
3353    alias instance this;
3354
3355    /**
3356    `ThreadLocal` disables all constructors. The intended usage is
3357    `ThreadLocal!A.instance`.
3358    */
3359    @disable this();
3360    /// Ditto
3361    @disable this(this);
3362}
3363
3364///
3365@system
3366unittest
3367{
3368    import std.experimental.allocator.building_blocks.free_list : FreeList;
3369    import std.experimental.allocator.gc_allocator : GCAllocator;
3370    import std.experimental.allocator.mallocator : Mallocator;
3371
3372    static assert(!is(ThreadLocal!Mallocator));
3373    static assert(!is(ThreadLocal!GCAllocator));
3374    alias Allocator = ThreadLocal!(FreeList!(GCAllocator, 0, 8));
3375    auto b = Allocator.instance.allocate(5);
3376    static assert(__traits(hasMember, Allocator, "allocate"));
3377}
3378
3379/*
3380(Not public.)
3381
3382A binary search tree that uses no allocation of its own. Instead, it relies on
3383user code to allocate nodes externally. Then `EmbeddedTree`'s primitives wire
3384the nodes appropriately.
3385
3386Warning: currently `EmbeddedTree` is not using rebalancing, so it may
3387degenerate. A red-black tree implementation storing the color with one of the
3388pointers is planned for the future.
3389*/
3390private struct EmbeddedTree(T, alias less)
3391{
3392    static struct Node
3393    {
3394        T payload;
3395        Node* left, right;
3396    }
3397
3398    private Node* root;
3399
3400    private Node* insert(Node* n, ref Node* backref)
3401    {
3402        backref = n;
3403        n.left = n.right = null;
3404        return n;
3405    }
3406
3407    Node* find(Node* data)
3408    {
3409        for (auto n = root; n; )
3410        {
3411            if (less(data, n))
3412            {
3413                n = n.left;
3414            }
3415            else if (less(n, data))
3416            {
3417                n = n.right;
3418            }
3419            else
3420            {
3421                return n;
3422            }
3423        }
3424        return null;
3425    }
3426
3427    Node* insert(Node* data)
3428    {
3429        if (!root)
3430        {
3431            root = data;
3432            data.left = data.right = null;
3433            return root;
3434        }
3435        auto n = root;
3436        for (;;)
3437        {
3438            if (less(data, n))
3439            {
3440                if (!n.left)
3441                {
3442                    // Found insertion point
3443                    return insert(data, n.left);
3444                }
3445                n = n.left;
3446            }
3447            else if (less(n, data))
3448            {
3449                if (!n.right)
3450                {
3451                    // Found insertion point
3452                    return insert(data, n.right);
3453                }
3454                n = n.right;
3455            }
3456            else
3457            {
3458                // Found
3459                return n;
3460            }
3461            if (!n) return null;
3462        }
3463    }
3464
3465    Node* remove(Node* data)
3466    {
3467        auto n = root;
3468        Node* parent = null;
3469        for (;;)
3470        {
3471            if (!n) return null;
3472            if (less(data, n))
3473            {
3474                parent = n;
3475                n = n.left;
3476            }
3477            else if (less(n, data))
3478            {
3479                parent = n;
3480                n = n.right;
3481            }
3482            else
3483            {
3484                // Found
3485                remove(n, parent);
3486                return n;
3487            }
3488        }
3489    }
3490
3491    private void remove(Node* n, Node* parent)
3492    {
3493        assert(n);
3494        assert(!parent || parent.left == n || parent.right == n);
3495        Node** referrer = parent
3496            ? (parent.left == n ? &parent.left : &parent.right)
3497            : &root;
3498        if (!n.left)
3499        {
3500            *referrer = n.right;
3501        }
3502        else if (!n.right)
3503        {
3504            *referrer = n.left;
3505        }
3506        else
3507        {
3508            // Find the leftmost child in the right subtree
3509            auto leftmost = n.right;
3510            Node** leftmostReferrer = &n.right;
3511            while (leftmost.left)
3512            {
3513                leftmostReferrer = &leftmost.left;
3514                leftmost = leftmost.left;
3515            }
3516            // Unlink leftmost from there
3517            *leftmostReferrer = leftmost.right;
3518            // Link leftmost in lieu of n
3519            leftmost.left = n.left;
3520            leftmost.right = n.right;
3521            *referrer = leftmost;
3522        }
3523    }
3524
3525    Ternary empty() const
3526    {
3527        return Ternary(!root);
3528    }
3529
3530    void dump()
3531    {
3532        import std.stdio : writeln;
3533        writeln(typeid(this), " @ ", cast(void*) &this);
3534        dump(root, 3);
3535    }
3536
3537    void dump(Node* r, uint indent)
3538    {
3539        import std.stdio : write, writeln;
3540        import std.range : repeat;
3541        import std.array : array;
3542
3543        write(repeat(' ', indent).array);
3544        if (!r)
3545        {
3546            writeln("(null)");
3547            return;
3548        }
3549        writeln(r.payload, " @ ", cast(void*) r);
3550        dump(r.left, indent + 3);
3551        dump(r.right, indent + 3);
3552    }
3553
3554    void assertSane()
3555    {
3556        static bool isBST(Node* r, Node* lb, Node* ub)
3557        {
3558            if (!r) return true;
3559            if (lb && !less(lb, r)) return false;
3560            if (ub && !less(r, ub)) return false;
3561            return isBST(r.left, lb, r) &&
3562                isBST(r.right, r, ub);
3563        }
3564        if (isBST(root, null, null)) return;
3565        dump;
3566        assert(0);
3567    }
3568}
3569
3570@system
3571unittest
3572{
3573    import std.experimental.allocator.gc_allocator : GCAllocator;
3574
3575    alias a = GCAllocator.instance;
3576    alias Tree = EmbeddedTree!(int, (a, b) => a.payload < b.payload);
3577    Tree t;
3578    assert(t.empty == Ternary.yes);
3579    int[] vals = [ 6, 3, 9, 1, 0, 2, 8, 11 ];
3580    foreach (v; vals)
3581    {
3582        auto n = new Tree.Node(v, null, null);
3583        assert(t.insert(n));
3584        assert(n);
3585        t.assertSane;
3586    }
3587    assert(t.empty != Ternary.yes);
3588    foreach (v; vals)
3589    {
3590        Tree.Node n = { v };
3591        assert(t.remove(&n));
3592        t.assertSane;
3593    }
3594    assert(t.empty == Ternary.yes);
3595}
3596
3597/*
3598
3599`InternalPointersTree` adds a primitive on top of another allocator: calling
3600`resolveInternalPointer(p)` returns the block within which the internal
3601pointer `p` lies. Pointers right after the end of allocated blocks are also
3602considered internal.
3603
3604The implementation stores three additional words with each allocation (one for
3605the block size and two for search management).
3606
3607*/
3608private struct InternalPointersTree(Allocator)
3609{
3610    import std.experimental.allocator.building_blocks.affix_allocator : AffixAllocator;
3611
3612    alias Tree = EmbeddedTree!(size_t,
3613        (a, b) => cast(void*) a + a.payload < cast(void*) b);
3614    alias Parent = AffixAllocator!(Allocator, Tree.Node);
3615
3616    // Own state
3617    private Tree blockMap;
3618
3619    alias alignment = Parent.alignment;
3620
3621    /**
3622    The implementation is available as a public member.
3623    */
3624    static if (stateSize!Parent) Parent parent;
3625    else alias parent = Parent.instance;
3626
3627    /// Allocator API.
3628    void[] allocate(size_t bytes)
3629    {
3630        auto r = parent.allocate(bytes);
3631        if (!r.ptr) return r;
3632        Tree.Node* n = &parent.prefix(r);
3633        n.payload = bytes;
3634        blockMap.insert(n) || assert(0);
3635        return r;
3636    }
3637
3638    /// Ditto
3639    bool deallocate(void[] b)
3640    {
3641        if (!b.ptr) return true;
3642        Tree.Node* n = &parent.prefix(b);
3643        blockMap.remove(n) || assert(false);
3644        parent.deallocate(b);
3645        return true;
3646    }
3647
3648    /// Ditto
3649    static if (hasMember!(Allocator, "reallocate"))
3650    bool reallocate(ref void[] b, size_t s)
3651    {
3652        auto n = &parent.prefix(b);
3653        assert(n.payload == b.length);
3654        blockMap.remove(n) || assert(0);
3655        if (!parent.reallocate(b, s))
3656        {
3657            // Failed, must reinsert the same node in the tree
3658            assert(n.payload == b.length);
3659            blockMap.insert(n) || assert(0);
3660            return false;
3661        }
3662        // Insert the new node
3663        n = &parent.prefix(b);
3664        n.payload = s;
3665        blockMap.insert(n) || assert(0);
3666        return true;
3667    }
3668
3669    /// Ditto
3670    Ternary owns(void[] b)
3671    {
3672        void[] result;
3673        return resolveInternalPointer(b.ptr, result);
3674    }
3675
3676    /// Ditto
3677    Ternary empty()
3678    {
3679        return Ternary(blockMap.empty);
3680    }
3681
3682    /** Returns the block inside which `p` resides, or `null` if the
3683    pointer does not belong.
3684    */
3685    pure nothrow @safe @nogc
3686    Ternary resolveInternalPointer(const void* p, ref void[] result)
3687    {
3688        // Must define a custom find
3689        Tree.Node* find()
3690        {
3691            for (auto n = blockMap.root; n; )
3692            {
3693                if (p < n)
3694                {
3695                    n = n.left;
3696                }
3697                else if ((() @trusted => p > (cast(void*) (n + 1)) + n.payload)())
3698                {
3699                    n = n.right;
3700                }
3701                else
3702                {
3703                    return n;
3704                }
3705            }
3706            return null;
3707        }
3708
3709        auto n = find();
3710        if (!n) return Ternary.no;
3711        result = (() @trusted => (cast(void*) (n + 1))[0 .. n.payload])();
3712        return Ternary.yes;
3713    }
3714}
3715
3716@system
3717unittest
3718{
3719    import std.experimental.allocator.mallocator : Mallocator;
3720    import std.random : randomCover;
3721
3722    InternalPointersTree!(Mallocator) a;
3723    int[] vals = [ 6, 3, 9, 1, 2, 8, 11 ];
3724    void[][] allox;
3725    foreach (v; vals)
3726    {
3727        allox ~= a.allocate(v);
3728    }
3729    a.blockMap.assertSane;
3730
3731    foreach (b; allox)
3732    {
3733        () pure nothrow @safe {
3734            void[] p;
3735            Ternary r = (() @nogc => a.resolveInternalPointer(&b[0], p))();
3736            assert(&p[0] == &b[0] && p.length >= b.length);
3737            r = a.resolveInternalPointer((() @trusted => &b[0] + b.length)(), p);
3738
3739            /* This line randomly fails on MacOS 12.x x64
3740             * https://issues.dlang.org/show_bug.cgi?id=22660
3741             * Commenting it out until someone can fix it.
3742             */
3743            //assert(&p[0] == &b[0] && p.length >= b.length);
3744
3745            r = a.resolveInternalPointer((() @trusted => &b[0] + b.length / 2)(), p);
3746            assert(&p[0] == &b[0] && p.length >= b.length);
3747            auto bogus = new void[b.length];
3748            assert(a.resolveInternalPointer(&bogus[0], p) == Ternary.no);
3749        }();
3750    }
3751
3752    foreach (b; allox.randomCover)
3753    {
3754        () nothrow @nogc { a.deallocate(b); }();
3755    }
3756
3757    assert(a.empty == Ternary.yes);
3758}
3759
3760//version (std_allocator_benchmark)
3761@system
3762unittest
3763{
3764    import std.experimental.allocator.building_blocks.null_allocator : NullAllocator;
3765    import std.experimental.allocator.building_blocks.allocator_list : AllocatorList;
3766    import std.experimental.allocator.building_blocks.bitmapped_block : BitmappedBlock;
3767    import std.experimental.allocator.building_blocks.segregator : Segregator;
3768    import std.experimental.allocator.building_blocks.bucketizer : Bucketizer;
3769    import std.experimental.allocator.building_blocks.free_list : FreeList;
3770    import std.experimental.allocator.gc_allocator : GCAllocator;
3771    import std.experimental.allocator.mallocator : Mallocator;
3772
3773    static void testSpeed(A)()
3774    {
3775        static if (stateSize!A) A a;
3776        else alias a = A.instance;
3777
3778        void[][128] bufs;
3779
3780        import std.random;
3781        foreach (i; 0 .. 100_000)
3782        {
3783            auto j = uniform(0, bufs.length);
3784            switch (uniform(0, 2))
3785            {
3786            case 0:
3787                () nothrow @nogc { a.deallocate(bufs[j]); }();
3788                bufs[j] = a.allocate(uniform(0, 4096));
3789                break;
3790            case 1:
3791                () nothrow @nogc { a.deallocate(bufs[j]); }();
3792                bufs[j] = null;
3793                break;
3794            default:
3795                assert(0);
3796            }
3797        }
3798    }
3799
3800    import std.algorithm.comparison : max;
3801
3802    alias FList = FreeList!(GCAllocator, 0, unbounded);
3803    alias A = Segregator!(
3804        8, FreeList!(GCAllocator, 0, 8),
3805        128, Bucketizer!(FList, 1, 128, 16),
3806        256, Bucketizer!(FList, 129, 256, 32),
3807        512, Bucketizer!(FList, 257, 512, 64),
3808        1024, Bucketizer!(FList, 513, 1024, 128),
3809        2048, Bucketizer!(FList, 1025, 2048, 256),
3810        3584, Bucketizer!(FList, 2049, 3584, 512),
3811        4072 * 1024, AllocatorList!(
3812            (size_t n) => BitmappedBlock!(4096)(cast(ubyte[]) GCAllocator.instance.allocate(
3813                max(n, 4072 * 1024)))),
3814        GCAllocator
3815    );
3816
3817    import std.stdio;
3818    import std.conv : to;
3819    import std.datetime.stopwatch;
3820    import std.algorithm.iteration : map;
3821
3822    if (false) writeln(benchmark!(
3823        testSpeed!NullAllocator,
3824        testSpeed!Mallocator,
3825        testSpeed!GCAllocator,
3826        testSpeed!(ThreadLocal!A),
3827        testSpeed!(A),
3828    )(20)[].map!(t => t.to!Duration));
3829}
3830
3831@system
3832unittest
3833{
3834    import std.experimental.allocator.building_blocks.free_list : FreeList;
3835    import std.experimental.allocator.building_blocks.region : InSituRegion;
3836    import std.experimental.allocator.building_blocks.fallback_allocator : FallbackAllocator;
3837    import std.experimental.allocator.gc_allocator : GCAllocator;
3838    import std.experimental.allocator.mallocator : Mallocator;
3839
3840    auto a = allocatorObject(Mallocator.instance);
3841    auto b = a.allocate(100);
3842    assert(b.length == 100);
3843
3844    FreeList!(GCAllocator, 0, 8) fl;
3845    auto sa = allocatorObject(fl);
3846    b = a.allocate(101);
3847    assert(b.length == 101);
3848
3849    FallbackAllocator!(InSituRegion!(10240, 64), GCAllocator) fb;
3850    // Doesn't work yet...
3851    //a = allocatorObject(fb);
3852    //b = a.allocate(102);
3853    //assert(b.length == 102);
3854}
3855
3856///
3857@system
3858unittest
3859{
3860    import std.experimental.allocator.building_blocks.allocator_list : AllocatorList;
3861    import std.experimental.allocator.building_blocks.bitmapped_block : BitmappedBlock;
3862    import std.experimental.allocator.building_blocks.segregator : Segregator;
3863    import std.experimental.allocator.building_blocks.bucketizer : Bucketizer;
3864    import std.experimental.allocator.building_blocks.free_list : FreeList;
3865    import std.experimental.allocator.gc_allocator : GCAllocator;
3866
3867    /// Define an allocator bound to the built-in GC.
3868    auto alloc = allocatorObject(GCAllocator.instance);
3869    auto b = alloc.allocate(42);
3870    assert(b.length == 42);
3871    assert(alloc.deallocate(b));
3872
3873    import std.algorithm.comparison : max;
3874    // Define an elaborate allocator and bind it to the class API.
3875    alias FList = FreeList!(GCAllocator, 0, unbounded);
3876    alias A = ThreadLocal!(
3877        Segregator!(
3878            8, FreeList!(GCAllocator, 0, 8),
3879            128, Bucketizer!(FList, 1, 128, 16),
3880            256, Bucketizer!(FList, 129, 256, 32),
3881            512, Bucketizer!(FList, 257, 512, 64),
3882            1024, Bucketizer!(FList, 513, 1024, 128),
3883            2048, Bucketizer!(FList, 1025, 2048, 256),
3884            3584, Bucketizer!(FList, 2049, 3584, 512),
3885            4072 * 1024, AllocatorList!(
3886                (n) => BitmappedBlock!(4096)(cast(ubyte[]) GCAllocator.instance.allocate(
3887                    max(n, 4072 * 1024)))),
3888            GCAllocator
3889        )
3890    );
3891
3892    auto alloc2 = allocatorObject(A.instance);
3893    b = alloc2.allocate(101);
3894    assert(alloc2.deallocate(b));
3895}
3896