Annotate more of Task/TaskLocal as safe.
This commit is contained in:
parent
d5e19e1db6
commit
0c3c31b969
|
@ -37,11 +37,15 @@ struct Task {
|
||||||
m_taskCounter = task_counter;
|
m_taskCounter = task_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
this(in Task other) nothrow { m_fiber = cast(shared(TaskFiber))other.m_fiber; m_taskCounter = other.m_taskCounter; }
|
this(in Task other)
|
||||||
|
@safe nothrow {
|
||||||
|
m_fiber = () @trusted { return cast(shared(TaskFiber))other.m_fiber; } ();
|
||||||
|
m_taskCounter = other.m_taskCounter;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the Task instance belonging to the calling task.
|
/** Returns the Task instance belonging to the calling task.
|
||||||
*/
|
*/
|
||||||
static Task getThis() nothrow @safe
|
static Task getThis() @safe nothrow
|
||||||
{
|
{
|
||||||
// In 2067, synchronized statements where annotated nothrow.
|
// In 2067, synchronized statements where annotated nothrow.
|
||||||
// DMD#4115, Druntime#1013, Druntime#1021, Phobos#2704
|
// DMD#4115, Druntime#1013, Druntime#1021, Phobos#2704
|
||||||
|
@ -73,16 +77,16 @@ struct Task {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this is not thread safe!
|
// FIXME: this is not thread safe!
|
||||||
@property ref ThreadInfo tidInfo() { return m_fiber ? taskFiber.tidInfo : s_tidInfo; }
|
@property ref ThreadInfo tidInfo() @safe { return m_fiber ? taskFiber.tidInfo : s_tidInfo; }
|
||||||
@property Tid tid() { return tidInfo.ident; }
|
@property Tid tid() @safe { return tidInfo.ident; }
|
||||||
}
|
}
|
||||||
|
|
||||||
T opCast(T)() const nothrow if (is(T == bool)) { return m_fiber !is null; }
|
T opCast(T)() const @safe nothrow if (is(T == bool)) { return m_fiber !is null; }
|
||||||
|
|
||||||
void join() { if (running) taskFiber.join(m_taskCounter); }
|
void join() @safe { if (running) taskFiber.join(m_taskCounter); }
|
||||||
void interrupt() { if (running) taskFiber.interrupt(m_taskCounter); }
|
void interrupt() @safe { if (running) taskFiber.interrupt(m_taskCounter); }
|
||||||
|
|
||||||
string toString() const { import std.string; return format("%s:%s", cast(void*)m_fiber, m_taskCounter); }
|
string toString() const @safe { import std.string; return format("%s:%s", () @trusted { return cast(void*)m_fiber; } (), m_taskCounter); }
|
||||||
|
|
||||||
void getDebugID(R)(ref R dst)
|
void getDebugID(R)(ref R dst)
|
||||||
{
|
{
|
||||||
|
@ -97,13 +101,13 @@ struct Task {
|
||||||
|
|
||||||
MD5 md;
|
MD5 md;
|
||||||
md.start();
|
md.start();
|
||||||
md.put(nativeToLittleEndian(cast(size_t)cast(void*)m_fiber));
|
md.put(nativeToLittleEndian(() @trusted { return cast(size_t)cast(void*)m_fiber; } ()));
|
||||||
md.put(nativeToLittleEndian(cast(size_t)cast(void*)m_taskCounter));
|
md.put(nativeToLittleEndian(m_taskCounter));
|
||||||
Base64.encode(md.finish()[0 .. 3], dst);
|
Base64.encode(md.finish()[0 .. 3], dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool opEquals(in ref Task other) const nothrow @safe { return m_fiber is other.m_fiber && m_taskCounter == other.m_taskCounter; }
|
bool opEquals(in ref Task other) const @safe nothrow { return m_fiber is other.m_fiber && m_taskCounter == other.m_taskCounter; }
|
||||||
bool opEquals(in Task other) const nothrow @safe { return m_fiber is other.m_fiber && m_taskCounter == other.m_taskCounter; }
|
bool opEquals(in Task other) const @safe nothrow { return m_fiber is other.m_fiber && m_taskCounter == other.m_taskCounter; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -159,7 +163,9 @@ struct TaskLocal(T)
|
||||||
void opAssign(T value) { this.storage = value; }
|
void opAssign(T value) { this.storage = value; }
|
||||||
|
|
||||||
@property ref T storage()
|
@property ref T storage()
|
||||||
{
|
@safe {
|
||||||
|
import std.conv : emplace;
|
||||||
|
|
||||||
auto fiber = TaskFiber.getThis();
|
auto fiber = TaskFiber.getThis();
|
||||||
|
|
||||||
// lazily register in FLS storage
|
// lazily register in FLS storage
|
||||||
|
@ -178,13 +184,13 @@ struct TaskLocal(T)
|
||||||
// make sure the current fiber has enough FLS storage
|
// make sure the current fiber has enough FLS storage
|
||||||
if (fiber.m_fls.length < TaskFiber.ms_flsFill) {
|
if (fiber.m_fls.length < TaskFiber.ms_flsFill) {
|
||||||
fiber.m_fls.length = TaskFiber.ms_flsFill + 128;
|
fiber.m_fls.length = TaskFiber.ms_flsFill + 128;
|
||||||
fiber.m_flsInit.length = TaskFiber.ms_flsCounter + 64;
|
() @trusted { fiber.m_flsInit.length = TaskFiber.ms_flsCounter + 64; } ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// return (possibly default initialized) value
|
// return (possibly default initialized) value
|
||||||
auto data = fiber.m_fls.ptr[m_offset .. m_offset+T.sizeof];
|
auto data = () @trusted { return fiber.m_fls.ptr[m_offset .. m_offset+T.sizeof]; } ();
|
||||||
if (!fiber.m_flsInit[m_id]) {
|
if (!() @trusted { return fiber.m_flsInit[m_id]; } ()) {
|
||||||
fiber.m_flsInit[m_id] = true;
|
() @trusted { fiber.m_flsInit[m_id] = true; } ();
|
||||||
import std.traits : hasElaborateDestructor, hasAliasing;
|
import std.traits : hasElaborateDestructor, hasAliasing;
|
||||||
static if (hasElaborateDestructor!T || hasAliasing!T) {
|
static if (hasElaborateDestructor!T || hasAliasing!T) {
|
||||||
void function(void[], size_t) destructor = (void[] fls, size_t offset){
|
void function(void[], size_t) destructor = (void[] fls, size_t offset){
|
||||||
|
@ -206,19 +212,19 @@ struct TaskLocal(T)
|
||||||
fls_info.offset = m_offset;
|
fls_info.offset = m_offset;
|
||||||
|
|
||||||
// make sure flsInfo has enough space
|
// make sure flsInfo has enough space
|
||||||
if (ms_flsInfo.length <= m_id)
|
if (TaskFiber.ms_flsInfo.length <= m_id)
|
||||||
ms_flsInfo.length = m_id + 64;
|
TaskFiber.ms_flsInfo.length = m_id + 64;
|
||||||
|
|
||||||
ms_flsInfo[m_id] = fls_info;
|
TaskFiber.ms_flsInfo[m_id] = fls_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_hasInitValue) {
|
if (m_hasInitValue) {
|
||||||
static if (__traits(compiles, emplace!T(data, m_initValue)))
|
static if (__traits(compiles, emplace!T(data, m_initValue)))
|
||||||
emplace!T(data, m_initValue);
|
() @trusted { emplace!T(data, m_initValue); } ();
|
||||||
else assert(false, "Cannot emplace initialization value for type "~T.stringof);
|
else assert(false, "Cannot emplace initialization value for type "~T.stringof);
|
||||||
} else emplace!T(data);
|
} else () @trusted { emplace!T(data); } ();
|
||||||
}
|
}
|
||||||
return (cast(T[])data)[0];
|
return *() @trusted { return cast(T*)data.ptr; } ();
|
||||||
}
|
}
|
||||||
|
|
||||||
alias storage this;
|
alias storage this;
|
||||||
|
@ -403,14 +409,14 @@ final package class TaskFiber : Fiber {
|
||||||
*/
|
*/
|
||||||
@property Task task() @safe nothrow { return Task(this, m_taskCounter); }
|
@property Task task() @safe nothrow { return Task(this, m_taskCounter); }
|
||||||
|
|
||||||
@property ref inout(ThreadInfo) tidInfo() inout nothrow { return m_tidInfo; }
|
@property ref inout(ThreadInfo) tidInfo() inout @safe nothrow { return m_tidInfo; }
|
||||||
|
|
||||||
@property size_t taskCounter() const { return m_taskCounter; }
|
@property size_t taskCounter() const @safe nothrow { return m_taskCounter; }
|
||||||
|
|
||||||
/** Blocks until the task has ended.
|
/** Blocks until the task has ended.
|
||||||
*/
|
*/
|
||||||
void join(size_t task_counter)
|
void join(size_t task_counter)
|
||||||
{
|
@safe {
|
||||||
while (m_running && m_taskCounter == task_counter)
|
while (m_running && m_taskCounter == task_counter)
|
||||||
m_onExit.wait();
|
m_onExit.wait();
|
||||||
}
|
}
|
||||||
|
@ -418,7 +424,7 @@ final package class TaskFiber : Fiber {
|
||||||
/** Throws an InterruptExeption within the task as soon as it calls an interruptible function.
|
/** Throws an InterruptExeption within the task as soon as it calls an interruptible function.
|
||||||
*/
|
*/
|
||||||
void interrupt(size_t task_counter)
|
void interrupt(size_t task_counter)
|
||||||
{
|
@safe {
|
||||||
import vibe.core.core : taskScheduler;
|
import vibe.core.core : taskScheduler;
|
||||||
|
|
||||||
if (m_taskCounter != task_counter)
|
if (m_taskCounter != task_counter)
|
||||||
|
@ -428,7 +434,7 @@ final package class TaskFiber : Fiber {
|
||||||
if (caller != Task.init) {
|
if (caller != Task.init) {
|
||||||
assert(caller != this.task, "A task cannot interrupt itself.");
|
assert(caller != this.task, "A task cannot interrupt itself.");
|
||||||
assert(caller.thread is this.thread, "Interrupting tasks in different threads is not yet supported.");
|
assert(caller.thread is this.thread, "Interrupting tasks in different threads is not yet supported.");
|
||||||
} else assert(Thread.getThis() is this.thread, "Interrupting tasks in different threads is not yet supported.");
|
} else assert(() @trusted { return Thread.getThis(); } () is this.thread, "Interrupting tasks in different threads is not yet supported.");
|
||||||
logTrace("Resuming task with interrupt flag.");
|
logTrace("Resuming task with interrupt flag.");
|
||||||
m_interrupt = true;
|
m_interrupt = true;
|
||||||
taskScheduler.switchTo(this.task);
|
taskScheduler.switchTo(this.task);
|
||||||
|
|
Loading…
Reference in a new issue