@@ -18,13 +18,15 @@ Suffixes are slower to get at because of alignment rounding, so prefixes should
1818be preferred. However, small prefixes blunt the alignment so if a large
1919alignment with a small affix is needed, suffixes should be chosen.
2020
21- The following methods are defined if $(D Allocator) defines them, and forward to it: $(D deallocateAll), $(D empty), $(D owns).
21+ The following methods are defined if $(D Allocator) defines them,
22+ and forwards to it: $(D deallocateAll), $(D empty), $(D owns).
2223 */
2324struct AffixAllocator (Allocator, Prefix, Suffix = void )
2425{
2526 import std.algorithm.comparison : min;
2627 import std.conv : emplace;
27- import std.experimental.allocator : RCIAllocator, theAllocator;
28+ import std.experimental.allocator : RCIAllocator, RCISharedAllocator,
29+ theAllocator, processAllocator;
2830 import std.experimental.allocator.common : stateSize, forwardToMember,
2931 roundUpToMultipleOf, alignedAt, alignDownTo, roundUpToMultipleOf,
3032 hasStaticallyKnownAlignment;
@@ -43,7 +45,8 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
4345 " This restriction could be relaxed in the future." );
4446
4547 /**
46- If $(D Prefix) is $(D void), the alignment is that of the parent. Otherwise, the alignment is the same as the $(D Prefix)'s alignment.
48+ If $(D Prefix) is $(D void), the alignment is that of the parent.
49+ Otherwise, the alignment is the same as the $(D Prefix)'s alignment.
4750 */
4851 static if (hasStaticallyKnownAlignment! Allocator)
4952 {
@@ -60,36 +63,39 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
6063 enum uint alignment = Prefix.alignof;
6164 }
6265
63- /**
64- If the parent allocator $(D Allocator) is stateful, an instance of it is
65- stored as a member. Otherwise, $(D AffixAllocator) uses
66- `Allocator.instance`. In either case, the name $(D _parent) is uniformly
67- used for accessing the parent allocator.
68- */
69- static if (stateSize! Allocator)
66+ private template Impl ()
7067 {
71- Allocator _parent;
72- static if (is (Allocator == RCIAllocator))
68+ static if (stateSize! Allocator)
7369 {
74- Allocator parent ()
70+ Allocator _parent;
71+ static if (is (Allocator == RCIAllocator) || is (Allocator == RCISharedAllocator))
7572 {
76- if (_parent.isNull) _parent = theAllocator;
77- assert (alignment <= _parent.alignment);
78- return _parent;
73+ Allocator parent ()
74+ {
75+ if (_parent.isNull)
76+ {
77+ static if (is (Allocator == RCIAllocator))
78+ {
79+ _parent = theAllocator;
80+ }
81+ else
82+ {
83+ _parent = processAllocator;
84+ }
85+ }
86+ assert (alignment <= _parent.alignment);
87+ return _parent;
88+ }
89+ }
90+ else
91+ {
92+ alias parent = _parent;
7993 }
8094 }
8195 else
8296 {
83- alias parent = _parent ;
97+ alias parent = Allocator.instance ;
8498 }
85- }
86- else
87- {
88- alias parent = Allocator.instance;
89- }
90-
91- private template Impl ()
92- {
9399
94100 size_t goodAllocSize (size_t s)
95101 {
@@ -298,6 +304,20 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
298304 */
299305 static AffixAllocator instance;
300306
307+ /**
308+ If the parent allocator `Allocator` is stateful, an instance of it is
309+ stored as a member. If the parent allocator is null instance of
310+ $(REF RCIAllocator, std,experimental,allocator) or
311+ $(REF RCISharedAllocator, std,experimental,allocator) then `AffixAllocator`
312+ will use $(REF theAllocator, std,experimental,allocator) or
313+ $(REF processAllocator, std,experimental,allocator) respectively.
314+ If the parent allocator `Allocator` is stateless, `AffixAllocator` uses
315+ `Allocator.instance`.
316+ In either case, the name `_parent` is uniformly used for accessing the
317+ parent allocator.
318+ */
319+ Allocator parent ();
320+
301321 /**
302322 Affix access functions offering references to the affixes of a
303323 block `b` previously allocated with this allocator. `b` may not be null.
@@ -520,3 +540,30 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
520540 static assert (is (typeof (a.allocate) == shared ));
521541 assert (buf.length == 10 );
522542}
543+
544+ @system unittest
545+ {
546+ import std.experimental.allocator : RCISharedAllocator;
547+
548+ shared AffixAllocator! (RCISharedAllocator, uint ) a;
549+ auto buf = a.allocate(42 );
550+ assert (buf.length == 42 );
551+ }
552+
553+ @system unittest
554+ {
555+ import std.experimental.allocator.mallocator : Mallocator;
556+ import std.experimental.allocator.building_blocks.stats_collector ;
557+
558+ alias SCAlloc = StatsCollector! (Mallocator, Options.bytesUsed);
559+ alias AffixAl = AffixAllocator! (SCAlloc, uint );
560+
561+ AffixAl a;
562+ auto b = a.allocate(42 );
563+ assert (b.length == 42 );
564+ assert (a.parent.bytesUsed == 42 + uint .sizeof);
565+ assert ((() nothrow @nogc => a.reallocate(b, 100 ))());
566+ assert (b.length == 100 );
567+ assert (a.parent.bytesUsed == 100 + uint .sizeof);
568+ assert ((() nothrow @nogc => a.deallocate(b))());
569+ }
0 commit comments