diff --git a/std/experimental/allocator/fallback_allocator.d b/std/experimental/allocator/fallback_allocator.d index 9d875dc93..f5ff230c0 100644 --- a/std/experimental/allocator/fallback_allocator.d +++ b/std/experimental/allocator/fallback_allocator.d @@ -305,6 +305,51 @@ unittest a.deallocate(b2); } +/* +Forwards an argument from one function to another +*/ +private auto ref forward(alias arg)() +{ + static if (__traits(isRef, arg)) + { + return arg; + } + else + { + import std.algorithm : move; + return move(arg); + } +} + +unittest +{ + void fun(T)(auto ref T a, string b) { /* ... */ } + void gun(T...)(auto ref T args) + { + fun(forward!(args[0]), forward!(args[1])); + } + gun(42, "hello"); + int x; + gun(x, "hello"); +} + +unittest +{ + static void checkByRef(T)(auto ref T value) + { + static assert(__traits(isRef, value)); + } + + static void checkByVal(T)(auto ref T value) + { + static assert(!__traits(isRef, value)); + } + + static void test1(ref int a) { checkByRef(forward!a); } + static void test2(int a) { checkByVal(forward!a); } + static void test3() { int a; checkByVal(forward!a); } +} + /** Convenience function that uses type deduction to return the appropriate $(D FallbackAllocator) instance. To initialize with allocators that don't have @@ -313,16 +358,19 @@ state, use their $(D it) static member. FallbackAllocator!(Primary, Fallback) fallbackAllocator(Primary, Fallback)(auto ref Primary p, auto ref Fallback f) { + alias R = FallbackAllocator!(Primary, Fallback); + import std.algorithm : move; + static if (stateSize!Primary) static if (stateSize!Fallback) - return typeof(return)(p, f); + return R(forward!p, forward!f); else - return typeof(return)(p); + return R(forward!p); else static if (stateSize!Fallback) - return typeof(return)(f); + return R(forward!f); else - return typeof(return)(); + return R(); } /// diff --git a/std/experimental/allocator/kernighan_ritchie.d b/std/experimental/allocator/kernighan_ritchie.d index 4cc5b0a7e..5f0e7e503 100644 --- a/std/experimental/allocator/kernighan_ritchie.d +++ b/std/experimental/allocator/kernighan_ritchie.d @@ -13,6 +13,9 @@ famed allocator) described by Brian Kernighan and Dennis Ritchie in section 8.7 of the book $(WEB amazon.com/exec/obidos/ASIN/0131103628/classicempire, "The C Programming Language"), Second Edition, Prentice Hall, 1988. +The recommended usage for $(D KRBlock) is as a simple means to add +$(D deallocate) to a region. + A $(D KRBlock) manages a single contiguous chunk of memory by embedding a free blocks list onto it. It is a very simple allocator with good memory utilization. $(D KRBlock) has a small control structure and no per-allocation overhead. Its @@ -75,7 +78,6 @@ copyable. */ struct KRBlock(ParentAllocator = NullAllocator) { - import std.format : format; import std.experimental.allocator.common : stateSize, alignedAt; private static struct Node @@ -148,6 +150,7 @@ struct KRBlock(ParentAllocator = NullAllocator) string toString() { + import std.format : format; string s = "KRBlock@"; s ~= format("%s-%s(0x%s[%s]", &this, &this + 1, payload.ptr, payload.length); @@ -234,7 +237,6 @@ struct KRBlock(ParentAllocator = NullAllocator) /* Noncopyable */ - static if (!is(ParentAllocator == NullAllocator)) @disable this(this); /** @@ -290,11 +292,11 @@ struct KRBlock(ParentAllocator = NullAllocator) { debug(KRBlock) writefln("KRBlock@%s: deallocate(%s[%s])", &this, b.ptr, b.length); - // Insert back in the freelist, keeping it sorted by address. Do not - // coalesce at this time. Instead, do it lazily during allocation. if (!b.ptr) return; assert(owns(b)); assert(b.ptr.alignedAt(Node.alignof)); + // Insert back in the freelist, keeping it sorted by address. Do not + // coalesce at this time. Instead, do it lazily during allocation. auto n = cast(Node*) b.ptr; n.size = goodAllocSize(b.length); // Linear search