Fix FreeListRef related issues.

This commit is contained in:
Sönke Ludwig 2016-11-10 12:01:35 +01:00
parent 7dafccc3a7
commit ccbd6a063f
2 changed files with 30 additions and 17 deletions

View file

@ -1095,7 +1095,7 @@ struct Future(T) {
{ {
if (!ready) m_task.join(); if (!ready) m_task.join();
assert(ready, "Task still running after join()!?"); assert(ready, "Task still running after join()!?");
return *cast(T*)m_result.get(); // casting away shared is safe, because this is a unique reference return *cast(T*)&m_result.get(); // casting away shared is safe, because this is a unique reference
} }
alias getResult this; alias getResult this;
@ -1135,7 +1135,7 @@ Future!(ReturnType!CALLABLE) async(CALLABLE, ARGS...)(CALLABLE callable, ARGS ar
Future!RET ret; Future!RET ret;
ret.init(); ret.init();
static void compute(FreeListRef!(shared(RET)) dst, CALLABLE callable, ARGS args) { static void compute(FreeListRef!(shared(RET)) dst, CALLABLE callable, ARGS args) {
*dst = cast(shared(RET))callable(args); dst = cast(shared(RET))callable(args);
} }
static if (isWeaklyIsolated!CALLABLE && isWeaklyIsolated!ARGS) { static if (isWeaklyIsolated!CALLABLE && isWeaklyIsolated!ARGS) {
ret.m_task = runWorkerTaskH(&compute, ret.m_result, callable, args); ret.m_task = runWorkerTaskH(&compute, ret.m_result, callable, args);

View file

@ -44,15 +44,17 @@ struct FreeListObjectAlloc(T, bool USE_GC = true, bool INIT = true, EXTRA = void
auto ret = s_firstFree; auto ret = s_firstFree;
s_firstFree = s_firstFree.next; s_firstFree = s_firstFree.next;
ret.next = null; ret.next = null;
mem = (cast(void*)ret)[0 .. ElemSize]; mem = () @trusted { return (cast(void*)ret)[0 .. ElemSize]; } ();
} else { } else {
//logInfo("alloc %s/%d", T.stringof, ElemSize); //logInfo("alloc %s/%d", T.stringof, ElemSize);
mem = Mallocator.instance.allocate(ElemSlotSize); mem = Mallocator.instance.allocate(ElemSlotSize);
static if( hasIndirections!T ) GC.addRange(mem.ptr, ElemSlotSize); static if(hasIndirections!T) () @trusted { GC.addRange(mem.ptr, ElemSlotSize); } ();
} }
static if (INIT) return cast(TR)internalEmplace!(Unqual!T)(mem, args); // FIXME: this emplace has issues with qualified types, but Unqual!T may result in the wrong constructor getting called. // FIXME: this emplace has issues with qualified types, but Unqual!T may result in the wrong constructor getting called.
else return cast(TR)mem.ptr; static if (INIT) internalEmplace!(Unqual!T)(mem, args);
return () @trusted { return cast(TR)mem.ptr; } ();
} }
static void free(TR obj) static void free(TR obj)
@ -72,6 +74,11 @@ struct FreeListObjectAlloc(T, bool USE_GC = true, bool INIT = true, EXTRA = void
} }
} }
@safe unittest {
struct S {}
FreeListObjectAlloc!S.alloc();
}
template AllocSize(T) template AllocSize(T)
{ {
@ -99,7 +106,7 @@ struct FreeListRef(T, bool INIT = true)
private size_t m_magic = 0x1EE75817; // workaround for compiler bug private size_t m_magic = 0x1EE75817; // workaround for compiler bug
static FreeListRef opCall(ARGS...)(ARGS args) static FreeListRef opCall(ARGS...)(ARGS args)
{ @safe {
//logInfo("refalloc %s/%d", T.stringof, ElemSize); //logInfo("refalloc %s/%d", T.stringof, ElemSize);
FreeListRef ret; FreeListRef ret;
ret.m_object = ObjAlloc.alloc(args); ret.m_object = ObjAlloc.alloc(args);
@ -141,19 +148,23 @@ struct FreeListRef(T, bool INIT = true)
checkInvariants(); checkInvariants();
if (m_object) { if (m_object) {
if (--this.refCount == 0) if (--this.refCount == 0)
ObjAlloc.free(m_object); () @trusted { ObjAlloc.free(m_object); } ();
} }
m_object = null; m_object = null;
m_magic = 0x1EE75817; m_magic = 0x1EE75817;
} }
@property const(TR) get() const { checkInvariants(); return m_object; } static if (is(T == class)) {
@property TR get() { checkInvariants(); return m_object; } @property inout(T) get() inout @safe nothrow { return m_object; }
} else {
@property ref inout(T) get() inout @safe nothrow { return *m_object; }
void opAssign(T t) { *m_object = t; }
}
alias get this; alias get this;
private @property ref int refCount() private @property ref int refCount()
const { const @trusted {
auto ptr = cast(ubyte*)cast(void*)m_object; auto ptr = cast(ubyte*)cast(void*)m_object;
ptr += ElemSize; ptr += ElemSize;
return *cast(int*)ptr; return *cast(int*)ptr;
@ -180,13 +191,15 @@ in {
} body { } body {
enum classSize = __traits(classInstanceSize, T); enum classSize = __traits(classInstanceSize, T);
auto result = cast(T) chunk.ptr; auto result = () @trusted { return cast(T) chunk.ptr; } ();
// Initialize the object in its pre-ctor state // Initialize the object in its pre-ctor state
static if (__VERSION__ < 2071) () @trusted {
chunk[0 .. classSize] = typeid(T).init[]; static if (__VERSION__ < 2071)
else chunk[0 .. classSize] = typeid(T).init[];
chunk[0 .. classSize] = typeid(T).initializer[]; // Avoid deprecation warning else
chunk[0 .. classSize] = typeid(T).initializer[]; // Avoid deprecation warning
} ();
// Call the ctor if any // Call the ctor if any
static if (is(typeof(result.__ctor(args)))) static if (is(typeof(result.__ctor(args))))
@ -216,7 +229,7 @@ in {
format("emplace: Misaligned memory block (0x%X): it must be %s-byte aligned for type %s", chunk.ptr, T.alignof, T.stringof)); format("emplace: Misaligned memory block (0x%X): it must be %s-byte aligned for type %s", chunk.ptr, T.alignof, T.stringof));
} body { } body {
return emplace(cast(T*)chunk.ptr, args); return emplace(() @trusted { return cast(T*)chunk.ptr; } (), args);
} }
private void logDebug_(ARGS...)(string msg, ARGS args) {} private void logDebug_(ARGS...)(string msg, ARGS args) {}