mirror of
https://github.com/dlang/phobos.git
synced 2025-04-30 07:00:37 +03:00
Improvements and fixes in affix_allocator; fix in isPowerOf2; fix alignment in scoped_allocator
This commit is contained in:
parent
c175553098
commit
c00b5885c1
3 changed files with 42 additions and 18 deletions
|
@ -19,6 +19,7 @@ The following methods are defined if $(D Allocator) defines them, and forward to
|
||||||
struct AffixAllocator(Allocator, Prefix, Suffix = void)
|
struct AffixAllocator(Allocator, Prefix, Suffix = void)
|
||||||
{
|
{
|
||||||
import std.conv, std.experimental.allocator.common, std.traits;
|
import std.conv, std.experimental.allocator.common, std.traits;
|
||||||
|
import std.algorithm : min;
|
||||||
|
|
||||||
static assert(
|
static assert(
|
||||||
!stateSize!Prefix || Allocator.alignment >= Prefix.alignof,
|
!stateSize!Prefix || Allocator.alignment >= Prefix.alignof,
|
||||||
|
@ -30,8 +31,9 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
|
||||||
/**
|
/**
|
||||||
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.
|
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.
|
||||||
*/
|
*/
|
||||||
enum uint alignment =
|
enum uint alignment = isPowerOf2(stateSize!Prefix)
|
||||||
stateSize!Prefix ? Prefix.alignof : Allocator.alignment;
|
? min(stateSize!Prefix, Allocator.alignment)
|
||||||
|
: (stateSize!Prefix ? Prefix.alignof : Allocator.alignment);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
If the parent allocator $(D Allocator) is stateful, an instance of it is
|
If the parent allocator $(D Allocator) is stateful, an instance of it is
|
||||||
|
@ -46,11 +48,15 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
|
||||||
{
|
{
|
||||||
size_t goodAllocSize(size_t s)
|
size_t goodAllocSize(size_t s)
|
||||||
{
|
{
|
||||||
return parent.goodAllocSize(actualAllocationSize(s));
|
auto a = actualAllocationSize(s);
|
||||||
|
return roundUpToMultipleOf(parent.goodAllocSize(a)
|
||||||
|
- stateSize!Prefix - stateSize!Suffix,
|
||||||
|
this.alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
private size_t actualAllocationSize(size_t s) const
|
private size_t actualAllocationSize(size_t s) const
|
||||||
{
|
{
|
||||||
|
assert(s > 0);
|
||||||
static if (!stateSize!Suffix)
|
static if (!stateSize!Suffix)
|
||||||
{
|
{
|
||||||
return s + stateSize!Prefix;
|
return s + stateSize!Prefix;
|
||||||
|
@ -76,10 +82,16 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
|
||||||
auto result = parent.allocate(actualAllocationSize(bytes));
|
auto result = parent.allocate(actualAllocationSize(bytes));
|
||||||
if (result is null) return null;
|
if (result is null) return null;
|
||||||
static if (stateSize!Prefix)
|
static if (stateSize!Prefix)
|
||||||
|
{
|
||||||
|
assert(result.ptr.alignedAt(Prefix.alignof));
|
||||||
emplace!Prefix(cast(Prefix*)result.ptr);
|
emplace!Prefix(cast(Prefix*)result.ptr);
|
||||||
|
}
|
||||||
static if (stateSize!Suffix)
|
static if (stateSize!Suffix)
|
||||||
emplace!Suffix(
|
{
|
||||||
cast(Suffix*)(result.ptr + result.length - Suffix.sizeof));
|
auto suffixP = result.ptr + result.length - Suffix.sizeof;
|
||||||
|
assert(suffixP.alignedAt(Suffix.alignof));
|
||||||
|
emplace!Suffix(cast(Suffix*)(suffixP));
|
||||||
|
}
|
||||||
return result[stateSize!Prefix .. stateSize!Prefix + bytes];
|
return result[stateSize!Prefix .. stateSize!Prefix + bytes];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,20 +100,24 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
|
||||||
{
|
{
|
||||||
auto result = parent.allocateAll();
|
auto result = parent.allocateAll();
|
||||||
if (result is null) return null;
|
if (result is null) return null;
|
||||||
|
if (result.length < actualAllocationSize(1))
|
||||||
|
{
|
||||||
|
deallocate(result);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
static if (stateSize!Prefix)
|
static if (stateSize!Prefix)
|
||||||
{
|
{
|
||||||
assert(result.length > stateSize!Prefix);
|
assert(result.length > stateSize!Prefix);
|
||||||
if (result.length <= stateSize!Prefix) return null;
|
|
||||||
emplace!Prefix(cast(Prefix*)result.ptr);
|
emplace!Prefix(cast(Prefix*)result.ptr);
|
||||||
result = result[stateSize!Prefix .. $];
|
result = result[stateSize!Prefix .. $];
|
||||||
}
|
}
|
||||||
static if (stateSize!Suffix)
|
static if (stateSize!Suffix)
|
||||||
{
|
{
|
||||||
|
assert(result.length > stateSize!Suffix);
|
||||||
// Ehm, find a properly aligned place for the suffix
|
// Ehm, find a properly aligned place for the suffix
|
||||||
auto p = (result.ptr + result.length - stateSize!Suffix)
|
auto p = (result.ptr + result.length - stateSize!Suffix)
|
||||||
.alignDownTo(Suffix.alignof);
|
.alignDownTo(Suffix.alignof);
|
||||||
assert(p > result.ptr);
|
assert(p > result.ptr);
|
||||||
if (p <= result.ptr) return null;
|
|
||||||
emplace!Suffix(cast(Suffix*) p);
|
emplace!Suffix(cast(Suffix*) p);
|
||||||
result = result[0 .. p - result.ptr];
|
result = result[0 .. p - result.ptr];
|
||||||
}
|
}
|
||||||
|
@ -130,7 +146,7 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
|
||||||
{
|
{
|
||||||
if (!b.ptr)
|
if (!b.ptr)
|
||||||
{
|
{
|
||||||
if (delta) b = allocate(delta);
|
b = allocate(delta);
|
||||||
return b.length == delta;
|
return b.length == delta;
|
||||||
}
|
}
|
||||||
auto t = actualAllocation(b);
|
auto t = actualAllocation(b);
|
||||||
|
@ -158,8 +174,7 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
|
||||||
static if (hasMember!(Allocator, "deallocate"))
|
static if (hasMember!(Allocator, "deallocate"))
|
||||||
void deallocate(void[] b)
|
void deallocate(void[] b)
|
||||||
{
|
{
|
||||||
auto p = b.ptr - stateSize!Prefix;
|
if (b.ptr) parent.deallocate(actualAllocation(b));
|
||||||
parent.deallocate(p[0 .. actualAllocationSize(b.length)]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The following methods are defined if $(D ParentAllocator) defines
|
/* The following methods are defined if $(D ParentAllocator) defines
|
||||||
|
@ -174,13 +189,16 @@ struct AffixAllocator(Allocator, Prefix, Suffix = void)
|
||||||
static if (stateSize!Prefix)
|
static if (stateSize!Prefix)
|
||||||
static ref Prefix prefix(void[] b)
|
static ref Prefix prefix(void[] b)
|
||||||
{
|
{
|
||||||
|
assert(b.ptr && b.ptr.alignedAt(Prefix.alignof));
|
||||||
return (cast(Prefix*)b.ptr)[-1];
|
return (cast(Prefix*)b.ptr)[-1];
|
||||||
}
|
}
|
||||||
static if (stateSize!Suffix)
|
static if (stateSize!Suffix)
|
||||||
ref Suffix suffix(void[] b)
|
ref Suffix suffix(void[] b)
|
||||||
{
|
{
|
||||||
|
assert(b.ptr);
|
||||||
auto p = b.ptr - stateSize!Prefix
|
auto p = b.ptr - stateSize!Prefix
|
||||||
+ actualAllocationSize(b.length);
|
+ actualAllocationSize(b.length);
|
||||||
|
assert(p && p.alignedAt(Suffix.alignof));
|
||||||
return (cast(Suffix*) p)[-1];
|
return (cast(Suffix*) p)[-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,14 +290,11 @@ unittest
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
import std.experimental.allocator.mallocator;
|
|
||||||
import std.experimental.allocator.heap_block;
|
import std.experimental.allocator.heap_block;
|
||||||
import std.experimental.allocator.common;
|
import std.experimental.allocator.common;
|
||||||
//testAllocator!(() => AffixAllocator!(Mallocator, size_t, size_t).it);
|
|
||||||
testAllocator!({
|
testAllocator!({
|
||||||
auto hb = HeapBlock!128(new void[128 * 4096]);
|
auto a = AffixAllocator!(HeapBlock!128, ulong, ulong)
|
||||||
AffixAllocator!(HeapBlock!128, size_t, size_t) a;
|
(HeapBlock!128(new void[128 * 4096]));
|
||||||
a.parent = hb;
|
|
||||||
return a;
|
return a;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,7 +324,12 @@ void* alignUpTo(void* ptr, uint alignment)
|
||||||
|
|
||||||
package bool isPowerOf2(uint x)
|
package bool isPowerOf2(uint x)
|
||||||
{
|
{
|
||||||
return (x & (x - 1)) == 0;
|
return (x & (x - 1)) == 0 && x;
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
assert(!isPowerOf2(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
package bool isGoodStaticAlignment(uint x)
|
package bool isGoodStaticAlignment(uint x)
|
||||||
|
@ -422,14 +427,18 @@ package string forwardToMember(string member, string[] funs...)
|
||||||
package void testAllocator(alias make)()
|
package void testAllocator(alias make)()
|
||||||
{
|
{
|
||||||
import std.conv : text;
|
import std.conv : text;
|
||||||
|
import std.stdio : writeln, stderr;
|
||||||
alias A = typeof(make());
|
alias A = typeof(make());
|
||||||
|
scope(failure) stderr.writeln("testAllocator failed for ", A.stringof);
|
||||||
|
|
||||||
auto a = make();
|
auto a = make();
|
||||||
|
|
||||||
// Test alignment
|
// Test alignment
|
||||||
static assert(A.alignment.isPowerOf2);
|
static assert(A.alignment.isPowerOf2);
|
||||||
|
|
||||||
// Test goodAllocSize
|
// Test goodAllocSize
|
||||||
assert(a.goodAllocSize(1) >= A.alignment);
|
assert(a.goodAllocSize(1) >= A.alignment,
|
||||||
|
text(a.goodAllocSize(1), " < ", A.alignment));
|
||||||
assert(a.goodAllocSize(11) >= 11.roundUpToMultipleOf(A.alignment));
|
assert(a.goodAllocSize(11) >= 11.roundUpToMultipleOf(A.alignment));
|
||||||
assert(a.goodAllocSize(111) >= 111.roundUpToMultipleOf(A.alignment));
|
assert(a.goodAllocSize(111) >= 111.roundUpToMultipleOf(A.alignment));
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ struct ScopedAllocator(ParentAllocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alignment offered
|
/// Alignment offered
|
||||||
enum alignment = ParentAllocator.alignment;
|
enum alignment = Allocator.alignment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Forwards to $(D parent.goodAllocSize) (which accounts for the management
|
Forwards to $(D parent.goodAllocSize) (which accounts for the management
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue