Skip to content

Commit

Permalink
std.typecons: Greatly simplify scoped()
Browse files Browse the repository at this point in the history
  • Loading branch information
kinke committed May 13, 2022
1 parent a37fd5f commit 0d49960
Showing 1 changed file with 5 additions and 32 deletions.
37 changes: 5 additions & 32 deletions std/typecons.d
Original file line number Diff line number Diff line change
Expand Up @@ -8265,29 +8265,14 @@ are no pointers to it. As such, it is illegal to move a scoped object.
template scoped(T)
if (is(T == class))
{
// _d_newclass now use default GC alignment (looks like (void*).sizeof * 2 for
// small objects). We will just use the maximum of filed alignments.
alias alignment = classInstanceAlignment!T;
alias aligned = _alignUp!alignment;

static struct Scoped
{
// Addition of `alignment` is required as `Scoped_store` can be misaligned in memory.
private void[aligned(__traits(classInstanceSize, T) + size_t.sizeof) + alignment] Scoped_store = void;
private align(__traits(classInstanceAlignment, T))
void[__traits(classInstanceSize, T)] buffer = void;

@property inout(T) Scoped_payload() inout
{
void* alignedStore = cast(void*) aligned(cast(size_t) Scoped_store.ptr);
// As `Scoped` can be unaligned moved in memory class instance should be moved accordingly.
immutable size_t d = alignedStore - Scoped_store.ptr;
size_t* currD = cast(size_t*) &Scoped_store[$ - size_t.sizeof];
if (d != *currD)
{
import core.stdc.string : memmove;
memmove(alignedStore, Scoped_store.ptr + *currD, __traits(classInstanceSize, T));
*currD = d;
}
return cast(inout(T)) alignedStore;
return cast(inout(T)) buffer.ptr;
}
alias Scoped_payload this;

Expand All @@ -8296,9 +8281,7 @@ if (is(T == class))

~this()
{
// `destroy` will also write .init but we have no functions in druntime
// for deterministic finalization and memory releasing for now.
.destroy(Scoped_payload);
.destroy!false(Scoped_payload);
}
}

Expand All @@ -8310,10 +8293,7 @@ if (is(T == class))
import core.lifetime : emplace, forward;

Scoped result = void;
void* alignedStore = cast(void*) aligned(cast(size_t) result.Scoped_store.ptr);
immutable size_t d = alignedStore - result.Scoped_store.ptr;
*cast(size_t*) &result.Scoped_store[$ - size_t.sizeof] = d;
emplace!(Unqual!T)(result.Scoped_store[d .. $ - size_t.sizeof], forward!args);
emplace!(Unqual!T)(result.buffer, forward!args);
return result;
}
}
Expand Down Expand Up @@ -8400,13 +8380,6 @@ if (is(T == class))
destroy(*b2); // calls A's destructor for b2.a
}

private size_t _alignUp(size_t alignment)(size_t n)
if (alignment > 0 && !((alignment - 1) & alignment))
{
enum badEnd = alignment - 1; // 0b11, 0b111, ...
return (n + badEnd) & ~badEnd;
}

// https://issues.dlang.org/show_bug.cgi?id=6580 testcase
@system unittest
{
Expand Down

0 comments on commit 0d49960

Please sign in to comment.