From 5e89ac4e918259afea48aa925bf9c6435674d92f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Wed, 2 Nov 2016 21:01:09 +0100 Subject: [PATCH] Safe-ify sync module. --- source/vibe/core/sync.d | 67 +++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/source/vibe/core/sync.d b/source/vibe/core/sync.d index 9f164a3..57c5da9 100644 --- a/source/vibe/core/sync.d +++ b/source/vibe/core/sync.d @@ -19,6 +19,23 @@ import std.stdio; import std.traits : ReturnType; +/** Creates a new signal that can be shared between fibers. +*/ +ManualEvent createManualEvent() +@safe { + return ManualEvent.init; +} +/// ditto +shared(ManualEvent) createSharedManualEvent() +@trusted { + return shared(ManualEvent).init; +} + +ScopedMutexLock!M scopedMutexLock(M : Mutex)(M mutex, LockMode mode = LockMode.lock) +{ + return ScopedMutexLock!M(mutex, mode); +} + enum LockMode { lock, tryLock, @@ -34,16 +51,16 @@ interface Lockable { /** RAII lock for the Mutex class. */ -struct ScopedMutexLock +struct ScopedMutexLock(M : Mutex = core.sync.mutex.Mutex) { @disable this(this); private { - Mutex m_mutex; + M m_mutex; bool m_locked; LockMode m_mode; } - this(core.sync.mutex.Mutex mutex, LockMode mode = LockMode.lock) { + this(M mutex, LockMode mode = LockMode.lock) { assert(mutex !is null); m_mutex = mutex; @@ -121,6 +138,8 @@ unittest { */ class LocalTaskSemaphore { +@safe: + // requires a queue import std.container.binaryheap; import std.container.array; @@ -190,7 +209,7 @@ class LocalTaskSemaphore if (++m_seq == uint.max) rewindSeq(); - m_waiters.insert(w); + () @trusted { m_waiters.insert(w); } (); do w.signal.wait(); while (!tryLock()); // on resume: destroy(w.signal); @@ -204,7 +223,7 @@ class LocalTaskSemaphore if (m_waiters.length > 0 && available > 0) { ThreadWaiter w = m_waiters.front(); w.signal.emit(); // resume one - m_waiters.removeFront(); + () @trusted { m_waiters.removeFront(); } (); } } @@ -225,7 +244,7 @@ class LocalTaskSemaphore } private void rewindSeq() - { + @trusted { Array!ThreadWaiter waiters = m_waiters.release(); ushort min_seq; import std.algorithm : min; @@ -257,6 +276,8 @@ class LocalTaskSemaphore See_Also: InterruptibleTaskMutex, RecursiveTaskMutex, core.sync.mutex.Mutex */ class TaskMutex : core.sync.mutex.Mutex, Lockable { +@safe: + private TaskMutexImpl!false m_impl; this(Object o) { m_impl.setup(); super(o); } @@ -271,16 +292,16 @@ unittest { auto mutex = new TaskMutex; { - auto lock = ScopedMutexLock(mutex); + auto lock = scopedMutexLock(mutex); assert(lock.locked); assert(mutex.m_impl.m_locked); - auto lock2 = ScopedMutexLock(mutex, LockMode.tryLock); + auto lock2 = scopedMutexLock(mutex, LockMode.tryLock); assert(!lock2.locked); } assert(!mutex.m_impl.m_locked); - auto lock = ScopedMutexLock(mutex, LockMode.tryLock); + auto lock = scopedMutexLock(mutex, LockMode.tryLock); assert(lock.locked); lock.unlock(); assert(!lock.locked); @@ -296,7 +317,7 @@ unittest { assert(!mutex.m_impl.m_locked); static if (__VERSION__ >= 2067) { - with(mutex.ScopedMutexLock) { + with(mutex.scopedMutexLock) { assert(mutex.m_impl.m_locked); } } @@ -356,6 +377,8 @@ unittest { See_Also: $(D TaskMutex), $(D InterruptibleRecursiveTaskMutex) */ final class InterruptibleTaskMutex : Lockable { +@safe: + private TaskMutexImpl!true m_impl; this() { m_impl.setup(); } @@ -390,6 +413,8 @@ unittest { See_Also: TaskMutex, core.sync.mutex.Mutex */ class RecursiveTaskMutex : core.sync.mutex.Mutex, Lockable { +@safe: + private RecursiveTaskMutexImpl!false m_impl; this(Object o) { m_impl.setup(); super(o); } @@ -416,6 +441,8 @@ unittest { See_Also: $(D RecursiveTaskMutex), $(D InterruptibleTaskMutex) */ final class InterruptibleRecursiveTaskMutex : Lockable { +@safe: + private RecursiveTaskMutexImpl!true m_impl; this() { m_impl.setup(); } @@ -551,6 +578,8 @@ private void runMutexUnitTests(M)() See_Also: InterruptibleTaskCondition */ class TaskCondition : core.sync.condition.Condition { +@safe: + private TaskConditionImpl!(false, Mutex) m_impl; this(core.sync.mutex.Mutex mtx) { @@ -625,6 +654,8 @@ unittest { See_Also: `TaskCondition` */ final class InterruptibleTaskCondition { +@safe: + private TaskConditionImpl!(true, Lockable) m_impl; this(core.sync.mutex.Mutex mtx) { m_impl.setup(mtx); } @@ -638,18 +669,6 @@ final class InterruptibleTaskCondition { } -/** Creates a new signal that can be shared between fibers. -*/ -ManualEvent createManualEvent() -{ - return ManualEvent.init; -} -/// ditto -shared(ManualEvent) createSharedManualEvent() -{ - return shared(ManualEvent).init; -} - /** A manually triggered cross-task event. Note: the ownership can be shared between multiple fibers and threads. @@ -897,7 +916,7 @@ struct ManualEvent { auto wnext = waiters.next; assert(wnext !is waiters); if (waiters.notifier !is null) { - logTrace("notify task %s %s %s", cast(void*)waiters, cast(void*)waiters.notifier.funcptr, waiters.notifier.ptr); + logTrace("notify task %s %s %s", cast(void*)waiters, () @trusted { return cast(void*)waiters.notifier.funcptr; } (), waiters.notifier.ptr); waiters.notifier(); waiters.notifier = null; } else logTrace("notify callback is null"); @@ -1607,6 +1626,8 @@ class TaskReadWriteMutex */ class InterruptibleTaskReadWriteMutex { + @safe: + private { alias State = ReadWriteMutexState!true; alias LockingIntent = State.LockingIntent;