Add a trap to detect invalid uses of InterruptibleTaskMutex in conjunction with synchronized.
This commit is contained in:
parent
ea4917d4d0
commit
ffa5bd5c58
|
@ -274,7 +274,6 @@ final class LocalTaskSemaphore
|
||||||
*/
|
*/
|
||||||
final class TaskMutex : core.sync.mutex.Mutex, Lockable {
|
final class TaskMutex : core.sync.mutex.Mutex, Lockable {
|
||||||
@safe:
|
@safe:
|
||||||
|
|
||||||
private TaskMutexImpl!false m_impl;
|
private TaskMutexImpl!false m_impl;
|
||||||
|
|
||||||
this(Object o) { m_impl.setup(); super(o); }
|
this(Object o) { m_impl.setup(); super(o); }
|
||||||
|
@ -376,7 +375,13 @@ final class InterruptibleTaskMutex : Lockable {
|
||||||
|
|
||||||
private TaskMutexImpl!true m_impl;
|
private TaskMutexImpl!true m_impl;
|
||||||
|
|
||||||
this() { m_impl.setup(); }
|
this()
|
||||||
|
{
|
||||||
|
m_impl.setup();
|
||||||
|
|
||||||
|
// detects invalid usage within synchronized(...)
|
||||||
|
() @trusted { this.__monitor = cast(void*)&NoUseMonitor.instance(); } ();
|
||||||
|
}
|
||||||
|
|
||||||
bool tryLock() nothrow { return m_impl.tryLock(); }
|
bool tryLock() nothrow { return m_impl.tryLock(); }
|
||||||
void lock() { m_impl.lock(); }
|
void lock() { m_impl.lock(); }
|
||||||
|
@ -437,10 +442,15 @@ unittest {
|
||||||
*/
|
*/
|
||||||
final class InterruptibleRecursiveTaskMutex : Lockable {
|
final class InterruptibleRecursiveTaskMutex : Lockable {
|
||||||
@safe:
|
@safe:
|
||||||
|
|
||||||
private RecursiveTaskMutexImpl!true m_impl;
|
private RecursiveTaskMutexImpl!true m_impl;
|
||||||
|
|
||||||
this() { m_impl.setup(); }
|
this()
|
||||||
|
{
|
||||||
|
m_impl.setup();
|
||||||
|
|
||||||
|
// detects invalid usage within synchronized(...)
|
||||||
|
() @trusted { this.__monitor = cast(void*)&NoUseMonitor.instance(); } ();
|
||||||
|
}
|
||||||
|
|
||||||
bool tryLock() { return m_impl.tryLock(); }
|
bool tryLock() { return m_impl.tryLock(); }
|
||||||
void lock() { m_impl.lock(); }
|
void lock() { m_impl.lock(); }
|
||||||
|
@ -453,6 +463,39 @@ unittest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Helper class to ensure that the non Object.Monitor compatible interruptible
|
||||||
|
// mutex classes are not accidentally used with the `synchronized` statement
|
||||||
|
private final class NoUseMonitor : Object.Monitor {
|
||||||
|
private static shared Proxy st_instance;
|
||||||
|
|
||||||
|
static struct Proxy {
|
||||||
|
Object.Monitor monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static @property ref shared(Proxy) instance()
|
||||||
|
@safe nothrow {
|
||||||
|
static shared(Proxy)* inst = null;
|
||||||
|
if (inst) return *inst;
|
||||||
|
|
||||||
|
() @trusted { // synchronized {} not @safe for DMD <= 2.078.3
|
||||||
|
synchronized {
|
||||||
|
if (!st_instance.monitor)
|
||||||
|
st_instance.monitor = new shared NoUseMonitor;
|
||||||
|
inst = &st_instance;
|
||||||
|
}
|
||||||
|
} ();
|
||||||
|
|
||||||
|
return *inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
override void lock() @safe @nogc nothrow {
|
||||||
|
assert(false, "Interruptible task mutexes cannot be used with synchronized(), use scopedMutexLock instead.");
|
||||||
|
}
|
||||||
|
|
||||||
|
override void unlock() @safe @nogc nothrow {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void runMutexUnitTests(M)()
|
private void runMutexUnitTests(M)()
|
||||||
{
|
{
|
||||||
import vibe.core.core;
|
import vibe.core.core;
|
||||||
|
|
Loading…
Reference in a new issue