On Tuesday, 26 January 2021 at 18:07:06 UTC, ludo wrote:
Hi guys,
still working on old D1 code, to be updated to D2. At some
point the previous dev wrote a FastLock class. The top comment
is from the dev himself, not me. My question is after the code.
---
class FastLock
{
protected Mutex mutex;
protected int lockCount;
protected Thread owner;
///
this()
{ mutex = new Mutex();
}
/**
* This works the same as Tango's Mutex's lock()/unlock except
provides extra performance in the special case where
* a thread calls lock()/unlock() multiple times while it
already has ownership from a previous call to lock().
* This is a common case in Yage.
*
* For convenience, lock() and unlock() calls may be nested.
Subsequent lock() calls will still maintain the lock,
* but unlocking will only occur after unlock() has been
called an equal number of times.
*
* On Windows, Tango's lock() is always faster than D's
synchronized statement. */
void lock()
{ auto self = Thread.getThis();
if (self !is owner)
{ mutex.lock();
owner = self;
}
lockCount++;
}
void unlock() /// ditto
{ assert(Thread.getThis() is owner);
lockCount--;
if (!lockCount)
{ owner = null;
mutex.unlock();
}
}
}
---
Now if I look at the doc , in particular Class
core.sync.mutex.Mutex, I see:
---
lock () If this lock is not already held by the caller, the
lock is acquired, then the internal counter is incremented by
one.
--
Which looks exactly like the behavior of "fastLock". Is it so
that the old Tango's mutex lock was not keeping count and would
lock the same object several time? Do we agree that the
FastLock class is obsolete considering current D core?
cheers
That code isn't thread safe at all (assuming FastLock is used
from several threads). lockCount isn't atomic which means the
code will not work with several threads. Also the assignment of
the variable owner isn't thread safe. As soon you start to
include more that one supposedly atomic assignment in
synchronization primitives, things quickly get out of hand.
Normal D Mutex uses pthread_mutex on Linux and the usual
CriticalSection stuff on Windows. Neither is particularly fast.
Futex on Linux isn't exactly super fast either. Synchronization
primitives aren't exactly fast on any system because that's how
it is. There are ways to makes things faster but adding stuff
like timeouts and the complexity goes exponential. There so many
pitfalls with synchronization primitives that it is hardly worth
it making your own.